diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-12-05 08:44:55 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-12-05 08:44:55 -0600 |
commit | d2b407f9f9272b8f7dbc97c494d11f2468157363 (patch) | |
tree | ba1c4b3164a826bb440266d48b82031b9c0f4d5c /apps/graphics/traveler/src/trv_rayrend.c | |
parent | 86e5c3a5b0792e9234f98e4aeb1c0721b56352b2 (diff) | |
download | nuttx-d2b407f9f9272b8f7dbc97c494d11f2468157363.tar.gz nuttx-d2b407f9f9272b8f7dbc97c494d11f2468157363.tar.bz2 nuttx-d2b407f9f9272b8f7dbc97c494d11f2468157363.zip |
Add first of several ray cast/rendering files
Diffstat (limited to 'apps/graphics/traveler/src/trv_rayrend.c')
-rwxr-xr-x | apps/graphics/traveler/src/trv_rayrend.c | 1337 |
1 files changed, 1337 insertions, 0 deletions
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)]); +} + |