RAYCAST.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:33k
- /*********************
- Portions of this code taken from Programming Gurus book by Waite Group
- Most written for super speed game on '040 by Joshua Glazer
- Those portions are Copyright Joshua Glazer c1994
- Lightening fast two-level Fixed Point Routines Copyright Joshua Glazer c1994
- These routines may be used by one Matthew Howard, but
- credit must be given to Joshua Glazer c1994
- **** Yea, well I wrote some nice asm routines for IBM so, you can give Matt Howard -1994
- a little credit too! ****
- I like writing Joshua Glazer c1994
- Violaters of the Copyright law violated by violating this source-code
- will be hunted down and castrated (or spayed) by Joshua Glazer c1994
- This means you!
- Actually, 'This' is a pronoun used to refer to a subject being talked about
- which is closer to the speaker than some other object.
- Oh Shut Up.
- Copyright Joshua Glazer c1994
- *********************/
- #include "asm.h"
- #include "ray.h"
- #include "rayrend.h"
- #include "raycl.h"
- #include "rayvb.h"
- #include "assert.h"
- #include "globals.h"
- #include "fixed.h"
- #include <mem.h>
- #include "mymem.h"
- #include <math.h>
- #include "asm.h"
- #include "prevarr.h"
- #include "voxinter.h"
- #include "texconst.h"
- #include "scrconf.h"
- #include "ldattrib.h"
- #include <stdio.h>
- #include <stdlib.h>
- #define BLACK_COLOR 240
- #define SS_NO_VISIBLE -1
- #define SS_VISIBLE 0
- #define LOW_WALL 0
- #define HIGH_WALL 1
- #define MID_WALL 2
- #define CLIP
- #define CHECK_HIGH_LOW_CLIP_OUT
- #define CLIPVERT
- #define DO_FLOORS
- #define BAR_LENGTH 10
- #define RED_COLOR 79
- typedef struct WALL_MOVE_INFO {
- MYFIXED top_start, bottom_start;
- MYFIXED top_increment, bottom_increment;
- ptexture texture;
- short type;
- long v_height;
- vb_node * cur_bounds;
- } wall_move_info;
- typedef struct INTERSECT_STRUCT {
- long distance, xpos;
- MYFIXED increment;
- } intersect_struct;
- intersect_struct * intersects;
- MYFIXED * floor_offsets_x;
- MYFIXED * floor_offsets_y;
- long v_angle_plus_90;
- MYFIXED floor_trans_x, floor_trans_y;
- short prev_win_top, prev_win_bottom,
- prev_wall_top, prev_wall_bottom, proj_left, proj_right;
- short floor_ray, floor_start, floor_end, cur_height_diff;
- Byte * floor_texture;
- Byte * cur_sky_texture;
- sector * Cur_Sec;
- long ssetup_count;
- void Seg_Setup(wall_move_info & mid_walls);
- void Get_Intersects(pvector2 base_v, angle_type angle_diff);
- void Draw_Seg(seg * cur_seg);
- /*
- Draw_Health
- Draws a bar for player's health
- */
- void Draw_Health() {
- long the_health=the_player->stats.current_health;
- long start_pos=Get_Phys_Screen_Width()*(Get_Phys_Screen_Height()-BAR_LENGTH);
- for (short cur_vert=0; cur_vert<BAR_LENGTH; cur_vert++) {
- memset(buff+start_pos+(cur_vert*Get_Phys_Screen_Width()), RED_COLOR, the_health);
- }
- }
- /*
- Win_Bounds_Setup
- Just initializes bounding values before a draw to all 0's for top and
- WINDOW_HEIGHT for bottom
- */
- inline void Win_Bounds_Setup()
- {
- memset(win_tops, 0, WINDOW_WIDTH * sizeof(short));
- memsetshort(win_bottoms, WINDOW_HEIGHT, WINDOW_WIDTH);
- }
- /*
- Init_Floor_Values
- Initializes values used for floor drawing
- Notes: None
- */
- inline void Init_Floor_Values()
- {
- // might as well calculate an angle that is used all the time for drawing floors
- v_angle_plus_90=Get_Angle_Difference(render_view_angle, ANGLE_90);
- floor_trans_x=fixedmult(x_inv_trans, rcos_table[v_angle_plus_90]);
- floor_trans_y=fixedmult(x_inv_trans, rsin_table[v_angle_plus_90]);
- long floor_adder_x=floor_trans_x >> X_TRANS_SHIFT;
- long floor_adder_y=floor_trans_y >> X_TRANS_SHIFT;
- long floor_sum_x=floor_adder_x * (-WINDOW_MIDDLEW);
- long floor_sum_y=floor_adder_y * (-WINDOW_MIDDLEW);
- for (short cur_ray=0; cur_ray < (WINDOW_WIDTH); cur_ray++) {
- floor_offsets_x[cur_ray]=floor_sum_x;
- floor_offsets_y[cur_ray]=floor_sum_y;
- floor_sum_x+=floor_adder_x;
- floor_sum_y+=floor_adder_y;
- }
- }
- /*
- Start_Tex
- Marks starts of texture lines on rows from "start" up to but not including "end at x position "ray"
- Notes: Assumes floor_texture already points to the floor texture to draw
- */
-
- inline void Start_Tex() {
- short row;
- for (row=floor_start; row<floor_end; row++) {
- tex_mark_table[row]=floor_ray;
- }
- }
- /*
- Finish_Tex
- Draws the previously marked floor textures on rows from "start" up to but no including "end"
- Ends lines at "ray"
- Notes: Assumes floor_texture already points to the floor texture to draw
- */
- inline void Finish_Tex() {
-
- short row, start_ray;
- long tempLight;
- MYFIXED distance_fixed;
- floor_run_info * cur_floor_run;
- for (row=floor_start; row<floor_end; row++) {
- start_ray=tex_mark_table[row];
- if (floor_ray<=start_ray)
- continue;
- if (floor_run_count>=MAX_FLOOR_RUNS)
- break;
- cur_floor_run=floor_runs+floor_run_count;
- floor_run_count++;
- // Set row to draw on
- cur_floor_run->screen_y=row;
- // Get starting x and width of texture
- cur_floor_run->scale=(short)(floor_ray-start_ray);
- cur_floor_run->screen_x=start_ray;
- // Get distance to floor
- distance_fixed=cur_height_diff *distance_table[row];
- Assert(distance_fixed < 0, "Negative floor row distance");
- // Get map starting positions
- cur_floor_run->map_x=fixedmult(rcos_table[render_view_angle] +
- floor_offsets_x[start_ray], distance_fixed)+(render_x);
- cur_floor_run->map_y=fixedmult(rsin_table[render_view_angle] +
- floor_offsets_y[start_ray], distance_fixed)+(render_y);
- // Get increments by multiplying the increment along the actual line by sin & cos of line angle
- cur_floor_run->x_inc=fixedmult(distance_fixed,
- floor_trans_x) >> X_TRANS_SHIFT;
- cur_floor_run->y_inc=fixedmult(distance_fixed,
- floor_trans_y) >> X_TRANS_SHIFT;
- // do light calculation
- // In getting the light value, we take into account that distance_fixed
- // is a fixed point number and add to the right shift the fixed point conversion
- // number
- tempLight=(SecLight(Cur_Sec)-
- (distance_fixed >> (SHIFT+SecLTSpeed(Cur_Sec))) );
- if (tempLight<0) tempLight=0;
- if (tempLight>MAX_LIGHT) tempLight=MAX_LIGHT;
- Assert(((tempLight <0) || (tempLight >MAX_LIGHT)), "Bad Lighting Value");
- cur_floor_run->light=pal_table[tempLight];
- cur_floor_run->texture=floor_texture;
- } /* endfor */
- }
- /*
- Draw_Sky_Column
- Draws one column of the sky texture from "top" down to but not including "bottom"
- Notes: This is a hack. Code is cryptic. Should be improved upon. For example, it should
- not require that sky texture be length of screen. Requires a theoretical
- understanding of screen rays intersecting a circle on the horizon that I don't have
- */
- inline void Draw_Sky_Column()
- {
- // Was the programmer such an idiot that he tried to draw column of length 0?
- if (floor_start>=floor_end)
- return;
- if (wall_run_count>=MAX_WALL_RUNS) {
- return;
- } /* endif */
- wall_run_info * cur_wall_run=wall_runs+wall_run_count;
- wall_run_count++;
- // Setup the render constants, pretty standard
- cur_wall_run->bound_val=SKY_HEIGHT-1;
- cur_wall_run->texture=cur_sky_texture;
- cur_wall_run->ray=floor_ray;
- cur_wall_run->top=floor_start;
- cur_wall_run->scale=floor_end-floor_start;
- cur_wall_run->clip=floor_start << SLIVER_SHIFT;
- cur_wall_run->light=pal_table[MAX_LIGHT];
- cur_wall_run->increment=SLIVER_ONE;
- cur_wall_run->width_shift=SKY_SHIFT;
- // Do a whole lot of stupid calculations to get the column in the texture to draw
- long temp_column;
- long temp_ray=floor_ray*HORIZ_VIEW_RANGE/WINDOW_WIDTH;
- long tempAngle;
- if (temp_ray<(HORIZ_VIEW_RANGE>>1))
- tempAngle=temp_ray;
- else tempAngle=Get_Angle_Difference(HORIZ_VIEW_RANGE, temp_ray);
- MYFIXED tempdiv=fixeddiv(tan_table[tempAngle],
- tan_table[HORIZ_VIEW_RANGE>>1]);
- tempdiv=convtoLONG((HORIZ_VIEW_RANGE>>1)*tempdiv);
- if (temp_ray>=(HORIZ_VIEW_RANGE>>1))
- tempdiv=HORIZ_VIEW_RANGE-tempdiv;
- // div by 2 to stretch out backround a little
- temp_column=(((HORIZ_VIEW_RANGE>>1)-tempdiv)+(render_view_angle));
-
- if (temp_column<0) {
- cur_wall_run->column=SKY_WIDTH-((-temp_column) % SKY_WIDTH);
- } else {
- cur_wall_run->column=temp_column % SKY_WIDTH;
- } /* endif */
- }
- /*
- Close_Textures
- Finishes up whatever textures were running in a given visible section
- Notes: Uses proj_right and the "prev" globals
- */
- inline void Close_Textures(short closing_ray)
- {
- long floor_height_diff=render_z-Cur_Sec->floor_height;
- long ceil_height_diff=Cur_Sec->ceil_height-render_z;
- floor_ray=closing_ray;
- floor_texture=Get_Floor_Texture(Cur_Sec->ceil_tex);
- floor_start=prev_win_top; floor_end=prev_wall_top;
- if ( ceil_height_diff>0 && floor_texture!=cur_sky_texture ) {
- Finish_Tex();
- } /* endif */
- floor_texture=Get_Floor_Texture(Cur_Sec->floor_tex);
- floor_start=prev_wall_bottom; floor_end=prev_win_bottom;
- if ( floor_height_diff>0 && floor_texture!=cur_sky_texture ) {
- Finish_Tex();
- } /* endif */
- }
- /*
- SegVisible
- Decides if a seg is (a) visible and (b) facing you
- */
- inline BOOL SegVisible(seg * cur_seg)
- {
- long x1, x2, y1, y2;
- pvector2 v1, v2;
- v1=Vector_List+cur_seg->v[0];
- v2=Vector_List+cur_seg->v[1];
- x1=v1->x;
- x2=v2->x;
- y1=v1->y;
- y2=v2->y;
- if ( fixedmult((x1-x2),(render_y-(y2<<SHIFT))) >= fixedmult((y1-y2),(render_x-(x2<<SHIFT))) ) {
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
- /////////////////////////////////////////////////////////////////////////////
- /*
- Ray_Caster
- The all powerful function that renders the screen
- Notes: Well, it isn't really all powerful. After all, it's just a routine,
- not some sort of diety. It dosen't even do that much, just calls other routines
- */
- void Ray_Caster(long x, long y, long z, long view_angle)
- {
- ssetup_count=0;
- // setup rendering constants
- render_x=x; render_y=y; render_z=z; render_view_angle=view_angle;
- // setup constants for floor drawing
- Init_Floor_Values();
- // save the current frame of the sky animation
- // (we will say that sky texture cannot change while rendering)
- cur_sky_texture=sky_texture->images[sky_texture->cur_image];
- // Initialize the clipping structures
- Win_Bounds_Setup();
- VB_InitList();
- // Set starting wall & floor run count to 0
- wall_run_count=0;
- floor_run_count=0;
- // initialize voxel colors
- memset((PUCHAR)prev_colors, BLACK_COLOR, Get_Phys_Screen_Width());
- // Turn over control to the bsp tracer
- BSP_Recursion_Draw();
- // If we have any floors, it's probably a good idea to render them
- if (floor_run_count>0) {
- Render_Floor_asm();
- } /* endif */
- // If we have any walls, its probably a good idea to render them too...
- if (wall_run_count>0) {
- Render_Sliver_asm();
- } /* endif */
- Draw_Health();
- }
- /*
- Draw_Sub_Sector
- Big time importance in this routine. Basically, it draws a sub sector (i.e. portion that cannot
- obscure any of itself). Does most of the hard calculations. Well, not anymore, Draw_Seg does
- now
- Notes: Still has problems, may crash system if you run it on sub sectors that are behind the player
- */
- void Draw_Sub_Sector(pssector cur_ss)
- {
- short cur_seg, num_segs, counter;
- // do dem sprites
- if (cur_ss->flags & VOXEL_SSECTOR) {
- Render_Voxel_Sub_Sector(cur_ss);
- } else {
- Draw_SS_Sprites(cur_ss);
- }
- cur_seg=cur_ss->seg_start;
- num_segs=cur_ss->seg_end-cur_ss->seg_start+1;
- for (counter=0; counter<num_segs; counter++) {
- if (SegVisible(Seg_List+cur_seg)) {
- Draw_Seg(Seg_List+cur_seg);
- } /* endif */
- if (VB_EmptyList())
- return;
- cur_seg++;
- } /* endfor */
- }
- /*
- Draw_Seg
- Just what it sounds like. Draws a seg. Calls Seg_Setup & Get_Intersects.
- Does some vector translation
- Notes: Not proven to always work. But then again, neither is nutrisweet.
- */
- void Draw_Seg(seg * cur_seg)
- {
- LONG abs_proj_left, abs_proj_right;
- LONG distance_left, distance_right;
- sector * Opp_Sec;
-
- sidedef * cur_sd;
- pvector2 v1,v2;
- vector2 vtrans1, vtrans2;
- pvb_node cur_bounds, next_bounds;
- wall_move_info low_wall, mid_wall, high_wall;
- BOOL mid_wall_exists, low_wall_exists, high_wall_exists, any_wall_exists;
- MYFIXED
- end_seg_top,
- end_seg_bottom,
- low_seg_top,
- high_seg_bottom;
- BOOL found;
- SHORT bounds_to_draw, bounds_done;
- short wall_height;
- angle_type seg_angle_diff;
- cur_bounds=VB_GetFirstNode();
- // Get the sector
- Cur_Sec=GetSecFromSeg(cur_seg);
- Assert(((Cur_Sec < Sector_List)||(Cur_Sec >= (Sector_List+Number_Of_Sectors))),
- "Invalid sector in Draw_Seg");
- v1=Vector_List+cur_seg->v[0];
- v2=Vector_List+cur_seg->v[1];
- // Translate Vectors
- // I use y for distance, but technically it ought to be x, so I switch x and y when translated
- rotate_angle=render_view_angle;
- rotate_x=(v1->x<<SHIFT) - render_x;
- rotate_y=(v1->y<<SHIFT) - render_y;
- vtrans1.x=FixedRotateY();
- vtrans1.y=FixedRotateX();
- rotate_x=(v2->x<<SHIFT) - render_x;
- rotate_y=(v2->y<<SHIFT) - render_y;
- vtrans2.x=FixedRotateY();
- vtrans2.y=FixedRotateX();
- // clip for lines in back of and in front of view window
- if ((vtrans1.y<=0)&&(vtrans2.y<=0))
- return;
- if ((vtrans1.y>= (MAXDIS<<SHIFT) ) || (vtrans2.y>= (MAXDIS<<SHIFT) ))
- return;
- // Get projected screen coordinates
- if (vtrans1.y>0) {
- abs_proj_left=(fixedmd(-vtrans1.x, SCALE_FACTOR, vtrans1.y) )
- +WINDOW_MIDDLEW;
- } /* endif */
- if (vtrans2.y>0) {
- abs_proj_right=(fixedmd(-vtrans2.x, SCALE_FACTOR, vtrans2.y) )
- +WINDOW_MIDDLEW;
- } /* endif */
- // Is this seg past the bounding window
-
- if (vtrans1.y>0) {
- found=FALSE;
- while ( (cur_bounds!=NULL) ) {
- if (abs_proj_left < cur_bounds->right) {
- found=TRUE;
- break;
- } /* endif */
- cur_bounds=VB_GetNextNode(cur_bounds);
- }
- if (!found) {
- return;
- }
- }
- // count number of bounding windows to draw in
- if (vtrans2.y<=0)
- abs_proj_right=WINDOW_WIDTH;
- next_bounds=cur_bounds;
- bounds_to_draw=0;
- while (next_bounds!=NULL) {
- if (abs_proj_right <= next_bounds->left)
- break;
- bounds_to_draw++;
- next_bounds=VB_GetNextNode(next_bounds);
- } /* endwhile */
- if (bounds_to_draw==0)
- return;
-
- Opp_Sec=GetOppSec(cur_seg);
- cur_sd=cur_seg->ld->s[cur_seg->left_sidedef];
- // Necessary to get intersections on seg
- seg_angle_diff=Get_Angle_Difference(cur_seg->angle, render_view_angle);
- Setup_Intersection(&vtrans1, &vtrans2);
- next_bounds=cur_bounds;
- // Do we have a middle texture
- if ( (cur_sd->texture_normal!=TEXTURE_NULL) ) {
- mid_wall_exists=TRUE;
- } else mid_wall_exists=FALSE;
- if ( (Opp_Sec!=NULL) &&
- (cur_sd->texture_low!=TEXTURE_NULL) &&
- (Opp_Sec->floor_height > Cur_Sec->floor_height) )
- low_wall_exists=TRUE;
- else low_wall_exists=FALSE;
- if ( (Opp_Sec!=NULL) &&
- (cur_sd->texture_high!=TEXTURE_NULL) &&
- (Opp_Sec->ceil_height < Cur_Sec->ceil_height) )
- high_wall_exists=TRUE;
- else high_wall_exists=FALSE;
- any_wall_exists=(((mid_wall_exists) || (low_wall_exists) || (high_wall_exists)) ? TRUE : FALSE);
- wall_height=Cur_Sec->ceil_height-Cur_Sec->floor_height;
- if (wall_height<=0) {
- return;
- } /* endif */
- for (bounds_done=0; bounds_done <bounds_to_draw; bounds_done++) {
- cur_bounds=next_bounds;
- next_bounds=VB_GetNextNode(next_bounds);
- Assert( ((cur_bounds < bounds) || (cur_bounds >= (bounds+WINDOW_WIDTH))),
- "Attempting to draw to invalid bounds area");
- // Setup up distance and projection values we will derive line movements from
- if ( (vtrans1.y <= 0) || (abs_proj_left < cur_bounds->left) ) {
- proj_left=cur_bounds->left;
- distance_left=Get_Intersection_Y(cur_bounds->left);
- } else {
- proj_left=abs_proj_left;
- distance_left=vtrans1.y;
- } /* endif */
- if ( (vtrans2.y <= 0) || (abs_proj_right > cur_bounds->right) ) {
- proj_right=cur_bounds->right;
- distance_right=Get_Intersection_Y(cur_bounds->right);
- } else {
- proj_right=abs_proj_right;
- distance_right=vtrans2.y;
- } /* endif */
- Assert( (proj_right < proj_left), "Try to draw seg of negative length");
- Assert( ((proj_left < 0)||(proj_right<0)||(proj_left>WINDOW_WIDTH)||
- (proj_right>WINDOW_WIDTH)), "Corrected seg bounds still illegal");
- if (proj_left==proj_right) {
- continue;
- }
- // Get distances and columns for each intersection along seg
-
- if (any_wall_exists)
- Get_Intersects(&vtrans1, seg_angle_diff);
- // Setup mid wall. Even if there is no mid wall, these values are still used
- mid_wall.bottom_start=GetFloorScVal(Cur_Sec, distance_left);
- end_seg_bottom=GetFloorScVal(Cur_Sec, distance_right);
- mid_wall.bottom_increment=(end_seg_bottom-mid_wall.bottom_start)
- / (proj_right-proj_left);
- mid_wall.top_start=GetCeilScVal(Cur_Sec, distance_left);
- end_seg_top=GetCeilScVal(Cur_Sec, distance_right);
- mid_wall.top_increment=(end_seg_top-mid_wall.top_start)
- / (proj_right-proj_left);
- if (!(cur_seg->ld->attributes & CLEAR_LD)) {
- #ifdef CLIP
- VB_CoverSection(cur_bounds, proj_left, proj_right);
- #endif
- }
- if (mid_wall_exists) {
- // Run setup procedure for the middle wall
- mid_wall.type=MID_WALL;
- mid_wall.texture=cur_sd->texture_normal;
- mid_wall.v_height=Cur_Sec->ceil_height-Cur_Sec->floor_height;
- mid_wall.cur_bounds=cur_bounds;
- Seg_Setup(mid_wall);
- } else {
- // Setup a bottom wall
-
- low_wall.bottom_start=mid_wall.bottom_start;
- low_wall.bottom_increment=mid_wall.bottom_increment;
- low_wall.type=LOW_WALL;
- low_wall.cur_bounds=cur_bounds;
- if (low_wall_exists) {
- low_wall.top_start=GetFloorScVal(Opp_Sec, distance_left);
- low_seg_top=GetFloorScVal(Opp_Sec, distance_right);
- low_wall.top_increment=(low_seg_top - low_wall.top_start)
- / (proj_right - proj_left);
- low_wall.v_height=Opp_Sec->floor_height-Cur_Sec->floor_height;
- low_wall.texture=cur_sd->texture_low;
- } else {
- low_wall.top_start=mid_wall.bottom_start;
- low_wall.top_increment=mid_wall.bottom_increment;
- low_wall.v_height=0;
- low_wall.texture=NULL;
- } /* endif */
- Seg_Setup(low_wall);
- high_wall.top_start=mid_wall.top_start;
- high_wall.top_increment=mid_wall.top_increment;
- high_wall.type=HIGH_WALL;
- high_wall.cur_bounds=cur_bounds;
- if (high_wall_exists) {
- high_wall.bottom_start=GetCeilScVal(Opp_Sec, distance_left);
- high_seg_bottom=GetCeilScVal(Opp_Sec, distance_right);
- high_wall.bottom_increment=(high_seg_bottom - high_wall.bottom_start)
- / (proj_right - proj_left);
- high_wall.v_height=Cur_Sec->ceil_height-Opp_Sec->ceil_height;
- high_wall.texture=cur_sd->texture_high;
- } else {
- high_wall.bottom_start=mid_wall.top_start;
- high_wall.bottom_increment=mid_wall.top_increment;
- high_wall.texture=NULL;
- high_wall.v_height=0;
- } /* endif */
- Seg_Setup(high_wall);
- }
- } /* endwhile */
- }
- /*
- Seg_Setup
- Setup wall runs that are used when drawing walls
- Also manages most floor and ceiling drawing
- Notes: adds to wall_runs array & wall_run_count
- */
- void Seg_Setup(wall_move_info & mid_walls)
- {
- ssetup_count++;
- wall_run_info * cur_wall_run;
- short cur_ray;
- MYFIXED mid_sum_top, mid_sum_bottom;
- MYFIXED top_increment, bottom_increment;
- short mid_top, mid_bottom, no_clip_top, no_clip_bottom;
- short cur_win_top, cur_win_bottom;
- short floor_height_diff, ceil_height_diff;
- long temp_light, long_distance, base_light, lt_speed;
- BOOL norm_floor, norm_ceiling, do_lower, do_upper;
- long cur_column;
- long cur_increment, cur_clip;
- Byte * cur_light;
- Byte * wall_texture;
- short texture_and_width, texture_and_height;
- Byte texture_width_shift;
- short wall_type;
- MYFIXED seg_height;
- short cov_mode_start;
- vb_node * cur_bounds;
- BOOL covering_mode;
- Ptr sec_floor_texture, sec_ceil_texture;
- wall_texture=Get_Wall_Texture(mid_walls.texture);
- texture_and_width=Get_Wall_Texture_Width(mid_walls.texture)-1;
- texture_and_height=Get_Wall_Texture_Height(mid_walls.texture)-1;
- texture_width_shift=Get_Wall_Texture_Shift(mid_walls.texture);
- wall_type=mid_walls.type;
- seg_height=mid_walls.v_height<<(SLIVER_SHIFT+W_TEX_SHIFT);
- // Get some constant lighting values
- base_light=SecLight(Cur_Sec);
- lt_speed=SecLTSpeed(Cur_Sec);
- // Setup floors and ceilings;
- sec_floor_texture=Get_Floor_Texture(Cur_Sec->floor_tex);
- sec_ceil_texture=Get_Floor_Texture(Cur_Sec->ceil_tex);
- floor_height_diff=render_z-Cur_Sec->floor_height;
- ceil_height_diff=Cur_Sec->ceil_height-render_z;
- if ((wall_type==HIGH_WALL) || (wall_type==MID_WALL)) {
- do_upper=TRUE;
- if (ceil_height_diff>0 && sec_ceil_texture!=cur_sky_texture)
- norm_ceiling=TRUE;
- else norm_ceiling=FALSE;
- } else do_upper=FALSE;
-
- if ((wall_type==LOW_WALL) || (wall_type==MID_WALL) && (!(Cur_Sec->flags & VOXEL_SECTOR))) {
- do_lower=TRUE;
- if (floor_height_diff>0 && sec_floor_texture!=cur_sky_texture)
- norm_floor=TRUE;
- else norm_floor=FALSE;
- } else do_lower=FALSE;
- // Set initial fixed point sums
- mid_sum_top=mid_walls.top_start; mid_sum_bottom=mid_walls.bottom_start;
- top_increment=mid_walls.top_increment; bottom_increment=mid_walls.bottom_increment;
- prev_win_top=prev_wall_top=win_tops[proj_left];
- prev_win_bottom=prev_wall_bottom=win_bottoms[proj_left];
- // init covering mode used to correct bounds with upper & lower textures
- covering_mode=FALSE;
- cur_bounds=mid_walls.cur_bounds;
- for (cur_ray=proj_left; cur_ray<proj_right; cur_ray++) {
- // Get the short values for actual screen coordinates
- mid_top=mid_sum_top>>SHIFT;
- mid_bottom=mid_sum_bottom>>SHIFT;
- // Increment fixed point sums
- mid_sum_top+=top_increment;
- mid_sum_bottom+=bottom_increment;
- // Adjust against window bounds
- cur_win_top=win_tops[cur_ray];
- cur_win_bottom=win_bottoms[cur_ray];
- // save non clipped bounds
- no_clip_top=mid_top;
- no_clip_bottom=mid_bottom;
- Assert(no_clip_top>no_clip_bottom, "Bad Seg! at ssetup_count= " << ssetup_count);
- // Adjust against window top
- if (mid_top < cur_win_top) {
- mid_top=cur_win_top;
- } /* endif */
- if (mid_bottom < cur_win_top) {
- mid_bottom=cur_win_top;
- } /* endif */
- // Adjust against window bottom
-
- if (mid_bottom > cur_win_bottom) {
- mid_bottom=cur_win_bottom;
- } /* endif */
- if (mid_top > cur_win_bottom) {
- mid_top=cur_win_bottom;
- } /* endif */
- // Do the floor and ceiling
- #ifdef DO_FLOORS
- floor_ray=cur_ray;
- if (do_upper) {
- floor_texture=sec_ceil_texture;
- if (norm_ceiling) {
- cur_height_diff=ceil_height_diff;
- if (prev_win_top < cur_win_top) {
- floor_start=prev_win_top; floor_end=MIN(cur_win_top, prev_wall_top);
- Finish_Tex();
- } else {
- floor_start=cur_win_top; floor_end=MIN(prev_win_top, mid_top);
- Start_Tex();
- }
- if (mid_top < prev_wall_top) {
- floor_start=MAX(mid_top, prev_win_top); floor_end=prev_wall_top;
- Finish_Tex();
- } else {
- floor_start=MAX(prev_wall_top, cur_win_top); floor_end=mid_top;
- Start_Tex();
- } /* endif */
- } else {
- floor_start=cur_win_top; floor_end=mid_top;
- Draw_Sky_Column();
- }
- prev_win_top=cur_win_top;
- prev_wall_top=mid_top;
- } /* end of if "do_upper"*/
- if (do_lower) {
- floor_texture=sec_floor_texture;
-
- if ( norm_floor ) {
-
- cur_height_diff=floor_height_diff;
- if (cur_win_bottom < prev_win_bottom) {
- floor_start=MAX(cur_win_bottom, prev_wall_bottom); floor_end=prev_win_bottom;
- Finish_Tex();
- } else {
- floor_start=MAX(mid_bottom, prev_win_bottom); floor_end=cur_win_bottom;
- Start_Tex();
- }
- if (prev_wall_bottom < mid_bottom) {
- floor_start=prev_wall_bottom; floor_end=MIN(prev_win_bottom, mid_bottom);
- Finish_Tex();
- } else {
- floor_start=mid_bottom; floor_end=MIN(prev_wall_bottom, cur_win_bottom);
- Start_Tex();
- } /* endif */
- } else {
- floor_start=mid_bottom; floor_end=cur_win_bottom;
- Draw_Sky_Column();
- }
- prev_win_bottom=cur_win_bottom;
- prev_wall_bottom=mid_bottom;
- } /* end of if "do_lower" */
- #endif
- #ifdef CLIPVERT
- // Update bounding windows
- //Note: Since upper and lower textures define the difference between two
- //sectors, you bound the top of a window with an upper texture's bottom,
- //and the bottom of a window with a lower texture's top
- if (wall_type == MID_WALL) {
- win_tops[cur_ray]=mid_top;
- win_bottoms[cur_ray]=mid_bottom;
- }
- if (wall_type == LOW_WALL) {
- win_bottoms[cur_ray]=mid_top;
- #ifdef CHECK_HIGH_LOW_CLIP_OUT
- if (covering_mode) {
- if (no_clip_top > cur_win_top) {
- VB_CoverSection(cur_bounds, cov_mode_start, cur_ray);
- covering_mode=FALSE;
- }
- } else {
- if (no_clip_top <= cur_win_top) {
- cov_mode_start=cur_ray;
- covering_mode=TRUE;
- }
- }
- #endif
- }
- if (wall_type == HIGH_WALL) {
- win_tops[cur_ray]=mid_bottom;
- #ifdef CHECK_HIGH_LOW_CLIP_OUT
- if (covering_mode) {
- if (no_clip_bottom < cur_win_bottom) {
- VB_CoverSection(cur_bounds, cov_mode_start, cur_ray);
- covering_mode=FALSE;
- }
- } else {
- if (no_clip_bottom >= cur_win_bottom) {
- cov_mode_start=cur_ray;
- covering_mode=TRUE;
- }
- }
- #endif
- }
- #endif
- // Do we even have a wall?
- if (mid_top >= mid_bottom)
- continue;
- // Setup light & column
- cur_increment=fixeddiv(seg_height, mid_sum_bottom-mid_sum_top);
- cur_clip=fixedmult(cur_increment, (mid_top<<SHIFT)-mid_sum_top);
- long_distance=intersects[cur_ray].distance>>SHIFT;
- temp_light=base_light-(long_distance >> lt_speed);
- if (temp_light <0) temp_light=0;
- if (temp_light > MAX_LIGHT) temp_light=MAX_LIGHT;
- cur_light=pal_table[temp_light];
- cur_column=intersects[cur_ray].xpos;
- if (cur_column<0)
- cur_column=texture_and_width-((-cur_column)&texture_and_width);
- else cur_column&=texture_and_width;
- // And setup wall run
- if (wall_run_count>=MAX_WALL_RUNS) {
- break;
- } /* endif */
- cur_wall_run=wall_runs+wall_run_count;
- wall_run_count++;
- cur_wall_run->width_shift=texture_width_shift;
- cur_wall_run->bound_val=texture_and_height;
- cur_wall_run->texture=wall_texture;
- cur_wall_run->top=mid_top;
- cur_wall_run->scale=mid_bottom-mid_top;
- cur_wall_run->ray=cur_ray;
- cur_wall_run->increment=cur_increment;
- cur_wall_run->clip=cur_clip;
- cur_wall_run->light=cur_light;
- cur_wall_run->column=(Byte)cur_column;
- } /* endfor */
- #ifdef CHECK_HIGH_LOW_CLIP_OUT
- if (covering_mode)
- VB_CoverSection(cur_bounds, cov_mode_start, proj_right);
- #endif
- if (do_upper && norm_ceiling) {
- cur_height_diff=ceil_height_diff;
- floor_texture=sec_ceil_texture;
- floor_ray=proj_right;
- floor_start=prev_win_top; floor_end=prev_wall_top;
- Finish_Tex();
- } /* endif */
- if (do_lower && norm_floor) {
- cur_height_diff=floor_height_diff;
- floor_texture=sec_floor_texture;
- floor_ray=proj_right;
- floor_start=prev_wall_bottom; floor_end=prev_win_bottom;
- Finish_Tex();
- } /* endif */
- }
- /*
- Get_Intersects
- This is the third time I am writing this routine. I do not know why I keep losing it
- In any case, this routine gets the intersection values along the seg for each ray
- Notes: It modifies global array intersects and require setup intersection to have been
- called previously
- */
- void Get_Intersects(pvector2 base_v, angle_type angle_diff)
- {
- intersect_struct * cur_intersect;
- long test_angle;
- // Decide whether deriving columns from x or y coordinate is more accurate
- test_angle=angle_diff;
- if (test_angle > ANGLE_180) test_angle-=ANGLE_180;
- BOOL is_y_angle=( ((test_angle <= ANGLE_45) || (test_angle >=ANGLE_135)) ? TRUE : FALSE);
- // based on that decision, run two different loops to get distance and column values
- if (is_y_angle) {
- MYFIXED base_y, subs_y;
-
- base_y=base_v->y;
- for (short cur_ray=proj_left; cur_ray < proj_right; cur_ray++) {
-
- cur_intersect=intersects+cur_ray;
- cur_intersect->distance=Get_Intersection_Y(cur_ray);
- Assert((cur_intersect->distance <= 0), "Negative column distance");
- subs_y=cur_intersect->distance-base_y;
-
- cur_intersect->xpos=convtoLONG(fixeddiv(subs_y << W_TEX_SHIFT,
- rcos_table[angle_diff]));
- cur_intersect->increment=fixedmult(cur_intersect->distance, y_inv_trans);
- } /* endfor */
- } else {
- MYFIXED base_x, subs_x;
- base_x=base_v->x;
- for (short cur_ray=proj_left; cur_ray < proj_right; cur_ray++) {
-
- cur_intersect=intersects+cur_ray;
- cur_intersect->distance=Get_Intersection_Y(cur_ray);
- Assert((cur_intersect->distance <=0), "Negative column distance");
- subs_x=Get_Intersection_X()-base_x;
- cur_intersect->xpos=convtoLONG(fixeddiv(subs_x << W_TEX_SHIFT,
- rsin_table[angle_diff]));
- cur_intersect->increment=fixedmult(cur_intersect->distance, y_inv_trans);
- } /* endfor */
- } /* endif */
- }
- void Draw_Sub_Sector_Setup()
- {
- intersects=(intersect_struct *)NewPtr(Get_Phys_Screen_Width() * sizeof(intersect_struct));
- floor_offsets_x=(MYFIXED *)NewPtr((Get_Phys_Screen_Width()) * sizeof(MYFIXED));
- floor_offsets_y=(MYFIXED *)NewPtr((Get_Phys_Screen_Width()) * sizeof(MYFIXED));
- }
- void Draw_Sub_Sector_Close()
- {
- DelPtr(intersects);
- DelPtr(floor_offsets_x);
- DelPtr(floor_offsets_y);
- }
- /*
- Ok, if you had the patience to read all the way down here, I feel obligated
- to tell you that an international communist revolution is going on right
- now. You are the only one who can save America. I am now dead.
- Some Tips:
- 1. Trust no one, and shoot most people on sight.
- 2. Try to disregard issues of morality, and instead protect national
- security.
- 3. Shoot first, then ask questions.
- 4. Your enemy has no respect whatsoever for human life.
- Right now, I'm being taken in by the communist leader, to be brainwashed.
- Except that I'm already dead. So this is somewhat irrelevant.
- Some details on the revolution:
- 1. The communist goal is to make the U.S. capsize. They are going to
- bomb only one side of the U.S. in hopes that they can make the weight
- distribution of the country so lopsided that it tips over.
- 2. They will drop pianos on everyone in Cleveland because the strained
- Soviet budget cannot afford missiles.
- 3. Soviets claim to have a weapon with the power to wipe out an entire
- continent. As proof of this, they will demonstrate the weapon on the
- plains of Siberia.
- 4. The Soviet amphibious forces are out of date. However, they have
- discovered that a large group of hypnotized frogs makes for an effective
- amphibian weapon.
- 5. They will shoot Jay Leno and give Letterman the NBC spot he deserves.
- Note: We actually want them to succeed here
- In any case, I have now been knocked unconcious by an unknown assailant.
- Except that I was already taken in by the communist leader. And that
- I'm already dead. But don't worry about me. Save your country. You'll
- be paid handsomely.
- */