summaryrefslogtreecommitdiff
path: root/apps/graphics
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-12-05 14:52:18 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-12-05 14:52:18 -0600
commit9a5cdd2c15b76c8e18370424fe0cc58c1f400f0d (patch)
tree93bfa0c4f617d8b1feb6f2733516efe9395a5d18 /apps/graphics
parente340b784cc39934935a5267a91f34e7443f2d21c (diff)
downloadnuttx-9a5cdd2c15b76c8e18370424fe0cc58c1f400f0d.tar.gz
nuttx-9a5cdd2c15b76c8e18370424fe0cc58c1f400f0d.tar.bz2
nuttx-9a5cdd2c15b76c8e18370424fe0cc58c1f400f0d.zip
Add fourth of several ray cast/rendering files
Diffstat (limited to 'apps/graphics')
-rw-r--r--apps/graphics/traveler/Makefile4
-rw-r--r--apps/graphics/traveler/include/trv_doors.h26
-rw-r--r--apps/graphics/traveler/include/trv_raycast.h2
-rw-r--r--apps/graphics/traveler/include/trv_rayprune.h8
-rw-r--r--apps/graphics/traveler/src/trv_doors.c34
-rw-r--r--apps/graphics/traveler/src/trv_rayavoid.c2
-rw-r--r--apps/graphics/traveler/src/trv_raycast.c1405
7 files changed, 1453 insertions, 28 deletions
diff --git a/apps/graphics/traveler/Makefile b/apps/graphics/traveler/Makefile
index 9fe4d5b34..d927fd18e 100644
--- a/apps/graphics/traveler/Makefile
+++ b/apps/graphics/traveler/Makefile
@@ -47,8 +47,8 @@ STACKSIZE = 2048
ASRCS =
CSRCS = trv_bitmaps.c trv_color.c trv_doors.c trv_graphics.c trv_input.c
-CSRCS += trv_mem.c trv_plane.c trv_pov.c trv_rayavoid.c trv_raycntl.c
-CSRCS += trv_rayrend.c trv_trigtbl.c
+CSRCS += trv_mem.c trv_plane.c trv_pov.c trv_rayavoid.c trv_raycast.c
+CSRCS += trv_raycntl.c trv_rayrend.c trv_trigtbl.c
MAINSRC = trv_main.c
ifeq ($(CONFIG_NX),y)
diff --git a/apps/graphics/traveler/include/trv_doors.h b/apps/graphics/traveler/include/trv_doors.h
index 9179e2979..33499a656 100644
--- a/apps/graphics/traveler/include/trv_doors.h
+++ b/apps/graphics/traveler/include/trv_doors.h
@@ -43,6 +43,32 @@
#include "trv_types.h"
/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* This structure describes the characteristics of the door which currently
+ * being opened.
+ */
+
+struct trv_opendoor_s
+{
+ FAR struct trv_rect_data_s *rect; /* Points to the current door rectangle */
+ uint8_t state; /* State of the door being opened */
+ trv_coord_t zbottom; /* Z-Coordinate of the bottom of the door */
+ trv_coord_t zdist; /* Distance which the door has moved */
+ int16_t clock; /* This is clock which counts down the time
+ * remaining to keep the door open */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* This structure describes the door which is currently opening */
+
+struct trv_opendoor_s g_opendoor;
+
+/****************************************************************************
* Public Function Prototypes
****************************************************************************/
diff --git a/apps/graphics/traveler/include/trv_raycast.h b/apps/graphics/traveler/include/trv_raycast.h
index dbc53cf8f..c48d1fca0 100644
--- a/apps/graphics/traveler/include/trv_raycast.h
+++ b/apps/graphics/traveler/include/trv_raycast.h
@@ -163,7 +163,7 @@ extern struct trv_camera_s g_camera;
* Public Function Prototypes
****************************************************************************/
-void trv_raycast(int16_t pitchangle, int16_t yawangle, int16_t screenyaw,
+void trv_raycast(int16_t pitch, int16_t yaw, int16_t screenyaw,
FAR struct trv_raycast_s *result);
#endif /* __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYCAST_H */
diff --git a/apps/graphics/traveler/include/trv_rayprune.h b/apps/graphics/traveler/include/trv_rayprune.h
index 4dd0d40cb..ec35805e1 100644
--- a/apps/graphics/traveler/include/trv_rayprune.h
+++ b/apps/graphics/traveler/include/trv_rayprune.h
@@ -43,6 +43,14 @@
#include "trv_types.h"
/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+extern struct trv_rect_head_s g_ray_xplane; /* List of X=plane rectangles */
+extern struct trv_rect_head_s g_ray_yplane; /* List of Y=plane rectangles */
+extern struct trv_rect_head_s g_ray_zplane; /* List of Z=plane rectangles */
+
+/****************************************************************************
* Public Function Prototypes
****************************************************************************/
diff --git a/apps/graphics/traveler/src/trv_doors.c b/apps/graphics/traveler/src/trv_doors.c
index 573beaea3..3fe3785e0 100644
--- a/apps/graphics/traveler/src/trv_doors.c
+++ b/apps/graphics/traveler/src/trv_doors.c
@@ -69,20 +69,6 @@ enum trv_door_state_e
DOOR_CLOSING, /* A door is closing */
};
-/* This structure describes the characteristics of the door which currently
- * being opened.
- */
-
-struct trv_opendoor_s
-{
- FAR struct trv_rect_data_s *rect; /* Points to the current door rectangle */
- uint8_t state; /* State of the door being opened */
- trv_coord_t zbottom; /* Z-Coordinate of the bottom of the door */
- trv_coord_t zdistance; /* Distance which the door has moved */
- int16_t clock; /* This is clock which counts down the time
- * remaining to keep the door open */
-};
-
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -146,10 +132,10 @@ static void trv_door_startopen (void)
* in motion
*/
- g_opendoor.rect = rect;
- g_opendoor.state = DOOR_OPENING;
- g_opendoor.zbottom = rect->vstart;
- g_opendoor.zdistance = 0;
+ g_opendoor.rect = rect;
+ g_opendoor.state = DOOR_OPENING;
+ g_opendoor.zbottom = rect->vstart;
+ g_opendoor.zdist = 0;
/* Mark the door's attribute to indicate that it is in motion */
@@ -176,8 +162,8 @@ static void trv_door_animation(void)
/* Raise the door a little */
- g_opendoor.zbottom += DOOR_ZSTEP;
- g_opendoor.zdistance += DOOR_ZSTEP;
+ g_opendoor.zbottom += DOOR_ZSTEP;
+ g_opendoor.zdist += DOOR_ZSTEP;
/* When the bottom of the door is above the player's head, we will
* say that the door is open
@@ -195,7 +181,7 @@ static void trv_door_animation(void)
/* Make sure that the door does not open wider than it is tall */
g_opendoor.zbottom = g_opendoor.rect->vend;
- g_opendoor.zdistance = g_opendoor.rect->vend - g_opendoor.rect->vstart;
+ g_opendoor.zdist = g_opendoor.rect->vend - g_opendoor.rect->vstart;
/* The door is done opening, the next state is the DOOR_OPEN state
* where we will hold the door open a while
@@ -229,7 +215,7 @@ static void trv_door_animation(void)
/* Lower the door a little */
g_opendoor.zbottom -= DOOR_ZSTEP;
- g_opendoor.zdistance -= DOOR_ZSTEP;
+ g_opendoor.zdist -= DOOR_ZSTEP;
/* When the bottom of the door is below the player's head, we
* will say that the door is closed
@@ -248,7 +234,7 @@ static void trv_door_animation(void)
/* Lower the door a little */
g_opendoor.zbottom -= DOOR_ZSTEP;
- g_opendoor.zdistance -= DOOR_ZSTEP;
+ g_opendoor.zdist -= DOOR_ZSTEP;
/* When the bottom of the door is below the player's head, we will
* say that the door is closed
@@ -261,7 +247,7 @@ static void trv_door_animation(void)
/* Check if the door is fully closed */
- if (g_opendoor.zdistance <= 0)
+ if (g_opendoor.zdist <= 0)
{
/* Indicate that the door is no longer in motion */
diff --git a/apps/graphics/traveler/src/trv_rayavoid.c b/apps/graphics/traveler/src/trv_rayavoid.c
index 6fc04ddf2..cfdccf828 100644
--- a/apps/graphics/traveler/src/trv_rayavoid.c
+++ b/apps/graphics/traveler/src/trv_rayavoid.c
@@ -576,7 +576,7 @@ trv_coord_t trv_rayclip_player_ymotion(FAR struct trv_camera_s *pov,
* Make sure that the player is standing on something!
*
****************************************************************************/
-
+
trv_coord_t trv_ray_adjust_zpos(FAR struct trv_camera_s *pov,
trv_coord_t height)
{
diff --git a/apps/graphics/traveler/src/trv_raycast.c b/apps/graphics/traveler/src/trv_raycast.c
new file mode 100644
index 000000000..96f81748e
--- /dev/null
+++ b/apps/graphics/traveler/src/trv_raycast.c
@@ -0,0 +1,1405 @@
+/*******************************************************************************
+ * apps/graphics/traveler/src/trv_bitmaps.c
+ * This file contains the low-level ray casting logic
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included files
+ ****************************************************************************/
+
+#include "trv_types.h"
+#include "trv_world.h"
+#include "trv_doors.h"
+#include "trv_plane.h"
+#include "trv_bitmaps.h"
+#include "trv_trigtbl.h"
+#include "trv_rayrend.h"
+#include "trv_rayprune.h"
+#include "trv_raycast.h"
+
+/****************************************************************************
+ * Compilation switches
+ ****************************************************************************/
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* The following switch enables view correction logic. */
+
+#define ENABLE_VIEW_CORRECTION 1
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void trv_ray_xcaster14(FAR struct trv_raycast_s *result);
+static void trv_ray_xcaster23(FAR struct trv_raycast_s *result);
+static void trv_ray_ycaster12(FAR struct trv_raycast_s *result);
+static void trv_ray_ycaster34(FAR struct trv_raycast_s *result);
+static void trv_ray_zcasteru(FAR struct trv_raycast_s *result);
+static void trv_ray_zcasterl(FAR struct trv_raycast_s *result);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The following are the tangent and the cotangent of the pitch angle
+ * adjusted for the viewing yaw angle so that the view is correct for the
+ * "fish eye" effect which results from the projection of the polar ray cast
+ * onto the flat display
+ */
+
+static int32_t g_adj_tanpitch;
+static int32_t g_adj_cotpitch;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_ray_xcaster14
+ *
+ * Description:
+ * This function casts a ray along the Y-Axis looking at points of
+ * intersection on the X-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "right" half of the view, then the X ray cast will
+ * proceed in a positive along the X axis and that all possible X-axis
+ * intersections will occur to at the "left" of a cell.
+ *
+ * NOTE: The X-Ray caster must run first because it initializes a
+ * data structure needed by both the Y and Z ray casters.
+ *
+ ***************************************************************************/
+
+static void trv_ray_xcaster14(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current X plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t relx; /* Relative position of the X plane */
+ trv_coord_t absy; /* Absolute Y position at relx given yaw */
+ trv_coord_t absz; /* Absolute Z position at relx given pitch */
+ trv_coord_t lastrelx1 = -1; /* Last relative X position processed */
+ trv_coord_t lastrelx2 = -1; /* Last relative X position processed */
+ int32_t dydx; /* Rate of change of Y wrt X (double) */
+ int32_t dzdx; /* Rate of change of Z wrt X (double) */
+
+ /* At a viewing angle of 270 degrees, no intersections with the g_ray_xplanes
+ * are possible!
+ */
+
+ if (g_camera.yaw == ANGLE_270)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of Y and Z with respect to X */
+ /* The tangent is equal to the rate of change of Y with respect to the
+ * X-axis. The tangent is stored at double the "normal" scaling.
+ */
+
+ dydx = TAN(g_camera.yaw);
+
+ /* Determine the rate of change of the Z with respect to X. The tangent is
+ * "double" precision; the secant is "double" precision. dzdx will be
+ * retained as "double" precision.
+ */
+
+ dzdx = qTOd(g_adj_tanpitch * ABS(g_sec_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in the X plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_xplane.head; list; list = list->flink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "beyond" the current camera
+ * position
+ */
+
+ if (rect->plane > g_camera.x)
+ {
+ /* get the X distance to the plane */
+
+ relx = rect->plane - g_camera.x;
+
+#if 0
+ /* g_ray_xplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (relx > result->xdist)
+ {
+ return;
+ }
+#endif
+
+ /* Calculate the Y position at this relative X position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relx != lastrelx1)
+ {
+ int32_t deltay; /* Scale == "triple" */
+
+ /* The dydx is stored at double the"normal" scaling -- so
+ * deltay is "triple" precision
+ */
+
+ deltay = dydx * ((int32_t) relx);
+ absy = tTOs(deltay) + g_camera.y; /* back to "single" */
+ lastrelx1 = relx;
+ }
+
+ /* Check if this Y position intersects the rectangle */
+
+ if (absy >= rect->hstart && absy <= rect->hend)
+ {
+ /* The Y position lies in the rectangle. Now, calculate the
+ * theZ position at this relative X position. We can skip
+ * this step if we are processing another rectangle at the
+ * same relx distance.
+ */
+
+ if (relx != lastrelx2)
+ {
+ int32_t deltaz; /* Scale == TRIPLE */
+
+ /* The dzdx is stored at double the"normal" scaling -- so
+ * deltaz is "triple" precision
+ */
+
+ deltaz = dzdx * ((int32_t) relx);
+ absz = tTOs(deltaz) + g_camera.z; /* Back to single */
+ lastrelx2 = relx;
+ }
+
+ /* Check if this Z position intersects the rectangle */
+
+ if (absz >= rect->vstart && absz <= rect->vend)
+ {
+ /* We've got a potential hit, let's see what it is */
+ /* Check if we just hit an ordinary opaque wall */
+
+ if (IS_NORMAL(rect))
+ {
+ /* Yes..Save the parameters associated with the normal
+ * wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ else if (IS_DOOR(rect))
+ {
+ /* Check if the door is in motion. */
+
+ if (!IS_MOVING_DOOR(rect))
+ {
+ /* Save the parameters associated with the normal
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+
+ /* The door is in motion, the Z-position to see if we can
+ * see under the door
+ */
+
+ else if (absz > g_opendoor.zbottom)
+ {
+ /* Save the parameters associated with the moving
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz - g_opendoor.zdist;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ }
+
+ /* Otherwise, it must be a transparent wall. We'll need to
+ * make our decision based upon the pixel that we hit
+ */
+
+ /* Check if the pixel at this location is visible */
+
+ else if (GET_FRONT_PIXEL(rect, absy, absz) != INVISIBLE_PIXEL)
+ {
+ /* Its visible, save the parameters associated with the
+ * transparent wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_ray_xcaster23
+ *
+ * Description:
+ * This function casts a ray along the Y-Axis looking at points of
+ * intersection on the X-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "left" half of the view, then the X ray cast will
+ * proceed in a negative along the X axis and that all possible X-axis
+ * intersections will occur on the "right" of a cell.
+ *
+ * NOTE: The X-Ray caster must run first because it initializes a
+ * data structure needed by both the Y and Z ray casters.
+ *
+ ***************************************************************************/
+
+static void trv_ray_xcaster23(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current X plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t relx; /* Relative position of the X plane */
+ trv_coord_t absy; /* Absolute Y position at relx given yaw */
+ trv_coord_t absz; /* Absolute Z position at relx given pitch */
+ trv_coord_t lastrelx1 = -1; /* Last relative X position processed */
+ trv_coord_t lastrelx2 = -1; /* Last relative X position processed */
+ int32_t dydx; /* Rate of change of Y wrt X (double) */
+ int32_t dzdx; /* Rate of change of Z wrt X (double) */
+
+ /* At a view angle of 90 degrees, no intersections with the g_ray_xplanes are
+ * possible!
+ */
+
+ if (g_camera.yaw == ANGLE_90)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of Y and Z with respect to X */
+ /* The negative tangent is equal to the rate of change of Y with respect
+ * to the X-axis. The tangent is stored at double the "normal" scaling.
+ */
+
+ dydx = -TAN(g_camera.yaw);
+
+ /* Determine the rate of change of the Z with respect to X. dydx is
+ * "double" precision; the secant is "double" precision. dzdx will be
+ * retained as "double" precision.
+ */
+
+ dzdx = qTOd(g_adj_tanpitch * ABS(g_sec_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in the X plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_xplane.tail; list; list = list->blink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "before" the current camera
+ * position
+ */
+
+ if (rect->plane < g_camera.x)
+ {
+ /* get the X distance to the plane */
+
+ relx = g_camera.x - rect->plane;
+#if 0
+ /* g_ray_xplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (relx > result->xdist)
+ {
+ return;
+ }
+#endif
+
+ /* Calculate the Y position at this relative X position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relx != lastrelx1)
+ {
+ int32_t deltay; /* Scale == "triple" */
+
+ /* The dydx is stored at double the"normal" scaling -- so deltay
+ * is "triple" precision
+ */
+
+ deltay = dydx * ((int32_t) relx);
+ absy = tTOs(deltay) + g_camera.y; /* back to "single" */
+ lastrelx1 = relx;
+ }
+
+ /* Check if this Y position intersects the rectangle */
+
+ if (absy >= rect->hstart && absy <= rect->hend)
+ {
+ /* The Y position lies in the rectangle. Now, calculate the
+ * Z position at this relative X position. We can skip this
+ * step if we are processing another rectangle at the same
+ * relx distance.
+ */
+
+ if (relx != lastrelx2)
+ {
+ int32_t deltaz; /* Scale == TRIPLE */
+
+ /* The dzdx is stored at double the"normal" scaling -- so
+ * deltaz is "triple" precision
+ */
+
+ deltaz = dzdx * ((int32_t) relx);
+ absz = tTOs(deltaz) + g_camera.z; /* Back to single */
+ lastrelx2 = relx;
+ }
+
+ /* Check if this Z position intersects the rectangle */
+
+ if (absz >= rect->vstart && absz <= rect->vend)
+ {
+ /* We've got a potential hit, let's see what it is */
+ /* Check if we just hit an ordinary opaque wall */
+
+ if (IS_NORMAL(rect))
+ {
+ /* Yes..Save the parameters associated with the normal
+ * wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ else if (IS_DOOR(rect))
+ {
+ /* Check if the door is in motion. */
+
+ if (!IS_MOVING_DOOR(rect))
+ {
+ /* Save the parameters associated with the normal
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+
+ /* The door is in motion, the Z-position to see if we can
+ * see under the door
+ */
+
+ else if (absz > g_opendoor.zbottom)
+ {
+ /* Save the parameters associated with the moving
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz - g_opendoor.zdist;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ }
+
+ /* Otherwise, it must be a transparent wall. We'll need to
+ * make our decision based upon the pixel that we hit
+ */
+
+ /* Check if the pixel at this location is visible */
+
+ else if (GET_BACK_PIXEL(rect, absy, absz) != INVISIBLE_PIXEL)
+ {
+ /* Its visible, save the parameters associated with the
+ * transparent wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, X_HIT);
+ result->xpos = absy;
+ result->ypos = absz;
+
+ result->xdist = relx;
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate X casting */
+
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_ray_ycaster12
+ *
+ * Description:
+ * This function casts a ray along the X-Axis looking at points of
+ * intersection on the Y-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "forward" half of the view, then the Y ray cast will
+ * proceed in a positive along the Y axis and that all possible Y-axis
+ * intersections will occur on the "front" of a cell.
+ *
+ * NOTE: The X-Ray is assumed to have been performed first!
+ *
+ ***************************************************************************/
+
+static void trv_ray_ycaster12(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current P plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t rely; /* Relative position of the Y plane */
+ trv_coord_t absx; /* Absolute X position at rely given yaw */
+ trv_coord_t absz; /* Absolute Z position at rely given pitch */
+ trv_coord_t lastrely1 = -1; /* Last relative Y position processed */
+ trv_coord_t lastrely2 = -1; /* Last relative Y position processed */
+ int32_t dxdy; /* Rate of change of X wrt Y (double) */
+ int32_t dzdy; /* Rate of change of Z wrt Y (double) */
+
+ /* At a viewing angle of 0 degrees, no intersections with the g_ray_yplane is
+ * possible!
+ */
+
+ if (g_camera.yaw == ANGLE_0)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of X and Z with respect to Y */
+ /* The inverted tangent is equal to the rate of change of X with respect to
+ * the Y-axis. The cotangent is stored at double the the "normal" scaling.
+ */
+
+ dxdy = g_cot_table(g_camera.yaw);
+
+ /* Determine the rate of change of the Z with respect to Y. The tangent
+ * is "double" precision; the cosecant is "double" precision. dzdy will
+ * be retained as "double" precision.
+ */
+
+ dzdy = qTOd(g_adj_tanpitch * ABS(g_csc_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in a Y plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_yplane.head; list; list = list->flink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "beyond" the current camera
+ * position
+ */
+
+ if (rect->plane > g_camera.y)
+ {
+ /* get the Y distance to the plane */
+
+ rely = rect->plane - g_camera.y;
+
+ /* g_ray_yplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (rely > result->ydist)
+ {
+ return;
+ }
+
+ /* Calculate the Y position at this relative X position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (rely != lastrely1)
+ {
+ int32_t deltax; /* Scale == "triple" */
+
+ /* The dxdy is stored at double the"normal" scaling -- so deltax
+ * is "triple" precision
+ */
+
+ deltax = dxdy * ((int32_t) rely);
+ absx = tTOs(deltax) + g_camera.x; /* back to "single" */
+ lastrely1 = rely;
+ }
+
+ /* Check if this X position intersects the rectangle */
+
+ if (absx >= rect->hstart && absx <= rect->hend)
+ {
+ /* The X position lies in the rectangle. Now, calculate the the
+ * Z position at this relative X position. We can skip this step
+ * if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (rely != lastrely2)
+ {
+ int32_t deltaz; /* Scale == TRIPLE */
+
+ /* The dzdy is stored at double the"normal" scaling -- so
+ * deltaz is "triple" precision
+ */
+
+ deltaz = dzdy * ((int32_t) rely);
+ absz = tTOs(deltaz) + g_camera.z; /* Back to single */
+ lastrely2 = rely;
+ }
+
+ /* Check if this Z position intersects the rectangle */
+
+ if (absz >= rect->vstart && absz <= rect->vend)
+ {
+ /* We've got a potential hit, let's see what it is */
+ /* Check if we just hit an ordinary opaque wall */
+
+ if (IS_NORMAL(rect))
+ {
+ /* Yes..Save the parameters associated with the normal
+ * wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ else if (IS_DOOR(rect))
+ {
+ /* Check if the door is in motion. */
+
+ if (!IS_MOVING_DOOR(rect))
+ {
+ /* Save the parameters associated with the normal
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+
+ /* The door is in motion, the Z-position to see if we can
+ * see under the door
+ */
+
+ else if (absz > g_opendoor.zbottom)
+ {
+ /* Save the parameters associated with the moving
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz - g_opendoor.zdist;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ }
+
+ /* Otherwise, it must be a transparent wall. We'll need to
+ * make our decision based upon the pixel that we hit
+ */
+
+ /* Check if the pixel at this location is visible */
+
+ else if (GET_FRONT_PIXEL(rect, absx, absz) != INVISIBLE_PIXEL)
+ {
+ /* Its visible, save the parameters associated with the
+ * transparent wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_ray_ycaster34
+ *
+ * Description:
+ * This function casts a ray along the X-Axis looking at points of
+ * intersection on the Y-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "back" half of the view, then the Y ray cast will
+ * proceed in a negative along the Y axis and that all possible Y-axis
+ * intersections will occur on the "back" of a cell.
+ *
+ * NOTE: The X-Ray is assumed to have been performed first!
+ *
+ ***************************************************************************/
+
+static void trv_ray_ycaster34(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current P plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t rely; /* Relative position of the Y plane */
+ trv_coord_t absx; /* Absolute X position at rely given yaw */
+ trv_coord_t absz; /* Absolute Z position at rely given pitch */
+ trv_coord_t lastrely1 = -1; /* Last relative Y position processed */
+ trv_coord_t lastrely2 = -1; /* Last relative Y position processed */
+ int32_t dxdy; /* Rate of change of X wrt Y (double) */
+ int32_t dzdy; /* Rate of change of Z wrt Y (double) */
+
+ /* At a viewing angle of 180 degrees, no intersections with the line x = bXi
+ * are possible!
+ */
+
+ if (g_camera.yaw == ANGLE_180)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of X and Z with respect to Y */
+ /* The negative inverted tangent is equal to the rate of change of X with
+ * respect to the Y-axis. The cotangent is stored at double the the
+ * "normal" scaling.
+ */
+
+ dxdy = -g_cot_table(g_camera.yaw - ANGLE_180);
+
+ /* Determine the rate of change of the Z with respect to Y. The tangent
+ * is "double" precision; the cosecant is "double" precision. dzdy will
+ * be retained as "double" precision.
+ */
+
+ dzdy = qTOd(g_adj_tanpitch * ABS(g_csc_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in a Y plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_yplane.tail; list; list = list->blink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "before" the current camera
+ * position
+ */
+
+ if (rect->plane < g_camera.y)
+ {
+ /* get the Y distance to the plane */
+
+ rely = g_camera.y - rect->plane;
+
+ /* g_ray_yplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (rely > result->ydist)
+ {
+ return;
+ }
+
+ /* Calculate the Y position at this relative X position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (rely != lastrely1)
+ {
+ int32_t deltax; /* Scale == "triple" */
+
+ /* The dxdy is stored at double the"normal" scaling -- so deltax
+ * is "triple" precision
+ */
+
+ deltax = dxdy * ((int32_t) rely);
+ absx = tTOs(deltax) + g_camera.x; /* back to "single" */
+ lastrely1 = rely;
+ }
+
+ /* Check if this X position intersects the rectangle */
+
+ if (absx >= rect->hstart && absx <= rect->hend)
+ {
+
+ /* The X position lies in the rectangle. Now, calculate the
+ * Z position at this relative X position. We can skip this
+ * step if we are processing another rectangle at the same
+ * relx distance.
+ */
+
+ if (rely != lastrely2)
+ {
+ int32_t deltaz; /* Scale == TRIPLE */
+
+ /* The dzdy is stored at double the"normal" scaling -- so
+ * deltaz is "triple" precision
+ */
+
+ deltaz = dzdy * ((int32_t) rely);
+ absz = tTOs(deltaz) + g_camera.z; /* Back to single */
+ lastrely2 = rely;
+ }
+
+ /* Check if this Z position intersects the rectangle */
+
+ if (absz >= rect->vstart && absz <= rect->vend)
+ {
+
+ /* We've got a potential hit, let's see what it is */
+ /* Check if we just hit an ordinary opaque wall */
+
+ if (IS_NORMAL(rect))
+ {
+ /* Yes..Save the parameters associated with the normal
+ * wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ else if (IS_DOOR(rect))
+ {
+ /* Check if the door is in motion. */
+
+ if (!IS_MOVING_DOOR(rect))
+ {
+ /* Save the parameters associated with the normal
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+
+ /* The door is in motion, the Z-position to see if we can
+ * see under the door
+ */
+
+ else if (absz > g_opendoor.zbottom)
+ {
+ /* Save the parameters associated with the moving
+ * door hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz - g_opendoor.zdist;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ }
+
+ /* Otherwise, it must be a transparent wall. We'll need to
+ * make our decision based upon the pixel that we hit
+ */
+
+ /* Check if the pixel at this location is visible */
+
+ else if (GET_BACK_PIXEL(rect, absx, absz) != INVISIBLE_PIXEL)
+ {
+ /* Its visible, save the parameters associated with the
+ * transparent wall hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT);
+ result->xpos = absx;
+ result->ypos = absz;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = rely;
+ result->zdist = ABS(absz - g_camera.z);
+
+ /* Terminate Y casting */
+
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_ray_zcasteru
+ *
+ * Description:
+ * This function casts a ray along the rotated Y-Axis looking at points of
+ * intersection on the Z-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "upper" half of the view, then the Z ray cast will
+ * proceed along the positive Z axis and that all possible Z-axis
+ * intersections will occur on the "bottom" of a cell.
+ *
+ * NOTE: It is assumed that both the X and Y ray casters have already
+ * ran!
+ ***************************************************************************/
+
+static void trv_ray_zcasteru(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current Z plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t relz; /* Relative position of the Z plane */
+ trv_coord_t absx; /* Absolute X position at relz given yaw */
+ trv_coord_t absy; /* Absolute Y position at relz given yaw */
+ trv_coord_t lastrelz1 = -1; /* Last relative Z position processed */
+ trv_coord_t lastrelz2 = -1; /* Last relative Z position processed */
+ int32_t dxdz; /* Rate of change of X wrt Z (double) */
+ int32_t dydz; /* Rate of change of Y wrt Z (double) */
+
+ /* At a viewing angle of 0 degrees, no intersections with the g_ray_zplanes are
+ * possible!
+ */
+
+ if (g_camera.pitch == ANGLE_0)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of X and Y with respect to Z */
+ /* Calculate the rate of change of X with respect to the Z-axis. The
+ * cotangent is stored at double the "normal" scaling and the cosine is
+ * also at double scaling. dxdz will be also be stored at double
+ * precision.
+ */
+
+ dxdz = qTOd(g_adj_cotpitch * ((int32_t) g_cos_table[g_camera.yaw]));
+
+ /* Calculate the rate of change of Y with respect to the Z-axis. The
+ * cotangent is stored at double the "normal" scaling and the sine is also
+ * at double scaling. dxdz will be also be stored at double precision.
+ */
+
+ dydz = qTOd(g_adj_cotpitch * ((int32_t) g_sin_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in the Z plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_zplane.head; list; list = list->flink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "beyond" the current camera
+ * position
+ */
+
+ if (rect->plane > g_camera.z)
+ {
+ /* get the Z distance to the plane */
+
+ relz = rect->plane - g_camera.z;
+
+ /* g_ray_zplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (relz > result->zdist)
+ {
+ return;
+ }
+
+ /* Calculate the X position at this relative Z position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relz != lastrelz1)
+ {
+ int32_t deltax; /* Scale == "triple" */
+
+ /* The dxdz is stored at double the"normal" scaling -- so deltax
+ * is "triple" precision
+ */
+
+ deltax = dxdz * ((int32_t) relz);
+ absx = tTOs(deltax) + g_camera.x; /* back to "single" */
+ lastrelz1 = relz;
+ }
+
+ /* Check if this X position intersects the rectangle */
+
+ if (absx >= rect->hstart && absx <= rect->hend)
+ {
+ /* The X position lies in the rectangle. Now, calculate the the
+ * Y position at this relative Z position. We can skip this step
+ * if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relz != lastrelz2)
+ {
+ int32_t deltay; /* Scale == TRIPLE */
+
+ /* The dydz is stored at double the"normal" scaling -- so
+ * deltay is "triple" precision
+ */
+
+ deltay = dydz * ((int32_t) relz);
+ absy = tTOs(deltay) + g_camera.y; /* back to "single" */
+ lastrelz2 = relz;
+ }
+
+ /* Check if this Y position intersects the rectangle */
+
+ if (absy >= rect->vstart && absy <= rect->vend)
+ {
+ /* We've got a hit, ..Save the parameters associated with the
+ * ceiling hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(BACK_HIT, Z_HIT);
+ result->xpos = absx;
+ result->ypos = absy;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = relz;
+
+ /* Terminate Z casting */
+
+ return;
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_ray_zcasterl
+ *
+ * Description:
+ * This function casts a ray along the rotated Y-Axis looking at points of
+ * intersection on the Z-Axis. If a block is defined at this intersection
+ * then a "hit" is found and the distance to this hit is determined.
+ *
+ * If we are in the "lower" half of the view, then the Z ray cast will
+ * proceed along the negative Z axis and that all possible Z-axis
+ * intersections will occur on the "top" of a cell.
+ *
+ * NOTE: It is assumed that both the X and Y ray casters have already
+ * ran!
+ *
+ ***************************************************************************/
+
+static void trv_ray_zcasterl(FAR struct trv_raycast_s *result)
+{
+ struct trv_rect_list_s *list; /* Points to the current Z plane rectangle */
+ struct trv_rect_data_s *rect; /* Points to the rectangle data */
+ trv_coord_t relz; /* Relative position of the Z plane */
+ trv_coord_t absx; /* Absolute X position at relz given yaw */
+ trv_coord_t absy; /* Absolute Y position at relz given yaw */
+ trv_coord_t lastrelz1 = -1; /* Last relative Z position processed */
+ trv_coord_t lastrelz2 = -1; /* Last relative Z position processed */
+ int32_t dxdz; /* Rate of change of X wrt Z (double) */
+ int32_t dydz; /* Rate of change of Y wrt Z (double) */
+
+ /* At a viewing angle of 0 degrees, no intersections with the g_ray_zplanes are
+ * possible!
+ */
+
+ if (g_camera.pitch == ANGLE_0)
+ {
+ return;
+ }
+
+ /* Pre-calculate the rate of change of X and Y with respect to Z */
+ /* Calculate the rate of change of X with respect to the Z-axis. The
+ * cotangent is stored at double the "normal" scaling and the cosine is
+ * also at double scaling. dxdz will be also be stored at double
+ * precision.
+ */
+
+ dxdz = qTOd(g_adj_cotpitch * ((int32_t) g_cos_table[g_camera.yaw]));
+
+ /* Calculate the rate of change of Y with respect to the Z-axis. The
+ * cotangent is stored at double the "normal" scaling and the sine is
+ * also at double scaling. dxdz will be also be stored at double
+ * precision.
+ */
+
+ dydz = qTOd(g_adj_cotpitch * ((int32_t) g_sin_table[g_camera.yaw]));
+
+ /* Look at every rectangle lying in the Z plane */
+ /* This logic should be improved at some point so that non-visible planes
+ * are "pruned" from the list prior to ray casting!
+ */
+
+ for (list = g_ray_zplane.tail; list; list = list->blink)
+ {
+ rect = &list->d;
+
+ /* Search for a rectangle which lies "before" the current camera
+ * position
+ */
+
+ if (rect->plane < g_camera.z)
+ {
+ /* get the Z distance to the plane */
+
+ relz = g_camera.z - rect->plane;
+
+ /* g_ray_zplane is an ordered list, if we have already hit something
+ * closer, then we can abort the casting now.
+ */
+
+ if (relz > result->zdist)
+ {
+ return;
+ }
+
+ /* Calculate the X position at this relative Z position. We can skip
+ * this step if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relz != lastrelz1)
+ {
+ int32_t deltax; /* Scale == "triple" */
+
+ /* The dxdz is stored at double the"normal" scaling -- so deltax
+ * is "triple" precision
+ */
+
+ deltax = dxdz * ((int32_t) relz);
+ absx = tTOs(deltax) + g_camera.x; /* back to "single" */
+ lastrelz1 = relz;
+ }
+
+ /* Check if this X position intersects the rectangle */
+
+ if (absx >= rect->hstart && absx <= rect->hend)
+ {
+ /* The X position lies in the rectangle. Now, calculate the the
+ * Y position at this relative Z position. We can skip this step
+ * if we are processing another rectangle at the same relx
+ * distance.
+ */
+
+ if (relz != lastrelz2)
+ {
+ int32_t deltay; /* Scale == TRIPLE */
+
+ /* The dydz is stored at double the"normal" scaling -- so
+ * deltay is "triple" precision
+ */
+
+ deltay = dydz * ((int32_t) relz);
+ absy = tTOs(deltay) + g_camera.y; /* back to "single" */
+ lastrelz2 = relz;
+ }
+
+ /* Check if this Y position intersects the rectangle */
+
+ if (absy >= rect->vstart && absy <= rect->vend)
+ {
+ /* We've got a hit, ..Save the parameters associated with the
+ * floor hit
+ */
+
+ result->rect = rect;
+ result->type = MK_HIT_TYPE(FRONT_HIT, Z_HIT);
+ result->xpos = absx;
+ result->ypos = absy;
+
+ result->xdist = ABS(absx - g_camera.x);
+ result->ydist = ABS(absy - g_camera.y);
+ result->zdist = relz;
+
+ /* Terminate Z casting */
+
+ return;
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_raycast
+ *
+ * Description:
+ * This function performs a single ray cast. It decomposes the cast by
+ * quadrants so that simpler casting algorithms can be used. It also
+ * enforces the order of casting: X first, then Y, and finally Z.
+ *
+ ***************************************************************************/
+
+void trv_raycast(int16_t pitch, int16_t yaw, int16_t screenyaw,
+ FAR struct trv_raycast_s *result)
+{
+ /* Set the camera pitch and yaw angles for this cast */
+
+ g_camera.pitch = pitch;
+ g_camera.yaw = yaw;
+
+ /* Initialize the result structure, assuming that there will be no hit */
+
+ result->rect = NULL;
+ result->type = NO_HIT;
+ result->xpos = 0;
+ result->ypos = 0;
+ result->xdist = TRV_INFINITY;
+ result->ydist = TRV_INFINITY;
+ result->zdist = TRV_INFINITY;
+
+ /* Prepare for X and Y ray casts. These casts will need the adjusted tangent
+ * of the pitch angle in order to correct for "fish eye" distortion. This
+ * correction consists of multiplying by the cosine of the relative screen
+ * yaw position. The tangent is double precision, the cosine is double
+ * precision, the result will be retained as double precision.
+ */
+
+ screenyaw = ABS(screenyaw);
+#if ENABLE_VIEW_CORRECTION
+ g_adj_tanpitch = qTOd(TAN(pitch) * ((int32_t) g_cos_table[screenyaw]));
+#else
+ g_adj_tanpitch = TAN(pitch);
+#endif
+
+ /* Perform X & Y raycasting based on the quadrant of the yaw angle */
+
+ if (g_camera.yaw < ANGLE_90)
+ {
+ trv_ray_xcaster14(result);
+ trv_ray_ycaster12(result);
+ }
+ else if (g_camera.yaw < ANGLE_180)
+ {
+ trv_ray_xcaster23(result);
+ trv_ray_ycaster12(result);
+ }
+ else if (g_camera.yaw < ANGLE_270)
+ {
+ trv_ray_xcaster23(result);
+ trv_ray_ycaster34(result);
+ }
+ else
+ {
+ trv_ray_xcaster14(result);
+ trv_ray_ycaster34(result);
+ }
+
+ /* Perform Z ray casting based upon if we are looking up or down */
+
+ if (g_camera.pitch < ANGLE_90)
+ {
+ /* Get the adjusted cotangent of the pitch angle which is used to correct
+ * for the "fish eye" distortion. This correction consists of
+ * multiplying by the inverted cosine of the relative screen yaw
+ * position. The cotangent is double precision, the secant is double
+ * precision, the result will be retained as double precision.
+ */
+
+#if ENABLE_VIEW_CORRECTION
+ g_adj_cotpitch = qTOd(g_cot_table(pitch) * g_sec_table[screenyaw]);
+#else
+ g_adj_cotpitch = g_cot_table(pitch);
+#endif
+ trv_ray_zcasteru(result);
+ }
+ else
+ {
+ /* Get the adjusted cotangent of the pitch angle which is used to correct
+ * for the "fish eye" distortion. This correction consists of
+ * multiplying by the inverted cosine of the relative screen yaw
+ * position. The cotangent is double precision, the secant is double
+ * precision, the result will be retained as double precision.
+ */
+
+#if ENABLE_VIEW_CORRECTION
+ g_adj_cotpitch =
+ qTOd(g_cot_table(ANGLE_360 - pitch) * g_sec_table[screenyaw]);
+#else
+ g_adj_cotpitch = g_cot_table(ANGLE_360 - pitch);
+#endif
+ trv_ray_zcasterl(result);
+ }
+}