summaryrefslogtreecommitdiff
path: root/apps/graphics/traveler/src
diff options
context:
space:
mode:
Diffstat (limited to 'apps/graphics/traveler/src')
-rwxr-xr-xapps/graphics/traveler/src/trv_doors.c336
-rw-r--r--apps/graphics/traveler/src/trv_graphics.c86
-rw-r--r--apps/graphics/traveler/src/trv_input.c1
-rw-r--r--apps/graphics/traveler/src/trv_main.c2
-rw-r--r--apps/graphics/traveler/src/trv_mem.c1
-rw-r--r--apps/graphics/traveler/src/trv_nxbkgd.c1
-rw-r--r--apps/graphics/traveler/src/trv_nxserver.c1
-rw-r--r--apps/graphics/traveler/src/trv_pov.c1
-rwxr-xr-xapps/graphics/traveler/src/trv_rayrend.c1337
9 files changed, 1726 insertions, 40 deletions
diff --git a/apps/graphics/traveler/src/trv_doors.c b/apps/graphics/traveler/src/trv_doors.c
new file mode 100755
index 000000000..7ae726ba7
--- /dev/null
+++ b/apps/graphics/traveler/src/trv_doors.c
@@ -0,0 +1,336 @@
+/*******************************************************************************
+ * apps/graphics/traveler/src/trv_doors.c
+ * This file contains the logic which manages world door 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_input.h"
+#include "trv_pov.h"
+#include "trv_plane.h"
+#include "trv_world.h"
+#include "trv_rayavoid.h"
+#include "trv_doors.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* This is the door opening rate */
+
+#define DOOR_ZSTEP 15
+#define DOOR_OPEN_WAIT 30
+
+/****************************************************************************
+ * Private Type Declarations
+ ***************************************************************************/
+
+/* These are possible values for the g_opendoor state variable */
+
+enum trv_door_state_e
+{
+ DOOR_IDLE = 0, /* No door action in progress */
+ DOOR_OPENING, /* A door is opening */
+ DOOR_OPEN, /* A door is open */
+ 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
+ ****************************************************************************/
+
+static void trv_door_startopen(void);
+static void trv_door_animation(void);
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/* Variables to track status of a door */
+
+struct trv_opendoor_s g_opendoor;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_door_startopen
+ *
+ * Description:
+ *
+ ***************************************************************************/
+
+static void trv_door_startopen (void)
+{
+ FAR struct trv_rect_data_s *rect;
+
+ /* Check if a door is already opening */
+
+ if (g_opendoor.state == DOOR_IDLE)
+ {
+ /* Test if there is a door within three steps in front of the player */
+ /* Try the X planes first */
+
+ rect = trv_test_xplane(&g_trv_player, 3*STEP_DISTANCE,
+ g_trv_player.yaw, g_player_height);
+
+ /* If there is no X door in front of the player, then try the Y Planes
+ * (it is assumed that there would not be doors this close in both
+ * planes!)
+ */
+
+ if (!rect || !IS_DOOR(rect))
+ {
+ rect = trv_test_yplane(&g_trv_player, 3*STEP_DISTANCE,
+ g_trv_player.yaw, g_player_height);
+ }
+
+ /* Check if we found a door in either the X or Y plane. */
+
+ if (rect && IS_DOOR(rect))
+ {
+ /* We now have found a door to open. Set the door open sequence
+ * in motion
+ */
+
+ g_opendoor.rect = rect;
+ g_opendoor.state = DOOR_OPENING;
+ g_opendoor.zbottom = rect->vstart;
+ g_opendoor.zdistance = 0;
+
+ /* Mark the door's attribute to indicate that it is in motion */
+
+ rect->attribute |= MOVING_DOOR_PLANE;
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_door_animation
+ * Description:
+ * This function is called every frame when a door is in motion.
+ ****************************************************************************/
+
+static void trv_door_animation(void)
+{
+ /* What we do next depends upon the state of the door state machine */
+
+ switch (g_opendoor.state)
+ {
+ /* A door is opening */
+
+ case DOOR_OPENING :
+
+ /* Raise the door a little */
+
+ g_opendoor.zbottom += DOOR_ZSTEP;
+ g_opendoor.zdistance += DOOR_ZSTEP;
+
+ /* When the bottom of the door is above the player's head, we will
+ * say that the door is open
+ */
+
+ if (g_opendoor.zbottom > g_trv_player.z)
+ {
+ g_opendoor.rect->attribute |= OPEN_DOOR_PLANE;
+ }
+
+ /* Check if the door is fully open */
+
+ if (g_opendoor.zbottom >= g_opendoor.rect->vend)
+ {
+ /* 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;
+
+ /* The door is done opening, the next state is the DOOR_OPEN state
+ * where we will hold the door open a while
+ */
+
+ g_opendoor.state = DOOR_OPEN;
+
+ /* Initialize the countdown timer which will determine how long
+ * the door is held open
+ */
+
+ g_opendoor.clock = DOOR_OPEN_WAIT;
+ }
+ break;
+
+ /* The door is open */
+
+ case DOOR_OPEN :
+ /* Decrement the door open clock. When it goes to zero, it is time
+ * to begin closing the door
+ */
+
+ if (--g_opendoor.clock <= 0)
+ {
+ /* The door is done opening, the next state is the DOOR_CLOSING
+ * states
+ */
+
+ g_opendoor.state = DOOR_CLOSING;
+
+ /* Lower the door a little */
+
+ g_opendoor.zbottom -= DOOR_ZSTEP;
+ g_opendoor.zdistance -= DOOR_ZSTEP;
+
+ /* When the bottom of the door is below the player's head, we
+ * will say that the door is closed
+ */
+
+ if (g_opendoor.zbottom <= g_trv_player.z)
+ {
+ g_opendoor.rect->attribute &= ~OPEN_DOOR_PLANE;
+ }
+ }
+ break;
+
+ /* The door is closing */
+
+ case DOOR_CLOSING :
+ /* Lower the door a little */
+
+ g_opendoor.zbottom -= DOOR_ZSTEP;
+ g_opendoor.zdistance -= DOOR_ZSTEP;
+
+ /* When the bottom of the door is below the player's head, we will
+ * say that the door is closed
+ */
+
+ if (g_opendoor.zbottom <= g_trv_player.z)
+ {
+ g_opendoor.rect->attribute &= ~OPEN_DOOR_PLANE;
+ }
+
+ /* Check if the door is fully closed */
+
+ if (g_opendoor.zdistance <= 0)
+ {
+ /* Indicate that the door is no longer in motion */
+
+ g_opendoor.rect->attribute &= ~(OPEN_DOOR_PLANE|MOVING_DOOR_PLANE);
+
+ /* Indicate that the entire door movement sequence is done */
+
+ g_opendoor.rect = NULL;
+ g_opendoor.state = DOOR_IDLE;
+ }
+ break;
+
+ /* There is nothing going on! */
+
+ case DOOR_IDLE :
+ default :
+ break;
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_door_initialize
+ *
+ * Description:
+ * This function performs initialization of the door animation logic
+ *
+ ****************************************************************************/
+
+void trv_door_initialize(void)
+{
+ /* Initialize the g_opendoor structure */
+
+ g_opendoor.rect = NULL;
+ g_opendoor.state = DOOR_IDLE;
+}
+
+/***************************************************************************
+ * Name: trv_door_animate
+ *
+ * Description:
+ * This function must be called on each cycle. It checks if the player
+ * is attempting to open a door. If so, the appropriate door animation
+ * is started. This function then calls trv_door_animation which must be
+ * called on each cycle to perform the door movement.
+ *
+ ***************************************************************************/
+
+void trv_door_animate(void)
+{
+ /* Check if the user is trying to open a door. */
+
+ if (g_trv_input.dooropen && g_opendoor.state == DOOR_IDLE)
+ {
+
+ /* Start the door opening action */
+
+ trv_door_startopen();
+ }
+
+ /* Process any necessary door movement animation on this cycle */
+
+ if (g_opendoor.state != DOOR_IDLE)
+ {
+ /* Perform the animation */
+
+ trv_door_animation();
+ }
+}
diff --git a/apps/graphics/traveler/src/trv_graphics.c b/apps/graphics/traveler/src/trv_graphics.c
index 02d9b61b9..c37086cab 100644
--- a/apps/graphics/traveler/src/trv_graphics.c
+++ b/apps/graphics/traveler/src/trv_graphics.c
@@ -41,6 +41,7 @@
#include "trv_main.h"
#include "trv_mem.h"
#include "trv_color.h"
+#include "trv_raycntl.h"
#include "trv_debug.h"
#include "trv_graphics.h"
@@ -130,8 +131,8 @@ static void trv_fb_initialize(FAR struct trv_graphics_info_s *ginfo)
trv_abort("getvideoinfo() failed\n");
}
- ginfo->hwwidth = vinfo.xres;
- ginfo->hwheight = vinfo.yres;
+ ginfo->xres = vinfo.xres;
+ ginfo->yres = vinfo.yres;
ret = fbdev->getplaneinfo(fbdev, 0, &pinfo);
if (ret < 0)
@@ -329,24 +330,21 @@ void trv_row_update(struct trv_graphics_info_s *ginfo,
FAR const trv_pixel_t *src,
FAR dev_pixel_t *dest)
{
- trv_coord_t hexpand;
dev_pixel_t pixel;
trv_coord_t srccol;
int i;
/* Loop for each column in the src render buffer */
- hexpand = (1 << ginfo->hscale);
-
- for (srccol = 0; srccol < ginfo->swwidth; srccol++)
+ for (srccol = 0; srccol < TRV_SCREEN_WIDTH; srccol++)
{
/* Map the source pixel */
pixel = ginfo->palette.lut[*src++];
- /* Copy it to the destination, expanding as necessary */
+ /* Expand pixels horizontally via pixel replication */
- for (i = 0; i < hexpand; i++)
+ for (i = 0; i < ginfo->xscale; i++)
{
*dest++ = pixel;
}
@@ -383,8 +381,8 @@ void trv_display_update(struct trv_graphics_info_s *ginfo,
int trv_graphics_initialize(FAR struct trv_graphics_info_s *ginfo)
{
- int swwidth;
- int swheight;
+ int width;
+ int height;
int scale;
/* Initialize the graphics device and get information about the display */
@@ -397,31 +395,39 @@ int trv_graphics_initialize(FAR struct trv_graphics_info_s *ginfo)
trv_nxsu_initialize(ginfo);
#endif
+ /* Check the size of the display */
+
+ width = ginfo->xres;
+ height = ginfo->yres;
+
+ if (width < TRV_SCREEN_WIDTH || height < TRV_SCREEN_HEIGHT)
+ {
+ trv_abort("ERROR: Display is too small\n");
+ }
+
/* Check if we need to scale the image */
- swwidth = ginfo->hwwidth;
- scale = 0;
+ scale = 0;
- while (swwidth > MAX_REND_WIDTH)
+ while (width >= TRV_SCREEN_WIDTH)
{
- swwidth >>= 1;
+ width -= TRV_SCREEN_WIDTH;
scale++;
}
- ginfo->swwidth = swwidth;
- ginfo->hscale = scale;
+ ginfo->xscale = scale;
+ ginfo->xoffset = (width >> 1);
+ ginfo->imgwidth = scale * TRV_SCREEN_WIDTH * sizeof(dev_pixel_t);
- swheight = ginfo->hwheight;
- scale = 0;
-
- while (swheight > MAX_REND_WIDTH)
+ scale = 0;
+ while (height >= TRV_SCREEN_HEIGHT)
{
- swheight >>= 1;
+ height -= TRV_SCREEN_HEIGHT;
scale++;
}
- ginfo->swheight = swheight;
- ginfo->vscale = scale;
+ ginfo->yscale = scale;
+ ginfo->yoffset = (height >> 1);
/* Allocate buffers
*
@@ -431,7 +437,7 @@ int trv_graphics_initialize(FAR struct trv_graphics_info_s *ginfo)
*/
ginfo->swbuffer = (trv_pixel_t*)
- trv_malloc(swwidth * swheight * sizeof(trv_pixel_t));
+ trv_malloc(TRV_SCREEN_WIDTH * TRV_SCREEN_HEIGHT * sizeof(trv_pixel_t));
if (!ginfo->swbuffer)
{
trv_abort("ERROR: Failed to allocate render buffer\n");
@@ -448,8 +454,7 @@ int trv_graphics_initialize(FAR struct trv_graphics_info_s *ginfo)
*/
#ifdef CONFIG_NX
- ginfo->hwbuffer = (trv_pixel_t*)
- trv_malloc(ginfo->hwwidth * sizeof(dev_pixel_t));
+ ginfo->hwbuffer = (trv_pixel_t*)trv_malloc(ginfo->imgwidth);
if (!ginfo->hwbuffer)
{
trv_abort("ERROR: Failed to allocate hardware line buffer\n");
@@ -503,28 +508,33 @@ void trv_graphics_terminate(FAR struct trv_graphics_info_s *ginfo)
void trv_display_update(struct trv_graphics_info_s *ginfo)
{
- FAR const uint8_t *src = (FAR const uint8_t *)ginfo->swbuffer;
- FAR uint8_t *dest = (FAR uint8_t *)ginfo->hwbuffer;
+ FAR const uint8_t *src;
+ FAR uint8_t *dest;
trv_coord_t srcrow;
#ifdef CONFIG_NX
trv_coord_t destrow;
#else
FAR uint8_t *first;
- trv_coord_t lnwidth;
#endif
- trv_coord_t vexpand;
int i;
- /* Loop for each row in the srce render buffer */
+ /* Get the star tof the first source row */
+
+ src = (FAR const uint8_t *)ginfo->swbuffer;
+
+ /* Get the start of the first destination row */
+
+ dest = (FAR uint8_t *)ginfo->hwbuffer +
+ (ginfo->yoffset * ginfo->stride) +
+ (ginfo->xoffset * sizeof(dev_pixel_t));
+
+ /* Loop for each row in the src render buffer */
- vexpand = (1 << ginfo->vscale);
#ifdef CONFIG_NX
destrow = 0;
-#else
- lnwidth = ginfo->hwwidth * sizeof(dev_pixel_t);
#endif
- for (srcrow = 0; srcrow < ginfo->swheight; srcrow++)
+ for (srcrow = 0; srcrow < TRV_SCREEN_HEIGHT; srcrow++)
{
/* Transfer the row to the device row/buffer */
@@ -543,7 +553,7 @@ void trv_display_update(struct trv_graphics_info_s *ginfo)
/* Then replicate as many times as is necessary */
- for (i = 1; i < vexpand; i++)
+ for (i = 1; i < ginfo->yscale; i++)
{
#ifdef CONFIG_NX
/* Transfer the row buffer to the NX window */
@@ -553,14 +563,14 @@ void trv_display_update(struct trv_graphics_info_s *ginfo)
#else
/* Point to the next row in the frame buffer */
- memcpy(dest, first, lnwidth);
+ memcpy(dest, first, ginfo->imgwidth);
dest += ginfo->stride;
#endif
}
/* Point to the next src row */
- src += ginfo->swwidth;
+ src += TRV_SCREEN_WIDTH;
}
}
diff --git a/apps/graphics/traveler/src/trv_input.c b/apps/graphics/traveler/src/trv_input.c
index ea100de5c..44644e150 100644
--- a/apps/graphics/traveler/src/trv_input.c
+++ b/apps/graphics/traveler/src/trv_input.c
@@ -1,6 +1,5 @@
/****************************************************************************
* apps/graphics/traveler/trv_input.c
- * This file contains the main logic for the NuttX version of Traveler
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/apps/graphics/traveler/src/trv_main.c b/apps/graphics/traveler/src/trv_main.c
index 594513a9a..bafd5cb1c 100644
--- a/apps/graphics/traveler/src/trv_main.c
+++ b/apps/graphics/traveler/src/trv_main.c
@@ -257,7 +257,7 @@ int traveler_main(int argc, char *argv[])
/* Paint the back drop */
- trv_rend_backdrop(&g_trv_player);
+ trv_rend_backdrop(&g_trv_player, &g_trv_ginfo);
/* Render the 3-D view */
diff --git a/apps/graphics/traveler/src/trv_mem.c b/apps/graphics/traveler/src/trv_mem.c
index 84e85c3d0..816e8081d 100644
--- a/apps/graphics/traveler/src/trv_mem.c
+++ b/apps/graphics/traveler/src/trv_mem.c
@@ -1,5 +1,6 @@
/****************************************************************************
* apps/graphics/traveler/src/trv_mem.c
+ * Memory management support
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/apps/graphics/traveler/src/trv_nxbkgd.c b/apps/graphics/traveler/src/trv_nxbkgd.c
index 08a54a834..e0f34a512 100644
--- a/apps/graphics/traveler/src/trv_nxbkgd.c
+++ b/apps/graphics/traveler/src/trv_nxbkgd.c
@@ -1,5 +1,6 @@
/****************************************************************************
* apps/graphics/traveler/trv_nxbkgd.c
+ * NX background window callback handlers
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/apps/graphics/traveler/src/trv_nxserver.c b/apps/graphics/traveler/src/trv_nxserver.c
index e2cedaa28..ea2501fff 100644
--- a/apps/graphics/traveler/src/trv_nxserver.c
+++ b/apps/graphics/traveler/src/trv_nxserver.c
@@ -1,5 +1,6 @@
/****************************************************************************
* apps/graphics/traveler/trv_nxlistener.c
+ * NX server logic
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/apps/graphics/traveler/src/trv_pov.c b/apps/graphics/traveler/src/trv_pov.c
index 33d66a1f6..38b67b620 100644
--- a/apps/graphics/traveler/src/trv_pov.c
+++ b/apps/graphics/traveler/src/trv_pov.c
@@ -1,5 +1,6 @@
/****************************************************************************
* apps/graphics/traveler/trv_pov.c
+ * This file contains the logic which manages player's point-of-view (POV)
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
diff --git a/apps/graphics/traveler/src/trv_rayrend.c b/apps/graphics/traveler/src/trv_rayrend.c
new file mode 100755
index 000000000..f9c45c3ad
--- /dev/null
+++ b/apps/graphics/traveler/src/trv_rayrend.c
@@ -0,0 +1,1337 @@
+/*****************************************************************************
+ * apps/graphics/traveler/src/trv_rayrend.c
+ * This file contains the functions needed to render a screen.
+ *
+ * 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_debug.h"
+#include "trv_world.h"
+#include "trv_plane.h"
+#include "trv_bitmaps.h"
+#include "trv_graphics.h"
+#include "trv_paltable.h"
+#include "trv_trigtbl.h"
+#include "trv_raycntl.h"
+#include "trv_raycast.h"
+#include "trv_rayrend.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* These are sometimes useful during debug */
+
+#define DISABLE_WALL_RENDING 0
+#define DISABLE_FLOOR_RENDING 0
+
+/* The following macros perform division (using g_invsize[]) and then a
+ * rescaling by the approprate constants so that the texture index is
+ * byte aligned
+ */
+
+#define TDIV(num,den,s) (((num) * g_invsize[den]) >> (s))
+
+/* This macro just performs the division and leaves the result with eight
+ * (more) bits of fraction
+ */
+
+#define DIV8(num,den) ((num) * g_invsize[den])
+
+/* The following macro aligns a SMALL precision number to that the texture
+ * index is byte aligned
+ */
+
+#define TALIGN(x,s) ((x) << (8-(s)))
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+/* This union is used to manage texture indices */
+
+union tex_ndx_u
+{
+ struct
+ {
+ uint8_t f;
+ uint8_t i;
+ } s;
+ int16_t w;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void trv_rend_zcell(uint8_t row, uint8_t col, uint8_t height,
+ uint8_t width);
+static void trv_rend_zrow(uint8_t row, uint8_t col, uint8_t width);
+static void trv_rend_zcol(uint8_t row, uint8_t col, uint8_t height);
+static void trv_rend_zpixel(uint8_t row, uint8_t col);
+
+static void trv_rend_wall(uint8_t row, uint8_t col, uint8_t height,
+ uint8_t width);
+static void trv_rend_wallrow(uint8_t row, uint8_t col, uint8_t width);
+static void trv_rend_wallcol(uint8_t row, uint8_t col, uint8_t height);
+static void trv_rend_wallpixel(uint8_t row, uint8_t col);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* The following array simply contains the inverted values of the integers
+ * from 0...VGULP_SIZE-1. The values in the table have 8 bits of fraction.
+ * The value for 0 is bogus!
+ */
+
+static const uint8_t g_invsize[VGULP_SIZE] =
+{
+ 0xff, 0xff, 0x80, 0x55, 0x40, 0x33, 0x2b, 0x25, /* 0..7 */
+ 0x20, 0x1c, 0x1a, 0x17, 0x15, 0x14, 0x12, 0x11 /* 8..15 */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_rend_zcell, trv_rend_zrow, trv_rend_zcol, trv_rend_zpixel
+ *
+ * Description:
+ * After matching hits have been obtained in all four corners of a cell,
+ * this function interpolates to complete the cell then transfers the cell
+ * to the double buffer. These are the general cases where no assumptions
+ * are made concerning the relative orientation of the cell and the texture.
+ * This general case is only used to texture floors and ceilings.
+ *
+ ****************************************************************************/
+
+/* This version is for non-degenerate cell, i.e., height>1 and width>1 */
+
+static void trv_rend_zcell(uint8_t row, uint8_t col, uint8_t height, uint8_t width)
+{
+#if (!DISABLE_FLOOR_RENDING)
+ uint8_t i;
+ uint8_t j;
+ uint8_t endrow;
+ uint8_t endcol;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u xpos;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t endzone;
+ int16_t zonestep;
+ int16_t hstart;
+ int16_t hrowstep;
+ int16_t hcolstep;
+ int16_t hstepincr;
+ int16_t vstart;
+ int16_t vrowstep;
+ int16_t vcolstep;
+ int16_t vstepincr;
+ int16_t tmpcolstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column];
+
+ /* Point to the bitmap associated with the upper left pixel. Since
+ * all of the pixels in this cell are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Within this function, all references to height and width are really
+ * (height-1) and (width-1)
+ */
+
+ height--;
+ width--;
+
+ /* Get the indices to the lower, right corner */
+
+ endcol = col + width;
+ endrow = row + height;
+
+ /* Calculate the horizontal interpolation values */
+ /* This is the H starting position (first row, first column) */
+
+ hstart = TALIGN(g_ray_hit[row][col].xpos, scale);
+
+ /* This is the change in xpos per column in the first row */
+
+ hcolstep =
+ TDIV((g_ray_hit[row][endcol].xpos - g_ray_hit[row][col].xpos),
+ width, scale);
+
+ /* This is the change in xpos per column in the last row */
+
+ tmpcolstep =
+ TDIV((g_ray_hit[endrow][endcol].xpos - g_ray_hit[endrow][col].xpos),
+ width, scale);
+
+ /* This is the change in hcolstep per row */
+
+ hstepincr = (TDIV((tmpcolstep - hcolstep), height, scale) >> 8);
+
+ /* This is the change in hstart for each row */
+
+ hrowstep =
+ TDIV((g_ray_hit[endrow][col].xpos - g_ray_hit[row][col].xpos),
+ height, scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first row, first column) */
+
+ vstart = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos per column in the first row */
+
+ vcolstep =
+ TDIV((g_ray_hit[row][endcol].ypos - g_ray_hit[row][col].ypos),
+ width, scale);
+
+ /* This is the change in ypos per column in the last row */
+
+ tmpcolstep =
+ TDIV((g_ray_hit[endrow][endcol].ypos - g_ray_hit[endrow][col].ypos),
+ width, scale);
+
+ /* This is the change in vcolstep per row */
+
+ vstepincr = (TDIV((tmpcolstep - vcolstep), height, scale) >> 8);
+
+ /* This is the change in vstart for each row */
+
+ vrowstep =
+ TDIV((g_ray_hit[endrow][col].ypos - g_ray_hit[row][col].ypos),
+ height, scale);
+
+ /* Determine the palette mapping table zone for each row */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_FZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist, 8);
+ endzone = GET_FZONE(g_ray_hit[endrow][col].xdist, g_ray_hit[endrow][col].ydist, 8);
+ zonestep = (DIV8((endzone - zone), height) >> 8);
+ }
+ else
+ {
+ zone = 0;
+ zonestep = 0;
+ }
+
+ /* Now, interpolate to texture each row (vertical component) */
+
+ for (i = row; i <= endrow; i++)
+ {
+ /* Set the initial horizontal & vertical offset */
+
+ xpos.w = hstart;
+ ypos.w = vstart;
+
+ /* Get the palette map to use on this row */
+
+ palptr = GET_PALPTR((zone >> 8));
+
+ /* Interpolate to texture each column in the row */
+
+ for (j = col; j <= endcol; j++)
+ {
+ /* Transfer the pixel at this interpolated position */
+
+ outpixel[j] = palptr[texture[TNDX(xpos.s.i, ypos.s.i, tsize, tmask)]];
+
+ /* Now Calculate the horizontal position for the next step */
+
+ xpos.w += hcolstep;
+ ypos.w += vcolstep;
+ }
+
+ /* Point to the next row */
+
+ outpixel += TRV_SCREEN_WIDTH;
+
+ /* Calculate the vertical position for the next step */
+
+ hstart += hrowstep;
+ vstart += vrowstep;
+
+ /* Adjust the step sizes to use on the next row */
+
+ hcolstep += hstepincr;
+ vcolstep += vstepincr;
+
+ /* Get the zone to use on the next row */
+
+ zone += zonestep;
+ }
+#endif
+}
+
+/* This version is for horizontal lines, i.e., height==1 and width>1 */
+
+static void trv_rend_zrow(uint8_t row, uint8_t col, uint8_t width)
+{
+#if (!DISABLE_FLOOR_RENDING)
+ uint8_t j;
+ uint8_t endcol;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u xpos;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t hcolstep;
+ int16_t vcolstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column];
+
+ /* Point to the bitmap associated with the left pixel. Since
+ * all of the pixels in this row are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Within this function, all references to width are really
+ * (width-1)
+ */
+
+ width--;
+
+ /* Get the index to the right side */
+
+ endcol = col + width;
+
+ /* Calculate the horizontal interpolation values */
+ /* This is the H starting position (first column) */
+
+ xpos.w = TALIGN(g_ray_hit[row][col].xpos, scale);
+
+ /* This is the change in xpos per column */
+
+ hcolstep =
+ TDIV((g_ray_hit[row][endcol].xpos - g_ray_hit[row][col].xpos),
+ width, scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first column) */
+
+ ypos.w = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos per column */
+
+ vcolstep =
+ TDIV((g_ray_hit[row][endcol].ypos - g_ray_hit[row][col].ypos),
+ width, scale);
+
+ /* Interpolate to texture each column in the row */
+
+ for (j = col; j <= endcol; j++)
+ {
+ /* Transfer the pixel at this interpolated position */
+
+ outpixel[j] = palptr[texture[TNDX(xpos.s.i, ypos.s.i, tsize, tmask)]];
+
+ /* Now Calculate the horizontal position for the next step */
+
+ xpos.w += hcolstep;
+ ypos.w += vcolstep;
+ }
+#endif
+}
+
+/* This version is for vertical lines, i.e., height>1 and width==1 */
+
+static void trv_rend_zcol(uint8_t row, uint8_t col, uint8_t height)
+{
+#if (!DISABLE_FLOOR_RENDING)
+ uint8_t i, endrow;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u xpos;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t hrowstep;
+ int16_t vrowstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column+col];
+
+ /* Point to the bitmap associated with the upper pixel. Since
+ * all of the pixels in this column are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Within this function, all references to height are really
+ * (height-1)
+ */
+
+ height--;
+
+ /* Get the indices to the lower end */
+
+ endrow = row + height;
+
+ /* Calculate the horizontal interpolation values */
+ /* This is the H starting position (first row) */
+
+ xpos.w = TALIGN(g_ray_hit[row][col].xpos, scale);
+
+ /* This is the change in xpos for each row */
+
+ hrowstep =
+ TDIV((g_ray_hit[endrow][col].xpos - g_ray_hit[row][col].xpos),
+ height, scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first row) */
+
+ ypos.w = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos for each row */
+
+ vrowstep =
+ TDIV((g_ray_hit[endrow][col].ypos - g_ray_hit[row][col].ypos),
+ height, scale);
+
+ /* Now, interpolate to texture each row (vertical component) */
+
+ for (i = row; i <= endrow; i++)
+ {
+ /* Transfer the pixel at this interpolated position */
+
+ *outpixel = palptr[texture[TNDX(xpos.s.i, ypos.s.i, tsize, tmask)]];
+
+ /* Point to the next row */
+
+ outpixel += TRV_SCREEN_WIDTH;
+
+ /* Calculate the vertical position for the next step */
+
+ xpos.w += hrowstep;
+ ypos.w += vrowstep;
+ }
+#endif
+}
+
+/* This version is for a single pixel, i.e., height==1 and width==1 */
+
+static void trv_rend_zpixel(uint8_t row, uint8_t col)
+{
+#if (!DISABLE_FLOOR_RENDING)
+ FAR uint8_t *palptr;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Point to the bitmap associated with the upper left pixel. */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ g_buffer_row[row][g_cell_column+col] =
+ palptr[texture[TNDX(g_ray_hit[row][col].xpos, g_ray_hit[row][col].ypos,
+ tsize, tmask)]];
+#endif
+}
+
+/****************************************************************************
+ * Name: trv_rend_wall, trv_rend_wallrow, trv_rend_wallcol, diplayWallPixel
+ *
+ * Description:
+ * After matching hits have been obtained in all four corners of a cell,
+ * this function interpolates to complete the cell then transfers the cell
+ * to the double buffer. These special simplifications for use on on
+ * vertical (X or Y) walls. In this case, we can assume that:
+ *
+ * g_ray_hit[row][col].xpos == g_ray_hit[row+height-1][col]
+ * g_ray_hit[row][col+width-1].xpos == g_ray_hit[row+height-1][col+width-1]
+ *
+ * In addition to these simplifications, these functions include the
+ * added complications of handling internal INVISIBLE_PIXELs which may
+ * occur within TRANSPARENT_WALLs.
+ *
+ ****************************************************************************/
+
+/* This version is for non-degenerate cell, i.e., height>1 and width>1 */
+
+static void trv_rend_wall(uint8_t row, uint8_t col,
+ uint8_t height, uint8_t width)
+{
+#if (!DISABLE_WALL_RENDING)
+ uint8_t i, j;
+ uint8_t endrow;
+ uint8_t endcol;
+ uint8_t inpixel;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u xpos;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t hstart;
+ int16_t hcolstep;
+ int16_t vstart;
+ int16_t vrowstep;
+ int16_t vcolstep;
+ int16_t vstepincr;
+ int16_t tmpcolstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column];
+
+ /* Point to the bitmap associated with the upper left pixel. Since
+ * all of the pixels in this cell are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Within this function, all references to height and width are really
+ * (height-1) and (width-1)
+ */
+
+ height--;
+ width--;
+
+ /* Get the indices to the lower, right corner */
+
+ endcol = col + width;
+ endrow = row + height;
+
+ /* Calculate the horizontal interpolation values */
+ /* This is the H starting position (first row, first column) */
+
+ hstart = TALIGN(g_ray_hit[row][col].xpos, scale);
+
+ /* This is the change in xpos per column in the first row */
+
+ hcolstep =
+ TDIV((g_ray_hit[row][endcol].xpos - g_ray_hit[row][col].xpos),
+ width, scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first row, first column) */
+
+ vstart = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos per column in the first row */
+
+ vcolstep =
+ TDIV((g_ray_hit[row][endcol].ypos - g_ray_hit[row][col].ypos),
+ width, scale);
+
+ /* This is the change in ypos per column in the last row */
+
+ tmpcolstep =
+ TDIV((g_ray_hit[endrow][endcol].ypos - g_ray_hit[endrow][col].ypos),
+ width, scale);
+
+ /* This is the change in vcolstep per row */
+
+ vstepincr = (TDIV((tmpcolstep - vcolstep), height, scale) >> 8);
+
+ /* This is the change in vstart for each row */
+
+ vrowstep =
+ TDIV((g_ray_hit[endrow][col].ypos - g_ray_hit[row][col].ypos),
+ height, scale);
+
+ /* Now, interpolate to texture each row (vertical component) */
+
+ for (i = row; i <= endrow; i++)
+ {
+ /* Set the initial horizontal & vertical offset */
+
+ xpos.w = hstart;
+ ypos.w = vstart;
+
+ /* Interpolate to texture each column in the row */
+
+ for (j = col; j <= endcol; j++)
+ {
+ /* Extract the pixel from the texture */
+
+ inpixel = texture[TNDX(xpos.s.i, ypos.s.i, tsize, tmask)];
+
+ /* If this is an INVISIBLE_PIXEL in a TRANSPARENT_WALL, then
+ * we will have to take some pretty extreme measures to get the
+ * correct value of the pixel
+ */
+
+ if ((inpixel == INVISIBLE_PIXEL) &&
+ (IS_TRANSPARENT(g_ray_hit[row][col].rect)))
+ {
+ /* Check if we hit anything */
+
+ if ((inpixel = trv_get_texture(i, j)) != INVISIBLE_PIXEL)
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ outpixel[j] = inpixel;
+ }
+ }
+ else
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ outpixel[j] = palptr[inpixel];
+ }
+
+ /* Now Calculate the horizontal position for the next step */
+
+ xpos.w += hcolstep;
+ ypos.w += vcolstep;
+ }
+
+ /* Point to the next row */
+
+ outpixel += TRV_SCREEN_WIDTH;
+
+ /* Calculate the vertical position for the next step */
+
+ vstart += vrowstep;
+
+ /* Adjust the step sizes to use on the next row */
+
+ vcolstep += vstepincr;
+ }
+#endif
+}
+
+/* This version is for horizontal lines, i.e., height==1 and width>1 */
+
+static void trv_rend_wallrow(uint8_t row, uint8_t col, uint8_t width)
+{
+#if (!DISABLE_WALL_RENDING)
+ uint8_t j;
+ uint8_t endcol;
+ uint8_t inpixel;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u xpos;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t hcolstep;
+ int16_t vcolstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column];
+
+ /* Point to the bitmap associated with the left pixel. Since
+ * all of the pixels in this row are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Within this function, all references to width are really
+ * (width-1)
+ */
+
+ width--;
+
+ /* Get the index to the right side */
+
+ endcol = col + width;
+
+ /* Calculate the horizontal interpolation values */
+ /* This is the H starting position (first column) */
+
+ xpos.w = TALIGN(g_ray_hit[row][col].xpos, scale);
+
+ /* This is the change in xpos per column */
+
+ hcolstep =
+ TDIV((g_ray_hit[row][endcol].xpos - g_ray_hit[row][col].xpos),
+ width, scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first column) */
+
+ ypos.w = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos per column */
+
+ vcolstep =
+ TDIV((g_ray_hit[row][endcol].ypos - g_ray_hit[row][col].ypos),
+ width, scale);
+
+ /* Interpolate to texture each column in the row */
+
+ for (j = col; j <= endcol; j++)
+ {
+ /* Extract the pixel from the texture */
+
+ inpixel = texture[TNDX(xpos.s.i, ypos.s.i, tsize, tmask)];
+
+ /* If this is an INVISIBLE_PIXEL in a TRANSPARENT_WALL, then
+ * we will have to take some pretty extreme measures to get the
+ * correct value of the pixel
+ */
+
+ if ((inpixel == INVISIBLE_PIXEL) &&
+ (IS_TRANSPARENT(g_ray_hit[row][col].rect)))
+ {
+ /* Cast another ray and see if we hit anything */
+
+ if ((inpixel = trv_get_texture(row, j)) != INVISIBLE_PIXEL)
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ outpixel[j] = inpixel;
+ }
+ }
+ else
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ outpixel[j] = palptr[inpixel];
+ }
+
+ /* Now Calculate the horizontal position for the next step */
+
+ xpos.w += hcolstep;
+ ypos.w += vcolstep;
+ }
+#endif
+}
+
+/* This version is for vertical line, i.e., height>1 and width==1 */
+
+static void trv_rend_wallcol(uint8_t row, uint8_t col, uint8_t height)
+{
+#if (!DISABLE_WALL_RENDING)
+ uint8_t i;
+ uint8_t endrow;
+ uint8_t inpixel;
+ FAR uint8_t *palptr;
+ FAR uint8_t *outpixel;
+ uint8_t scale;
+ FAR trv_pixel_t *texture;
+ FAR struct trv_bitmap_s *bmp;
+ union tex_ndx_u ypos;
+ uint16_t tmask;
+ uint16_t tsize;
+ int16_t zone;
+ int16_t xpos;
+ int16_t vrowstep;
+
+ /* Displace the double buffer pointer */
+
+ outpixel = &g_buffer_row[row][g_cell_column+col];
+
+ /* Point to the bitmap associated with the upper pixel. Since
+ * all of the pixels in this cell are the same "hit," we don't have
+ * to recalculate this
+ */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ bmp = g_even_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+ else
+ {
+ bmp = g_odd_bitmaps[g_ray_hit[row][col].rect->texture];
+ }
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ texture = bmp->bm;
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Extract the texture scaling from the rectangle structure */
+
+ scale = g_ray_hit[row][col].rect->scale;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* Within this function, all references to height are really
+ * (height-1)
+ */
+
+ height--;
+
+ /* Get the indices to the lower end */
+
+ endrow = row + height;
+
+ /* Calculate the horizontal interpolation values */
+
+ xpos = sFRAC(g_ray_hit[row][col].xpos >> scale);
+
+ /* Calculate the vertical interpolation values */
+ /* This is the V starting position (first row, first column) */
+
+ ypos.w = TALIGN(g_ray_hit[row][col].ypos, scale);
+
+ /* This is the change in ypos for each row */
+
+ vrowstep =
+ TDIV((g_ray_hit[endrow][col].ypos - g_ray_hit[row][col].ypos),
+ height, scale);
+
+ /* Now, interpolate to texture the vertical line */
+
+ for (i = row; i <= endrow; i++)
+ {
+ /* Extract the pixel from the texture */
+
+ inpixel = texture[TNDX(xpos, ypos.s.i, tsize, tmask)];
+
+ /* If this is an INVISIBLE_PIXEL in a TRANSPARENT_WALL, then
+ * we will have to take some pretty extreme measures to get the
+ * correct value of the pixel
+ */
+
+ if ((inpixel == INVISIBLE_PIXEL) &&
+ (IS_TRANSPARENT(g_ray_hit[row][col].rect)))
+ {
+ /* Check if we hit anything */
+
+ if ((inpixel = trv_get_texture(i, col)) != INVISIBLE_PIXEL)
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ *outpixel = inpixel;
+ }
+ }
+ else
+ {
+ /* Map the normal pixel and transfer the pixel at this
+ * interpolated position
+ */
+
+ *outpixel = palptr[inpixel];
+ }
+
+ /* Point to the next row */
+
+ outpixel += TRV_SCREEN_WIDTH;
+
+ /* Calculate the vertical position for the next step */
+
+ ypos.w += vrowstep;
+ }
+#endif
+}
+
+/* This version is for a single pixel, i.e., height==1 and width==1 */
+
+static void trv_rend_wallpixel(uint8_t row, uint8_t col)
+{
+#if (!DISABLE_WALL_RENDING)
+ uint8_t *palptr;
+ int16_t zone;
+
+ /* Get the a pointer to the palette mapping table */
+
+ if (IS_SHADED(g_ray_hit[row][col].rect))
+ {
+ zone = GET_ZONE(g_ray_hit[row][col].xdist, g_ray_hit[row][col].ydist);
+ palptr = GET_PALPTR(zone);
+ }
+ else
+ {
+ palptr = GET_PALPTR(0);
+ }
+
+ /* The map and transfer the pixel to the display buffer */
+
+ if (IS_FRONT_HIT(&g_ray_hit[row][col]))
+ {
+ g_buffer_row[row][g_cell_column+col] =
+ palptr[GET_FRONT_PIXEL(g_ray_hit[row][col].rect,
+ g_ray_hit[row][col].xpos,
+ g_ray_hit[row][col].ypos)];
+ }
+ else
+ {
+ g_buffer_row[row][g_cell_column+col] =
+ palptr[GET_BACK_PIXEL(g_ray_hit[row][col].rect,
+ g_ray_hit[row][col].xpos,
+ g_ray_hit[row][col].ypos)];
+ }
+#endif
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: trv_rend_backdrop
+ * Description:
+ *
+ * Clear the screen and draw the sky and ground using 32 bit transfers.
+ *
+ ****************************************************************************/
+
+void trv_rend_backdrop(FAR struct trv_camera_s *camera,
+ FAR struct trv_graphics_info_s *ginfo)
+{
+#ifdef ENABLE_VIDEO
+ FAR uint32_t *dest;
+ uint32_t plotpixels;
+ int32_t skyrows;
+ uint16_t buffersize;
+ uint16_t n;
+ int16_t pitchoffset;
+
+ /* The destination of the transfer is the screen buffer */
+
+ dest = (uint32_t*)ginfo->swbuffer;
+
+ /* Convert the pitch angle into signed screen offset */
+
+ if ((pitchoffset = camera->pitch) > ANGLE_90)
+ {
+ pitchoffset -= ANGLE_360;
+ }
+
+ /* Determine the size of the "sky" buffer in rows. Positive pitchoffset
+ * means we are looking up. In this case the sky gets bigger.
+ */
+
+ skyrows = WINDOW_MIDDLE + pitchoffset;
+
+ /* Handle the case where we are looking down and do not see any of the
+ * sky
+ */
+
+ if (skyrows <= 0)
+ {
+ /* No sky rows -- No sky buffersize */
+
+ skyrows = buffersize = 0;
+ }
+
+ /* Copy the sky color into the top half of the screen */
+
+ else
+ {
+ /* Handle the case where we are looking up and see only the sky */
+
+ if (skyrows > WINDOW_HEIGHT)
+ {
+ skyrows = WINDOW_HEIGHT;
+ }
+
+ /* Determine the size of the "sky" buffer in 32-bit units */
+
+ buffersize = (TRV_SCREEN_WIDTH/4) * skyrows;
+
+ /* Combine the sky color into 32-bit "quadruple pixels" */
+
+ plotpixels = (((uint32_t)g_sky_color << 24) |
+ ((uint32_t)g_sky_color << 16) |
+ ((uint32_t)g_sky_color << 8) |
+ (uint32_t)g_sky_color);
+
+ /* Then transfer the "sky" */
+
+ for (n = 0; n < buffersize; n++)
+ {
+ *dest++ = plotpixels;
+ }
+ }
+
+ /* Copy the ground color into the bottom half of the screen */
+
+ if (skyrows < WINDOW_HEIGHT)
+ {
+ /* Determine the size of the "ground" buffer in 32-bit units */
+
+ buffersize = (TRV_SCREEN_WIDTH/4) * (WINDOW_HEIGHT - skyrows);
+
+ /* Combine the ground color into 32-bit "quadruple pixels" */
+
+ plotpixels = (((uint32_t)g_ground_color << 24) |
+ ((uint32_t)g_ground_color << 16) |
+ ((uint32_t)g_ground_color << 8) |
+ (uint32_t)g_ground_color);
+
+ /* Then transfer the "ground" */
+
+ for (n = 0; n < buffersize; n++)
+ {
+ *dest++ = plotpixels;
+ }
+ }
+#endif
+}
+
+/****************************************************************************
+ * Name: trv_rend_cell, trv_rend_row, trv_rend_column, trv_rend_pixel
+ *
+ * Description:
+ * After matching hits have been obtained in all four corners of a cell,
+ * this function interpolates to complete the cell then transfers the cell
+ * to the double buffer.
+ *
+ ****************************************************************************/
+
+/* This version is for non-degenerate cell, i.e., height>1 and width>1 */
+
+void trv_rend_cell(uint8_t row, uint8_t col, uint8_t height, uint8_t width)
+{
+ /* If the cell is visible, then put it in the off-screen buffer.
+ * Otherwise, just drop it on the floor
+ */
+
+ if (g_ray_hit[row][col].rect)
+ {
+ /* Apply texturing... special case for hits on floor or ceiling */
+
+ if (IS_ZRAY_HIT(&g_ray_hit[row][col]))
+ {
+ trv_rend_zcell(row, col, height, width);
+ }
+ else
+ {
+ trv_rend_wall(row, col, height, width);
+ }
+ }
+}
+
+/* This version is for horizontal lines, i.e., height==1 and width>1 */
+
+void trv_rend_row(uint8_t row, uint8_t col, uint8_t width)
+{
+ /* If the cell is visible, then put it in the off-screen buffer.
+ * Otherwise, just drop it on the floor
+ */
+
+ if (g_ray_hit[row][col].rect)
+ {
+ /* Apply texturing... special case for hits on floor or ceiling */
+
+ if (IS_ZRAY_HIT(&g_ray_hit[row][col]))
+ {
+ trv_rend_zrow(row, col, width);
+ }
+ else
+ {
+ trv_rend_wallrow(row, col, width);
+ }
+ }
+}
+
+/* This version is for vertical lines, i.e., height>1 and width==1 */
+
+void trv_rend_column(uint8_t row, uint8_t col, uint8_t height)
+{
+ /* If the cell is visible, then put it in the off-screen buffer.
+ * Otherwise, just drop it on the floor
+ */
+
+ if (g_ray_hit[row][col].rect)
+ {
+ /* Apply texturing... special case for hits on floor or ceiling */
+
+ if (IS_ZRAY_HIT(&g_ray_hit[row][col]))
+ {
+ trv_rend_zcol(row, col, height);
+ }
+ else
+ {
+ trv_rend_wallcol(row, col, height);
+ }
+ }
+}
+
+/* This version is for a single pixel, i.e., height==1 and width==1 */
+
+void trv_rend_pixel(uint8_t row, uint8_t col)
+{
+ /* If the cell is visible, then put it in the off-screen buffer.
+ * Otherwise, just drop it on the floor
+ */
+
+ if (g_ray_hit[row][col].rect)
+ {
+ /* Apply texturing... special case for hits on floor or ceiling */
+
+ if (IS_ZRAY_HIT(&g_ray_hit[row][col]))
+ {
+ trv_rend_zpixel(row, col);
+ }
+ else
+ {
+ trv_rend_wallpixel(row, col);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: trv_get_rectpixel
+ *
+ * Description:
+ * Returns the pixel for a hit at (xpos, ypos) on rect.
+ *
+ ****************************************************************************/
+
+trv_pixel_t trv_get_rectpixel(int16_t xpos, int16_t ypos,
+ FAR struct trv_bitmap_s *bmp, uint8_t scale)
+{
+ uint16_t tmask;
+ uint16_t tsize;
+
+ /* Get parameters associated with the size of the bitmap texture */
+
+ tsize = bmp->log2h;
+ tmask = TMASK(tsize);
+
+ /* Return the texture code at this position */
+
+ return(bmp->bm[TNDX((xpos >> scale), (ypos >> scale), tsize, tmask)]);
+}
+