From 7433c4a86d4d473bd5a33fa5c18b0128e794bd6b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 5 Dec 2014 08:44:55 -0600 Subject: [PATCH] Add first of several ray cast/rendering files --- graphics/traveler/Makefile | 9 +- graphics/traveler/include/trv_bitmaps.h | 44 + graphics/traveler/include/trv_color.h | 6 +- graphics/traveler/include/trv_paltable.h | 82 ++ graphics/traveler/include/trv_raycast.h | 166 +++ graphics/traveler/include/trv_raycntl.h | 1 + graphics/traveler/include/trv_rayrend.h | 40 +- graphics/traveler/include/trv_trigtbl.h | 58 + graphics/traveler/src/trv_main.c | 2 +- graphics/traveler/src/trv_rayrend.c | 1337 ++++++++++++++++++++++ 10 files changed, 1735 insertions(+), 10 deletions(-) create mode 100644 graphics/traveler/include/trv_paltable.h create mode 100644 graphics/traveler/include/trv_raycast.h create mode 100755 graphics/traveler/src/trv_rayrend.c diff --git a/graphics/traveler/Makefile b/graphics/traveler/Makefile index 0c4c0e600..6bbfe7aed 100644 --- a/graphics/traveler/Makefile +++ b/graphics/traveler/Makefile @@ -37,16 +37,17 @@ -include $(TOPDIR)/Make.defs include $(APPDIR)/Make.defs -# Hello, World! built-in application info +# Traveler built-in application info APPNAME = traveler PRIORITY = SCHED_PRIORITY_DEFAULT STACKSIZE = 2048 -# Hello, World! Example +# Traveler files -ASRCS = -CSRCS = trv_color.c trv_doors.c trv_graphics.c trv_input.c trv_mem.c trv_pov.c +ASRCS = +CSRCS = trv_color.c trv_doors.c trv_graphics.c trv_input.c trv_mem.c trv_pov.c +CSRCS += trv_rayrend.c MAINSRC = trv_main.c ifeq ($(CONFIG_NX),y) diff --git a/graphics/traveler/include/trv_bitmaps.h b/graphics/traveler/include/trv_bitmaps.h index 2bd3cb0b6..71ecc25ce 100644 --- a/graphics/traveler/include/trv_bitmaps.h +++ b/graphics/traveler/include/trv_bitmaps.h @@ -47,10 +47,54 @@ * Pre-processor Definitions ****************************************************************************/ +#define BITMAP_WIDTH 64 +#define BITMAP_HEIGHT 64 +#define BITMAP_LOG2H 6 +#define BITMAP_SIZE (BITMAP_WIDTH * BITMAP_HEIGHT) +#define BITMAP_IMASK (BITMAP_HEIGHT-1) +#define BITMAP_JMASK (BITMAP_WIDTH-1) +#define BITMAP_JSHIFT 6 +#define BMICLIP(i) ((i) & BITMAP_IMASK) +#define BMJCLIP(i) ((i) & BITMAP_JMASK) +#define BMOFFSET(i,j) (((i) << BITMAP_JSHIFT) | (j)) +#define MAX_BITMAPS 256 + /**************************************************************************** * Public Types ****************************************************************************/ +struct trv_bitmap_s +{ + uint16_t w; + uint16_t h; + uint8_t log2h; + FAR trv_pixel_t *bm; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These point to the (allocated) bit map buffers for the even and odd + * bitmaps + */ + +extern struct trv_bitmap_s *g_even_bitmaps[MAX_BITMAPS]; +#ifndef WEDIT +extern struct trv_bitmap_s *g_odd_bitmaps[MAX_BITMAPS]; +#endif + +/* This is the maximum value + 1 of a texture code */ + +extern uint16_t g_trv_nbitmaps; + +/* These are the colors from the worldPalette which should used to rend + * the sky and ground + */ + +extern trv_pixel_t g_sky_color; +extern trv_pixel_t g_ground_color; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/graphics/traveler/include/trv_color.h b/graphics/traveler/include/trv_color.h index 9e8f8abb1..313001b7c 100644 --- a/graphics/traveler/include/trv_color.h +++ b/graphics/traveler/include/trv_color.h @@ -91,9 +91,9 @@ struct trv_color_rgb_s { - uint8_t red; - uint8_t green; - uint8_t blue; + uint8_t red; /* red component of color 0-63 */ + uint8_t green; /* green component of color 0-63 */ + uint8_t blue; /* blue component of color 0-63 */ }; struct trv_color_lum_s diff --git a/graphics/traveler/include/trv_paltable.h b/graphics/traveler/include/trv_paltable.h new file mode 100644 index 000000000..38df97473 --- /dev/null +++ b/graphics/traveler/include/trv_paltable.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * apps/graphics/traveler/include/trv_paltable.h + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_PALTABLE_H +#define __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_PALTABLE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "trv_types.h" + +/**************************************************************************** + * Pre-processor + ****************************************************************************/ + +/* Here some palette-related definitions. */ + +#define PALETTE_SIZE 256 /* This is the number of colors in the palette */ +#define NUM_ZONES 16 /* This is the number of distance zones in the palette table */ + +/* Here are some macros used to access the palette table. */ + +#define PAL_SCALE_BITS 2 +#define GET_DISTANCE(x,y) ( (x) >= (y) ? ((x) + ((y) >>1)) : ((y) + ((x) >>1))) +#define GET_ZONE(x,y) (GET_DISTANCE(x,y) >> (sSHIFT+PAL_SCALE_BITS)) +#define GET_PALINDEX(d) ((d) >= NUM_ZONES ? (NUM_ZONES-1) : (d)) +#define GET_PALPTR(d) g_paltable[GET_PALINDEX(d)] + +/* This is a special version which is used by the texture logic. The + * texture engine used 8 bits of fraction in many of its calculation + */ + +#define GET_FZONE(x,y,n) (GET_DISTANCE(x,y) >> (sSHIFT+PAL_SCALE_BITS-(n))) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This is the palette table which is used to adjust the texture values + * with distance + */ + +extern trv_pixel_t *g_paltable[NUM_ZONES]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_PALTABLE_H */ diff --git a/graphics/traveler/include/trv_raycast.h b/graphics/traveler/include/trv_raycast.h new file mode 100644 index 000000000..472f0dcae --- /dev/null +++ b/graphics/traveler/include/trv_raycast.h @@ -0,0 +1,166 @@ +/**************************************************************************** + * apps/graphics/traveler/include/trv_raycast.h + * This is the header file associated with trv_raycast.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * + ****************************************************************************/ + +#ifndef __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYCAST_H +#define __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYCAST_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "trv_types.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The following definitions define the world view window in terms of the + * 320x200 display coordinates. + */ + +#define WINDOW_LEFT 0 /* Offset (in bytes) to the left side + * of the world window */ +#define WINDOW_WIDTH 320 /* Width of the world window */ +#define WINDOW_TOP 0 /* Offset (in multiples of TRV_SCREEN_WIDTH) + * to the top of world window */ +#define WINDOW_HEIGHT 200 /* height of the world window */ +#define WINDOW_MIDDLE 100 /* Center or horizon of the world window */ + +/* This calculation tends to overflow unless it is cast carefully */ + +#define WINDOW_SIZE (((int32_t)WINDOW_WIDTH)*((int32_t)WINDOW_HEIGHT)) + +/* This is the biggest distance that can be represented with int16_t */ + +#define TRV_INFINITY 0x7fff + +/* The actual size of the image will be determined by the + * both the WINDOW size as well as the GULP size + */ + +#define NUMBER_HGULPS (WINDOW_WIDTH/HGULP_SIZE) +#define IMAGE_WIDTH (HGULP_SIZE*NUMBER_HGULPS) +#define IMAGE_LEFT (((WINDOW_WIDTH-IMAGE_WIDTH) >> 1) + WINDOW_LEFT) +#define IMAGE_HEIGHT WINDOW_HEIGHT +#define IMAGE_TOP WINDOW_TOP + +/* This defines the number of pixels (in each direction) with will be + * processed on each pass through the innermost ray casting loop + */ + +#define HGULP_SIZE 7 +#define VGULP_SIZE 16 + +/* The following define the various meanings of hit.type */ + +#define NO_HIT 0x00 +#define FRONT_HIT 0x00 +#define BACK_HIT 0x01 +#define FB_MASK 0x01 +#define X_HIT 0x00 +#define Y_HIT 0x02 +#define Z_HIT 0x04 +#define XYZ_MASK 0x06 + +#define IS_FRONT_HIT(h) (((h)->type & FB_MASK) == FRONT_HIT) +#define IS_BACK_HIT(h) (((h)->type & FB_MASK) == BACK_HIT) +#define IS_XRAY_HIT(h) (((h)->type & XYZ_MASK) == X_HIT) +#define IS_YRAY_HIT(h) (((h)->type & XYZ_MASK) == Y_HIT) +#define IS_ZRAY_HIT(h) (((h)->type & XYZ_MASK) == Z_HIT) + +#define MK_HIT_TYPE(fb,xyz) ((fb)|(xyz)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This structure provides the return values for each ray caster. For + * performance reasons, the size of this structure should be an even + * power of two (makes index calculation faster). + */ + +struct trv_rect_data_s; +struct trv_raycast_s +{ + /* 'rect' points to the rectangle that was hit (if any) */ + + FAR struct trv_rect_data_s *rect; + + uint8_t type; /* Type of hit: X/Y/Z cast, front/back */ + uint8_t unused2; /* Padding to force power of two size */ + int16_t xpos; /* Horizontal position on surface of the hit */ + int16_t ypos; /* Vertical position on surface of the hit */ + int16_t xdist; /* X distance to the hit */ + int16_t ydist; /* Y distance to the hit */ + int16_t zdist; /* Z distance to the hit (not used) */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This structure holds pre-calculated pitch data for all ray casts. NOTE: + * would be a performance improvement if this structure is an even power of + *two in size (don't have to multiply to calculate indices) + */ + +/* The following array describes the hits from X/Y/Z-ray casting for the + * current HGULP_SIZE x VGULP_SIZE cell + */ + +extern struct trv_raycast_s g_ray_hit[VGULP_SIZE][HGULP_SIZE+1]; + +/* This structure points to the double buffer row corresponding to the + * pitch angle + */ + +extern uint8_t *g_buffer_row[VGULP_SIZE]; + +/* The is the "column" offset in g_buffer_row for the current cell being + * operated on. This value is updated in a loop by trv_raycaster. + */ + +extern int16_t g_cell_column; + +/* This structure holds the parameters used in the current ray cast */ + +extern struct trv_camera_s g_camera; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYCAST_H */ diff --git a/graphics/traveler/include/trv_raycntl.h b/graphics/traveler/include/trv_raycntl.h index 47bc6bf54..7726c2006 100644 --- a/graphics/traveler/include/trv_raycntl.h +++ b/graphics/traveler/include/trv_raycntl.h @@ -64,5 +64,6 @@ struct trv_graphics_info_s; void trv_raycaster(FAR struct trv_camera_s *player, FAR struct trv_graphics_info_s *ginfo); +uint8_t trv_get_texture(uint8_t row, uint8_t col); #endif /* __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYCNTL_H */ diff --git a/graphics/traveler/include/trv_rayrend.h b/graphics/traveler/include/trv_rayrend.h index 189e17e46..5ae77f59a 100644 --- a/graphics/traveler/include/trv_rayrend.h +++ b/graphics/traveler/include/trv_rayrend.h @@ -41,12 +41,37 @@ ****************************************************************************/ #include "trv_types.h" -#include "trv_world.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* The following macro calculates the texture index for the given the + * horizontal position (h), the vertical position (v) and the log2 bitmap + * size (s). + */ + +#define TMASK(s) ((1 << (s)) - 1) +#define TFIX(x,s) ((x) << (s)) +#define TFRAC(x,m) ((x) & (m)) +#define TNDX(h,v,s,m) (TFIX( TFRAC( (~(v)), m ), s) + TFRAC( h, m ) ) + +/* Here is a macro to extract one pixel from a WALL texture. This is used + * by the raycasters to determine a hit in a transparent wall hit an + * opaque portion of the texture + */ + +#define GET_FRONT_PIXEL(r,h,v) \ + trv_get_rectpixel(h,v,g_even_bitmaps[ (r)->texture ], (r)->scale) +#define GET_BACK_PIXEL(r,h,v) \ + trv_get_rectpixel(h,v,g_odd_bitmaps[ (r)->texture ], (r)->scale) + +/* This is special value of a pixel in a "grandparent" rectangle which means + * that the pixel is transparent. + */ + +#define INVISIBLE_PIXEL 0 + /**************************************************************************** * Public Types ****************************************************************************/ @@ -55,6 +80,17 @@ * Public Function Prototypes ****************************************************************************/ -void trv_rend_backdrop (struct trv_camera_s *camera); +struct trv_camera_s; +struct trv_graphics_info_s; +struct trv_bitmap_s; + +void trv_rend_backdrop(FAR struct trv_camera_s *camera, + FAR struct trv_graphics_info_s *ginfo); +void trv_rend_cell(uint8_t row, uint8_t col, uint8_t height, uint8_t width); +void trv_rend_row(uint8_t row, uint8_t col, uint8_t width); +void trv_rend_column(uint8_t row, uint8_t col, uint8_t height); +void trv_rend_pixel(uint8_t row, uint8_t col); +trv_pixel_t trv_get_rectpixel(int16_t hPos, int16_t vPos, + FAR struct trv_bitmap_s *bmp, uint8_t scale); #endif /* __APPS_GRAPHICS_TRAVELER_INCLUDE_TRV_RAYEND_H */ diff --git a/graphics/traveler/include/trv_trigtbl.h b/graphics/traveler/include/trv_trigtbl.h index deac5a0fb..999270a12 100644 --- a/graphics/traveler/include/trv_trigtbl.h +++ b/graphics/traveler/include/trv_trigtbl.h @@ -45,6 +45,7 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Angles *******************************************************************/ /* These are definitions of commonly used angles. */ @@ -69,6 +70,63 @@ #define ANGLE_270 1440 #define ANGLE_360 1920 +/* Fixed precision definitions **********************************************/ + +/* SMALL precision (6 bits past binary point) */ +/* This occurs frequently because each CELL is 64x64 */ + +#define sUNITY 64 +#define sHALF 32 +#define sQUARTER 16 +#define sSHIFT 6 +#define sMASK 63 + +#define sTRUNC(a) ((a) >> sSHIFT) +#define sROUND(a) (((a) + sHALF) >> sSHIFT) +#define sFIX(a) ((a) << sSHIFT) +#define sSNAP(a) ((a) & (~sMASK)) +#define sFRAC(a) ((a) & sMASK) + +#define sMUL(a,b) (((int32_t)(a) * (int32_t)(b)) >> sSHIFT ) +#define sDIV(a,b) (((int32_t)(a) << sSHIFT) / (b)) +#define sFLOAT(a) ((float)(a) / (float)sUNITY) + +/* DOUBLE precision (12 bits past binary point) */ +/* This precision results when two SMALL precision numbers are multiplied */ + +#define dUNITY 4096 +#define dHALF 2048 +#define dSHIFT 12 +#define dMASK 4095 + +#define dTRUNC(a) ((a) >> dSHIFT) +#define dROUND(a) (((a) + dHALF) >> dSHIFT) +#define dFIX(a) ((a) << dSHIFT) +#define dSNAP(a) ((a) & (~dMASK)) +#define dFRAC(a) ((a) & dMASK) + +/* TRIPLE precision (18 bits past binary point) */ +/* This precision results when a SMALL and a DOUBLE precision number + * are multiplied + */ + +#define tSHIFT 18 + +/* QUAD precision (24 bits past binary point) */ +/* This precision results when two DOUBLE precision numbers are multiplied */ + +#define qSHIFT 24 + +/* BIG precision (16 bits past binary point) */ +/* This is convenient precision because it is easy to extract the integer + * portion without shifting or masking + */ + +#define bUNITY 65536 +#define bHALF 32768 +#define bSHIFT 16 +#define bMASK 65535 + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/graphics/traveler/src/trv_main.c b/graphics/traveler/src/trv_main.c index 594513a9a..bafd5cb1c 100644 --- a/graphics/traveler/src/trv_main.c +++ b/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/graphics/traveler/src/trv_rayrend.c b/graphics/traveler/src/trv_rayrend.c new file mode 100755 index 000000000..f9c45c3ad --- /dev/null +++ b/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 + * + * 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)]); +} +