RAYCAST.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:33k
源码类别:

游戏

开发平台:

Visual C++

  1. /*********************
  2. Portions of this code taken from Programming Gurus book by Waite Group
  3. Most written for super speed game on '040 by Joshua Glazer
  4. Those portions are Copyright Joshua Glazer c1994
  5. Lightening fast two-level Fixed Point Routines Copyright Joshua Glazer c1994
  6. These routines may be used by one Matthew Howard, but 
  7. credit must be given to Joshua Glazer c1994
  8. **** Yea, well I wrote some nice asm routines for IBM so, you can give Matt Howard -1994
  9. a little credit too! ****
  10. I like writing Joshua Glazer c1994
  11. Violaters of the Copyright law violated by violating this source-code
  12. will be hunted down and castrated (or spayed) by Joshua Glazer c1994
  13. This means you!
  14. Actually, 'This' is a pronoun used to refer to a subject being talked about
  15. which is closer to the speaker than some other object.
  16. Oh Shut Up.
  17. Copyright Joshua Glazer c1994
  18. *********************/
  19. #include "asm.h"
  20. #include "ray.h"
  21. #include "rayrend.h"
  22. #include "raycl.h"
  23. #include "rayvb.h"
  24. #include "assert.h"
  25. #include "globals.h"
  26. #include "fixed.h"
  27. #include <mem.h>
  28. #include "mymem.h"
  29. #include <math.h>
  30. #include "asm.h"
  31. #include "prevarr.h"
  32. #include "voxinter.h"
  33. #include "texconst.h"
  34. #include "scrconf.h"
  35. #include "ldattrib.h"
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #define BLACK_COLOR 240  
  39. #define SS_NO_VISIBLE -1
  40. #define SS_VISIBLE 0
  41. #define LOW_WALL 0
  42. #define HIGH_WALL 1
  43. #define MID_WALL 2
  44. #define CLIP
  45. #define CHECK_HIGH_LOW_CLIP_OUT
  46. #define CLIPVERT
  47. #define DO_FLOORS
  48. #define BAR_LENGTH 10
  49. #define RED_COLOR 79
  50. typedef struct WALL_MOVE_INFO {
  51.    MYFIXED top_start, bottom_start;
  52.    MYFIXED top_increment, bottom_increment;
  53.    ptexture texture;
  54.    short type;
  55.    long v_height;
  56.    vb_node * cur_bounds;
  57. } wall_move_info;
  58. typedef struct INTERSECT_STRUCT {
  59.    long distance, xpos;
  60.    MYFIXED increment;
  61. } intersect_struct;
  62. intersect_struct * intersects;
  63. MYFIXED * floor_offsets_x;
  64. MYFIXED * floor_offsets_y;
  65. long v_angle_plus_90;
  66. MYFIXED floor_trans_x, floor_trans_y;
  67. short prev_win_top, prev_win_bottom,
  68. prev_wall_top, prev_wall_bottom, proj_left, proj_right;
  69. short floor_ray, floor_start, floor_end, cur_height_diff;
  70. Byte * floor_texture;
  71. Byte * cur_sky_texture;
  72. sector * Cur_Sec;
  73. long ssetup_count;
  74. void Seg_Setup(wall_move_info & mid_walls);
  75. void Get_Intersects(pvector2 base_v, angle_type angle_diff);
  76. void Draw_Seg(seg * cur_seg);
  77. /*
  78.    Draw_Health
  79.    Draws a bar for player's health
  80. */
  81. void Draw_Health() {
  82. long the_health=the_player->stats.current_health;
  83. long start_pos=Get_Phys_Screen_Width()*(Get_Phys_Screen_Height()-BAR_LENGTH);
  84. for (short cur_vert=0; cur_vert<BAR_LENGTH; cur_vert++) {
  85.   memset(buff+start_pos+(cur_vert*Get_Phys_Screen_Width()), RED_COLOR, the_health);
  86. }
  87. }
  88. /*
  89.    Win_Bounds_Setup
  90.    Just initializes bounding values before a draw to all 0's for top and
  91.    WINDOW_HEIGHT for bottom
  92. */
  93. inline void Win_Bounds_Setup()
  94. {
  95.    memset(win_tops, 0, WINDOW_WIDTH * sizeof(short));
  96.    memsetshort(win_bottoms, WINDOW_HEIGHT, WINDOW_WIDTH);
  97. }
  98. /*
  99.    Init_Floor_Values
  100.    Initializes values used for floor drawing
  101.    Notes: None
  102. */
  103. inline void Init_Floor_Values()
  104. {
  105.    // might as well calculate an angle that is used all the time for drawing floors
  106.    v_angle_plus_90=Get_Angle_Difference(render_view_angle, ANGLE_90);
  107.    floor_trans_x=fixedmult(x_inv_trans, rcos_table[v_angle_plus_90]);
  108.    floor_trans_y=fixedmult(x_inv_trans, rsin_table[v_angle_plus_90]);
  109.    long floor_adder_x=floor_trans_x >> X_TRANS_SHIFT;
  110.    long floor_adder_y=floor_trans_y >> X_TRANS_SHIFT;
  111.    long floor_sum_x=floor_adder_x * (-WINDOW_MIDDLEW);
  112.    long floor_sum_y=floor_adder_y * (-WINDOW_MIDDLEW);
  113.    for (short cur_ray=0; cur_ray < (WINDOW_WIDTH); cur_ray++) {
  114.       floor_offsets_x[cur_ray]=floor_sum_x;
  115.       floor_offsets_y[cur_ray]=floor_sum_y;
  116.       floor_sum_x+=floor_adder_x;
  117.       floor_sum_y+=floor_adder_y;
  118.       }
  119. }
  120. /*
  121.    Start_Tex
  122.    Marks starts of texture lines on rows from "start" up to but not including "end at x position "ray"
  123.    Notes: Assumes floor_texture already points to the floor texture to draw
  124. */
  125.                        
  126. inline void Start_Tex() {
  127.    short row;
  128.    for (row=floor_start; row<floor_end; row++) {
  129.       tex_mark_table[row]=floor_ray;
  130.       }
  131. }
  132. /*
  133.    Finish_Tex
  134.    Draws the previously marked floor textures on rows from "start" up to but no including "end"
  135.    Ends lines at "ray"
  136.    Notes: Assumes floor_texture already points to the floor texture to draw
  137. */
  138. inline void Finish_Tex() {
  139.  
  140.    short row, start_ray;
  141.    long tempLight;
  142.    MYFIXED distance_fixed;
  143.    floor_run_info * cur_floor_run;
  144.    for (row=floor_start; row<floor_end; row++) {
  145.       start_ray=tex_mark_table[row];
  146.       if (floor_ray<=start_ray)
  147.          continue;
  148.       if (floor_run_count>=MAX_FLOOR_RUNS)
  149.          break;
  150.       cur_floor_run=floor_runs+floor_run_count;
  151.       floor_run_count++;
  152.       // Set row to draw on
  153.       cur_floor_run->screen_y=row;
  154.       // Get starting x and width of texture
  155.       cur_floor_run->scale=(short)(floor_ray-start_ray);
  156.       cur_floor_run->screen_x=start_ray;
  157.       // Get distance to floor
  158.       distance_fixed=cur_height_diff *distance_table[row];
  159.       Assert(distance_fixed < 0, "Negative floor row distance");
  160.       // Get map starting positions
  161.       cur_floor_run->map_x=fixedmult(rcos_table[render_view_angle] + 
  162.         floor_offsets_x[start_ray], distance_fixed)+(render_x);
  163.       cur_floor_run->map_y=fixedmult(rsin_table[render_view_angle] +
  164.         floor_offsets_y[start_ray], distance_fixed)+(render_y);
  165.       // Get increments by multiplying the increment along the  actual line by sin & cos of line angle
  166.       cur_floor_run->x_inc=fixedmult(distance_fixed,
  167.          floor_trans_x) >> X_TRANS_SHIFT;
  168.       cur_floor_run->y_inc=fixedmult(distance_fixed,
  169.          floor_trans_y) >> X_TRANS_SHIFT;
  170.       // do light calculation
  171.       // In getting the light value, we take into account that distance_fixed
  172.       // is a fixed point number and add to the right shift the fixed point conversion
  173.       // number
  174.       tempLight=(SecLight(Cur_Sec)-
  175.          (distance_fixed >> (SHIFT+SecLTSpeed(Cur_Sec))) );
  176.       if (tempLight<0) tempLight=0;
  177.       if (tempLight>MAX_LIGHT) tempLight=MAX_LIGHT;
  178.       Assert(((tempLight <0) || (tempLight >MAX_LIGHT)), "Bad Lighting Value");
  179.       cur_floor_run->light=pal_table[tempLight];
  180.        cur_floor_run->texture=floor_texture;
  181.    } /* endfor */
  182. }
  183. /*
  184.   Draw_Sky_Column
  185.   Draws one column of the sky texture from "top" down to but not including "bottom"
  186.   Notes: This is a hack. Code is cryptic. Should be improved upon. For example, it should
  187.   not require that sky texture be length of screen. Requires a theoretical
  188.   understanding of screen rays intersecting a circle on the horizon that I don't have
  189. */
  190. inline void Draw_Sky_Column()
  191. {
  192.    // Was the programmer such an idiot that he tried to draw column of length 0?
  193.    if (floor_start>=floor_end)
  194.       return;
  195.    if (wall_run_count>=MAX_WALL_RUNS) {
  196.       return;
  197.    } /* endif */
  198.    wall_run_info * cur_wall_run=wall_runs+wall_run_count;
  199.    wall_run_count++;
  200.    // Setup the render constants, pretty standard
  201.    cur_wall_run->bound_val=SKY_HEIGHT-1;
  202.    cur_wall_run->texture=cur_sky_texture;
  203.    cur_wall_run->ray=floor_ray;
  204.    cur_wall_run->top=floor_start;
  205.    cur_wall_run->scale=floor_end-floor_start;
  206.    cur_wall_run->clip=floor_start << SLIVER_SHIFT;
  207.    cur_wall_run->light=pal_table[MAX_LIGHT];
  208.    cur_wall_run->increment=SLIVER_ONE;
  209.    cur_wall_run->width_shift=SKY_SHIFT;
  210.    // Do a whole lot of stupid calculations to get the column in the texture to draw
  211.    long temp_column;
  212.    long temp_ray=floor_ray*HORIZ_VIEW_RANGE/WINDOW_WIDTH;
  213.    long tempAngle;
  214.    if (temp_ray<(HORIZ_VIEW_RANGE>>1))
  215.       tempAngle=temp_ray;
  216.    else tempAngle=Get_Angle_Difference(HORIZ_VIEW_RANGE, temp_ray);
  217.    MYFIXED tempdiv=fixeddiv(tan_table[tempAngle],
  218.         tan_table[HORIZ_VIEW_RANGE>>1]);
  219.    tempdiv=convtoLONG((HORIZ_VIEW_RANGE>>1)*tempdiv);
  220.    if (temp_ray>=(HORIZ_VIEW_RANGE>>1))
  221.       tempdiv=HORIZ_VIEW_RANGE-tempdiv;
  222.    // div by 2 to stretch out backround a little
  223.    temp_column=(((HORIZ_VIEW_RANGE>>1)-tempdiv)+(render_view_angle));
  224.   
  225.    if (temp_column<0) {
  226.       cur_wall_run->column=SKY_WIDTH-((-temp_column) % SKY_WIDTH);
  227.    } else {
  228.       cur_wall_run->column=temp_column % SKY_WIDTH;
  229.    } /* endif */
  230. }
  231. /*
  232.    Close_Textures
  233.    Finishes up whatever textures were running in a given visible section
  234.    Notes: Uses proj_right and the "prev" globals
  235. */
  236. inline void Close_Textures(short closing_ray)
  237. {
  238. long floor_height_diff=render_z-Cur_Sec->floor_height;
  239. long ceil_height_diff=Cur_Sec->ceil_height-render_z;
  240. floor_ray=closing_ray;
  241. floor_texture=Get_Floor_Texture(Cur_Sec->ceil_tex);
  242. floor_start=prev_win_top; floor_end=prev_wall_top;
  243. if ( ceil_height_diff>0 && floor_texture!=cur_sky_texture ) {
  244.    Finish_Tex();
  245. } /* endif */
  246. floor_texture=Get_Floor_Texture(Cur_Sec->floor_tex);
  247. floor_start=prev_wall_bottom; floor_end=prev_win_bottom;
  248. if ( floor_height_diff>0 && floor_texture!=cur_sky_texture ) {
  249.    Finish_Tex();
  250. } /* endif */
  251. }
  252. /*
  253.    SegVisible
  254.    Decides if a seg is (a) visible and (b) facing you
  255. */
  256. inline BOOL SegVisible(seg * cur_seg)
  257. {
  258. long x1, x2, y1, y2;
  259. pvector2 v1, v2;
  260. v1=Vector_List+cur_seg->v[0];
  261. v2=Vector_List+cur_seg->v[1];
  262. x1=v1->x;
  263. x2=v2->x;
  264. y1=v1->y;
  265. y2=v2->y;
  266. if ( fixedmult((x1-x2),(render_y-(y2<<SHIFT))) >= fixedmult((y1-y2),(render_x-(x2<<SHIFT))) ) {
  267.    return TRUE;
  268. } else {
  269.    return FALSE;
  270. } /* endif */
  271. }
  272. /////////////////////////////////////////////////////////////////////////////
  273. /*
  274.    Ray_Caster
  275.    The all powerful function that renders the screen
  276.    Notes: Well, it isn't really all powerful. After all, it's just a routine,
  277.    not some sort of diety. It dosen't even do that much, just calls other routines
  278. */
  279. void Ray_Caster(long x, long y, long z, long view_angle)
  280. {
  281. ssetup_count=0;
  282. // setup rendering constants
  283. render_x=x; render_y=y; render_z=z; render_view_angle=view_angle;
  284. // setup constants for floor drawing
  285. Init_Floor_Values();
  286. // save the current frame of the sky animation 
  287. // (we will say that sky texture cannot change while rendering)
  288. cur_sky_texture=sky_texture->images[sky_texture->cur_image];
  289. // Initialize the clipping structures
  290. Win_Bounds_Setup();
  291. VB_InitList();
  292. // Set starting wall & floor run count to 0
  293. wall_run_count=0;
  294. floor_run_count=0;
  295. // initialize voxel colors
  296. memset((PUCHAR)prev_colors, BLACK_COLOR, Get_Phys_Screen_Width());
  297. // Turn over control to the bsp tracer
  298. BSP_Recursion_Draw();
  299. // If we have any floors, it's probably a good idea to render them
  300. if (floor_run_count>0) {
  301.    Render_Floor_asm();
  302. } /* endif */
  303. // If we have any walls, its probably a good idea to render them too...
  304. if (wall_run_count>0) {
  305.    Render_Sliver_asm();
  306. } /* endif */
  307. Draw_Health();
  308. }
  309. /*
  310.   Draw_Sub_Sector
  311.   Big time importance in this routine. Basically, it draws a sub sector (i.e. portion that cannot
  312.   obscure any of itself). Does most of the hard calculations. Well, not anymore, Draw_Seg does
  313.   now
  314.   Notes: Still has problems, may crash system if you run it on sub sectors that are behind the player
  315. */
  316. void Draw_Sub_Sector(pssector cur_ss)
  317. {
  318. short cur_seg, num_segs, counter;
  319. // do dem sprites
  320. if (cur_ss->flags & VOXEL_SSECTOR) {
  321.    Render_Voxel_Sub_Sector(cur_ss);
  322. } else {
  323. Draw_SS_Sprites(cur_ss);
  324. }
  325. cur_seg=cur_ss->seg_start;
  326. num_segs=cur_ss->seg_end-cur_ss->seg_start+1;
  327. for (counter=0; counter<num_segs; counter++) {
  328.    if (SegVisible(Seg_List+cur_seg)) {
  329.       Draw_Seg(Seg_List+cur_seg);
  330.    } /* endif */
  331.    if (VB_EmptyList())
  332.       return;
  333.    cur_seg++;
  334. } /* endfor */
  335. }
  336. /*
  337.    Draw_Seg
  338.    Just what it sounds like. Draws a seg. Calls Seg_Setup & Get_Intersects.
  339.    Does some vector translation
  340.    Notes: Not proven to always work. But then again, neither is nutrisweet.
  341. */
  342. void Draw_Seg(seg * cur_seg)
  343. {
  344.    LONG abs_proj_left, abs_proj_right;
  345.    LONG distance_left, distance_right;
  346.    sector * Opp_Sec;
  347.    
  348.    sidedef * cur_sd;
  349.    pvector2 v1,v2;
  350.    vector2 vtrans1, vtrans2;
  351.    pvb_node cur_bounds, next_bounds;
  352.    wall_move_info low_wall, mid_wall, high_wall;
  353.    BOOL mid_wall_exists, low_wall_exists, high_wall_exists, any_wall_exists;
  354.    MYFIXED
  355.    end_seg_top,
  356.    end_seg_bottom,
  357.    low_seg_top,
  358.    high_seg_bottom;
  359.    BOOL found;
  360.    SHORT bounds_to_draw, bounds_done;
  361.    short wall_height;
  362.    angle_type seg_angle_diff;
  363.    cur_bounds=VB_GetFirstNode();
  364.    // Get the sector
  365.    Cur_Sec=GetSecFromSeg(cur_seg);
  366.    Assert(((Cur_Sec < Sector_List)||(Cur_Sec >= (Sector_List+Number_Of_Sectors))),
  367.         "Invalid sector in Draw_Seg");
  368.    v1=Vector_List+cur_seg->v[0];
  369.    v2=Vector_List+cur_seg->v[1];
  370.    // Translate Vectors
  371.    // I use y for distance, but technically it ought to be x, so I switch x and y when translated
  372.    rotate_angle=render_view_angle;
  373.    rotate_x=(v1->x<<SHIFT) - render_x;
  374.    rotate_y=(v1->y<<SHIFT) - render_y;
  375.    vtrans1.x=FixedRotateY();
  376.    vtrans1.y=FixedRotateX();
  377.    rotate_x=(v2->x<<SHIFT) - render_x;
  378.    rotate_y=(v2->y<<SHIFT) - render_y;
  379.    vtrans2.x=FixedRotateY();
  380.    vtrans2.y=FixedRotateX();
  381.    // clip for lines in back of and in front of view window
  382.    if ((vtrans1.y<=0)&&(vtrans2.y<=0))
  383.       return;
  384.    if ((vtrans1.y>= (MAXDIS<<SHIFT) ) || (vtrans2.y>= (MAXDIS<<SHIFT) ))
  385.       return;
  386.    // Get projected screen coordinates
  387.    if (vtrans1.y>0) {
  388.       abs_proj_left=(fixedmd(-vtrans1.x, SCALE_FACTOR, vtrans1.y) )
  389.                 +WINDOW_MIDDLEW;
  390.    } /* endif */
  391.    if (vtrans2.y>0) {
  392.       abs_proj_right=(fixedmd(-vtrans2.x, SCALE_FACTOR, vtrans2.y) )
  393.                 +WINDOW_MIDDLEW;
  394.    } /* endif */
  395.    // Is this seg past the bounding window
  396.  
  397.    if (vtrans1.y>0) {
  398.       found=FALSE;
  399.       while ( (cur_bounds!=NULL) ) {
  400.          if (abs_proj_left < cur_bounds->right) {
  401.             found=TRUE;
  402.             break;
  403.          } /* endif */
  404.          cur_bounds=VB_GetNextNode(cur_bounds);
  405.       }
  406.       if (!found) {
  407.          return;
  408.       }
  409.    }
  410.    // count number of bounding windows to draw in
  411.    if (vtrans2.y<=0)
  412.       abs_proj_right=WINDOW_WIDTH;
  413.    next_bounds=cur_bounds;
  414.    bounds_to_draw=0;
  415.    while (next_bounds!=NULL) {
  416.       if (abs_proj_right <= next_bounds->left)
  417.          break;
  418.       bounds_to_draw++;
  419.       next_bounds=VB_GetNextNode(next_bounds);
  420.    } /* endwhile */
  421.    if (bounds_to_draw==0)
  422.       return;
  423.       
  424.    Opp_Sec=GetOppSec(cur_seg);
  425.    cur_sd=cur_seg->ld->s[cur_seg->left_sidedef];
  426.    // Necessary to get intersections on seg
  427.    seg_angle_diff=Get_Angle_Difference(cur_seg->angle, render_view_angle);
  428.    Setup_Intersection(&vtrans1, &vtrans2);
  429.    next_bounds=cur_bounds;
  430.    // Do we have a middle texture
  431.    if ( (cur_sd->texture_normal!=TEXTURE_NULL) ) {
  432.       mid_wall_exists=TRUE;
  433.    } else mid_wall_exists=FALSE;
  434.    if ( (Opp_Sec!=NULL) && 
  435.       (cur_sd->texture_low!=TEXTURE_NULL) &&
  436.       (Opp_Sec->floor_height > Cur_Sec->floor_height) )
  437.       low_wall_exists=TRUE;
  438.    else low_wall_exists=FALSE;
  439.    if ( (Opp_Sec!=NULL) &&
  440.       (cur_sd->texture_high!=TEXTURE_NULL) &&
  441.       (Opp_Sec->ceil_height < Cur_Sec->ceil_height) )
  442.       high_wall_exists=TRUE;
  443.    else high_wall_exists=FALSE;
  444.    any_wall_exists=(((mid_wall_exists) || (low_wall_exists) || (high_wall_exists)) ? TRUE : FALSE);
  445.    wall_height=Cur_Sec->ceil_height-Cur_Sec->floor_height;
  446.    if (wall_height<=0) {
  447.       return;
  448.    } /* endif */
  449.    for (bounds_done=0; bounds_done <bounds_to_draw; bounds_done++) {
  450.       cur_bounds=next_bounds;
  451.       next_bounds=VB_GetNextNode(next_bounds);
  452.       Assert( ((cur_bounds < bounds) || (cur_bounds >= (bounds+WINDOW_WIDTH))),
  453.          "Attempting to draw to invalid bounds area");
  454.       // Setup up distance and projection values we will derive line movements from
  455.       if ( (vtrans1.y <= 0) || (abs_proj_left < cur_bounds->left) ) {
  456.          proj_left=cur_bounds->left;
  457.          distance_left=Get_Intersection_Y(cur_bounds->left);
  458.       } else {
  459.          proj_left=abs_proj_left;
  460.          distance_left=vtrans1.y;
  461.       } /* endif */
  462.       if ( (vtrans2.y <= 0) || (abs_proj_right > cur_bounds->right) ) {
  463.          proj_right=cur_bounds->right;
  464.          distance_right=Get_Intersection_Y(cur_bounds->right);
  465.       } else {
  466.          proj_right=abs_proj_right;
  467.          distance_right=vtrans2.y;
  468.       } /* endif */
  469.       Assert( (proj_right < proj_left), "Try to draw seg of negative length");
  470.       Assert( ((proj_left < 0)||(proj_right<0)||(proj_left>WINDOW_WIDTH)||
  471.         (proj_right>WINDOW_WIDTH)), "Corrected seg bounds still illegal");
  472.       if (proj_left==proj_right) {
  473.          continue;
  474.       }
  475.       // Get distances and columns for each intersection along seg
  476.      
  477.       if (any_wall_exists)
  478.          Get_Intersects(&vtrans1, seg_angle_diff);
  479.       // Setup mid wall. Even if there is no mid wall, these values are still used
  480.       mid_wall.bottom_start=GetFloorScVal(Cur_Sec, distance_left);
  481.       end_seg_bottom=GetFloorScVal(Cur_Sec, distance_right);
  482.       mid_wall.bottom_increment=(end_seg_bottom-mid_wall.bottom_start)
  483.          / (proj_right-proj_left);
  484.       mid_wall.top_start=GetCeilScVal(Cur_Sec, distance_left);
  485.       end_seg_top=GetCeilScVal(Cur_Sec, distance_right);
  486.       mid_wall.top_increment=(end_seg_top-mid_wall.top_start)
  487.          / (proj_right-proj_left);
  488.       if (!(cur_seg->ld->attributes & CLEAR_LD)) {
  489. #ifdef CLIP
  490.          VB_CoverSection(cur_bounds, proj_left, proj_right);
  491. #endif
  492.       }
  493.       if (mid_wall_exists) {
  494.             // Run setup procedure for the middle wall
  495.          mid_wall.type=MID_WALL;
  496.          mid_wall.texture=cur_sd->texture_normal;
  497.          mid_wall.v_height=Cur_Sec->ceil_height-Cur_Sec->floor_height;
  498.          mid_wall.cur_bounds=cur_bounds;
  499.          Seg_Setup(mid_wall);
  500.       } else {
  501.          // Setup a bottom wall
  502.  
  503.          low_wall.bottom_start=mid_wall.bottom_start;
  504.          low_wall.bottom_increment=mid_wall.bottom_increment;
  505.          low_wall.type=LOW_WALL;
  506.          low_wall.cur_bounds=cur_bounds;
  507.          if (low_wall_exists) {
  508.             low_wall.top_start=GetFloorScVal(Opp_Sec, distance_left);
  509.             low_seg_top=GetFloorScVal(Opp_Sec, distance_right);
  510.             low_wall.top_increment=(low_seg_top - low_wall.top_start)
  511.                / (proj_right - proj_left);
  512.             low_wall.v_height=Opp_Sec->floor_height-Cur_Sec->floor_height;
  513.             low_wall.texture=cur_sd->texture_low;
  514.          } else {              
  515.             low_wall.top_start=mid_wall.bottom_start;
  516.             low_wall.top_increment=mid_wall.bottom_increment;
  517.             low_wall.v_height=0;
  518.             low_wall.texture=NULL;
  519.          } /* endif */
  520.          Seg_Setup(low_wall);
  521.          high_wall.top_start=mid_wall.top_start;
  522.          high_wall.top_increment=mid_wall.top_increment;
  523.          high_wall.type=HIGH_WALL;
  524.          high_wall.cur_bounds=cur_bounds;
  525.          if (high_wall_exists) {
  526.             high_wall.bottom_start=GetCeilScVal(Opp_Sec, distance_left);
  527.             high_seg_bottom=GetCeilScVal(Opp_Sec, distance_right);
  528.             high_wall.bottom_increment=(high_seg_bottom - high_wall.bottom_start)
  529.                / (proj_right - proj_left);
  530.             high_wall.v_height=Cur_Sec->ceil_height-Opp_Sec->ceil_height;
  531.             high_wall.texture=cur_sd->texture_high;
  532.          } else {
  533.             high_wall.bottom_start=mid_wall.top_start;
  534.             high_wall.bottom_increment=mid_wall.top_increment;
  535.             high_wall.texture=NULL;
  536.             high_wall.v_height=0;
  537.          } /* endif */
  538.          Seg_Setup(high_wall);
  539.       }
  540.    } /* endwhile */
  541. }
  542. /*
  543.   Seg_Setup
  544.   Setup wall runs that are used when drawing walls
  545.   Also manages most floor and ceiling drawing
  546.   Notes: adds to wall_runs array & wall_run_count
  547. */
  548. void Seg_Setup(wall_move_info & mid_walls)
  549. {
  550.    ssetup_count++;
  551.    wall_run_info * cur_wall_run;
  552.    short cur_ray;
  553.    MYFIXED mid_sum_top, mid_sum_bottom;
  554.    MYFIXED top_increment, bottom_increment;
  555.    short mid_top, mid_bottom, no_clip_top, no_clip_bottom;
  556.    short cur_win_top, cur_win_bottom;
  557.    short floor_height_diff, ceil_height_diff;
  558.    long temp_light, long_distance, base_light, lt_speed;
  559.    BOOL norm_floor, norm_ceiling, do_lower, do_upper;
  560.    long cur_column;
  561.    long cur_increment, cur_clip;
  562.    Byte * cur_light;
  563.    Byte * wall_texture;
  564.    short texture_and_width, texture_and_height;
  565.    Byte texture_width_shift;
  566.    short wall_type;
  567.    MYFIXED seg_height;
  568.    short cov_mode_start;
  569.    vb_node * cur_bounds;
  570.    BOOL covering_mode;
  571.    Ptr sec_floor_texture, sec_ceil_texture;
  572.    wall_texture=Get_Wall_Texture(mid_walls.texture);
  573.    texture_and_width=Get_Wall_Texture_Width(mid_walls.texture)-1;
  574.    texture_and_height=Get_Wall_Texture_Height(mid_walls.texture)-1;
  575.    texture_width_shift=Get_Wall_Texture_Shift(mid_walls.texture);
  576.    wall_type=mid_walls.type;
  577.    seg_height=mid_walls.v_height<<(SLIVER_SHIFT+W_TEX_SHIFT);
  578.    // Get some constant lighting values
  579.    base_light=SecLight(Cur_Sec);
  580.    lt_speed=SecLTSpeed(Cur_Sec);
  581.    // Setup floors and ceilings;
  582.    sec_floor_texture=Get_Floor_Texture(Cur_Sec->floor_tex);
  583.    sec_ceil_texture=Get_Floor_Texture(Cur_Sec->ceil_tex);
  584.    floor_height_diff=render_z-Cur_Sec->floor_height;
  585.    ceil_height_diff=Cur_Sec->ceil_height-render_z;
  586.    if ((wall_type==HIGH_WALL) || (wall_type==MID_WALL)) {
  587.       do_upper=TRUE;
  588.       if (ceil_height_diff>0 && sec_ceil_texture!=cur_sky_texture)
  589.          norm_ceiling=TRUE;
  590.       else norm_ceiling=FALSE;
  591.    } else do_upper=FALSE;
  592.                                                 
  593.    if ((wall_type==LOW_WALL) || (wall_type==MID_WALL) && (!(Cur_Sec->flags & VOXEL_SECTOR))) {
  594.       do_lower=TRUE;
  595.       if (floor_height_diff>0 && sec_floor_texture!=cur_sky_texture)
  596.          norm_floor=TRUE;
  597.       else norm_floor=FALSE;
  598.    } else do_lower=FALSE;
  599.    // Set initial fixed point sums
  600.    mid_sum_top=mid_walls.top_start; mid_sum_bottom=mid_walls.bottom_start;
  601.    top_increment=mid_walls.top_increment; bottom_increment=mid_walls.bottom_increment;
  602.    prev_win_top=prev_wall_top=win_tops[proj_left];
  603.    prev_win_bottom=prev_wall_bottom=win_bottoms[proj_left];
  604.    // init covering mode used to correct bounds with upper & lower textures
  605.    covering_mode=FALSE;
  606.    cur_bounds=mid_walls.cur_bounds;
  607.    for (cur_ray=proj_left; cur_ray<proj_right; cur_ray++) {
  608.       // Get the short values for actual screen coordinates
  609.       mid_top=mid_sum_top>>SHIFT;
  610.       mid_bottom=mid_sum_bottom>>SHIFT;
  611.       // Increment fixed point sums
  612.       mid_sum_top+=top_increment;
  613.       mid_sum_bottom+=bottom_increment;
  614.       // Adjust against window bounds
  615.       cur_win_top=win_tops[cur_ray];
  616.       cur_win_bottom=win_bottoms[cur_ray];
  617.       // save non clipped bounds
  618.       no_clip_top=mid_top;
  619.       no_clip_bottom=mid_bottom;
  620.       Assert(no_clip_top>no_clip_bottom, "Bad Seg! at ssetup_count= " << ssetup_count);
  621.       // Adjust against window top
  622.       if (mid_top < cur_win_top) {
  623.          mid_top=cur_win_top;
  624.       } /* endif */
  625.       if (mid_bottom < cur_win_top) {
  626.          mid_bottom=cur_win_top;
  627.       } /* endif */
  628.       // Adjust against window bottom
  629.  
  630.       if (mid_bottom > cur_win_bottom) {
  631.          mid_bottom=cur_win_bottom;
  632.       } /* endif */
  633.       if (mid_top > cur_win_bottom) {
  634.          mid_top=cur_win_bottom;
  635.       } /* endif */
  636.       // Do the floor and ceiling
  637. #ifdef DO_FLOORS
  638.       floor_ray=cur_ray;
  639.       if (do_upper) {
  640.          floor_texture=sec_ceil_texture;
  641.          if (norm_ceiling) {
  642.             cur_height_diff=ceil_height_diff;
  643.             if (prev_win_top < cur_win_top) {
  644.                floor_start=prev_win_top; floor_end=MIN(cur_win_top, prev_wall_top);
  645.                Finish_Tex();
  646.             } else {
  647.                floor_start=cur_win_top; floor_end=MIN(prev_win_top, mid_top);
  648.                Start_Tex();
  649.             }
  650.             if (mid_top < prev_wall_top) {
  651.                floor_start=MAX(mid_top, prev_win_top); floor_end=prev_wall_top;
  652.                Finish_Tex();
  653.             } else {
  654.                floor_start=MAX(prev_wall_top, cur_win_top); floor_end=mid_top;
  655.                Start_Tex();
  656.             } /* endif */
  657.          } else {
  658.             floor_start=cur_win_top; floor_end=mid_top;
  659.             Draw_Sky_Column();
  660.          }
  661.          prev_win_top=cur_win_top;
  662.          prev_wall_top=mid_top;
  663.       } /* end of if "do_upper"*/
  664.       if (do_lower) {
  665.          floor_texture=sec_floor_texture;
  666.          
  667.          if ( norm_floor ) {
  668.            
  669.             cur_height_diff=floor_height_diff;
  670.             if (cur_win_bottom < prev_win_bottom) {
  671.                floor_start=MAX(cur_win_bottom, prev_wall_bottom); floor_end=prev_win_bottom;
  672.                Finish_Tex();
  673.             } else {
  674.                floor_start=MAX(mid_bottom, prev_win_bottom); floor_end=cur_win_bottom;
  675.                Start_Tex();
  676.             }
  677.             if (prev_wall_bottom < mid_bottom) {
  678.                floor_start=prev_wall_bottom; floor_end=MIN(prev_win_bottom, mid_bottom);
  679.                Finish_Tex();
  680.             } else {
  681.                floor_start=mid_bottom; floor_end=MIN(prev_wall_bottom, cur_win_bottom);
  682.                Start_Tex();
  683.             } /* endif */
  684.          } else {
  685.             floor_start=mid_bottom; floor_end=cur_win_bottom;
  686.             Draw_Sky_Column();
  687.          }
  688.          prev_win_bottom=cur_win_bottom;
  689.          prev_wall_bottom=mid_bottom;
  690.       } /* end of if "do_lower" */
  691. #endif
  692. #ifdef CLIPVERT
  693.       // Update bounding windows
  694.       //Note: Since upper and lower textures define the difference between two
  695.       //sectors, you bound the top of a window with an upper texture's bottom,
  696.       //and the bottom of a window with a lower texture's top
  697.       if (wall_type == MID_WALL) {
  698.          win_tops[cur_ray]=mid_top;
  699.          win_bottoms[cur_ray]=mid_bottom;
  700.       }
  701.       if (wall_type == LOW_WALL) {
  702.           win_bottoms[cur_ray]=mid_top;
  703. #ifdef CHECK_HIGH_LOW_CLIP_OUT
  704.           if (covering_mode) {
  705.              if (no_clip_top > cur_win_top) {
  706.                 VB_CoverSection(cur_bounds, cov_mode_start, cur_ray);
  707.                 covering_mode=FALSE;
  708.                 }
  709.           } else {
  710.              if (no_clip_top <= cur_win_top) {
  711.                 cov_mode_start=cur_ray;
  712.                 covering_mode=TRUE;
  713.              }
  714.           }
  715. #endif
  716.       }
  717.       if (wall_type == HIGH_WALL) {
  718.           win_tops[cur_ray]=mid_bottom;
  719. #ifdef CHECK_HIGH_LOW_CLIP_OUT
  720.           if (covering_mode) {
  721.              if (no_clip_bottom < cur_win_bottom) {
  722.                 VB_CoverSection(cur_bounds, cov_mode_start, cur_ray);
  723.                 covering_mode=FALSE;
  724.                 }
  725.           } else {
  726.              if (no_clip_bottom >= cur_win_bottom) {
  727.                 cov_mode_start=cur_ray;
  728.                 covering_mode=TRUE;
  729.              }
  730.           }
  731. #endif
  732.       }
  733. #endif
  734.       // Do we even have a wall?
  735.       if (mid_top >= mid_bottom)
  736.          continue;
  737.       // Setup light & column
  738.       cur_increment=fixeddiv(seg_height, mid_sum_bottom-mid_sum_top);
  739.       cur_clip=fixedmult(cur_increment, (mid_top<<SHIFT)-mid_sum_top);
  740.       long_distance=intersects[cur_ray].distance>>SHIFT;
  741.       temp_light=base_light-(long_distance >> lt_speed);
  742.       if (temp_light <0) temp_light=0;
  743.       if (temp_light > MAX_LIGHT) temp_light=MAX_LIGHT;
  744.       cur_light=pal_table[temp_light];
  745.       cur_column=intersects[cur_ray].xpos;
  746.       if (cur_column<0) 
  747.          cur_column=texture_and_width-((-cur_column)&texture_and_width);
  748.       else cur_column&=texture_and_width;
  749.       // And setup wall run
  750.       if (wall_run_count>=MAX_WALL_RUNS) {
  751.          break;
  752.       } /* endif */
  753.       cur_wall_run=wall_runs+wall_run_count;
  754.       wall_run_count++;
  755.       cur_wall_run->width_shift=texture_width_shift;
  756.       cur_wall_run->bound_val=texture_and_height;
  757.       cur_wall_run->texture=wall_texture;
  758.       cur_wall_run->top=mid_top;
  759.       cur_wall_run->scale=mid_bottom-mid_top;
  760.       cur_wall_run->ray=cur_ray;
  761.       cur_wall_run->increment=cur_increment;
  762.       cur_wall_run->clip=cur_clip;
  763.       cur_wall_run->light=cur_light;
  764.       cur_wall_run->column=(Byte)cur_column;
  765.    } /* endfor */
  766. #ifdef CHECK_HIGH_LOW_CLIP_OUT
  767. if (covering_mode)
  768.    VB_CoverSection(cur_bounds, cov_mode_start, proj_right);
  769. #endif
  770. if (do_upper && norm_ceiling) {
  771.    cur_height_diff=ceil_height_diff;
  772.    floor_texture=sec_ceil_texture;
  773.    floor_ray=proj_right;
  774.    floor_start=prev_win_top; floor_end=prev_wall_top;
  775.    Finish_Tex();
  776. } /* endif */
  777. if (do_lower && norm_floor) {
  778.    cur_height_diff=floor_height_diff;
  779.    floor_texture=sec_floor_texture;
  780.    floor_ray=proj_right;
  781.    floor_start=prev_wall_bottom; floor_end=prev_win_bottom;
  782.    Finish_Tex();
  783. } /* endif */
  784. }
  785. /*
  786.    Get_Intersects
  787.    This is the third time I am writing this routine. I do not know why I keep losing it
  788.    In any case, this routine gets the intersection values along the seg for each ray
  789.    Notes: It modifies global array intersects and require setup intersection to have been
  790.    called previously
  791. */
  792. void Get_Intersects(pvector2 base_v, angle_type angle_diff)
  793. {
  794.    intersect_struct * cur_intersect;
  795.    long test_angle;
  796.    // Decide whether deriving columns from x or y coordinate is more accurate
  797.    test_angle=angle_diff;
  798.    if (test_angle > ANGLE_180) test_angle-=ANGLE_180;
  799.    BOOL is_y_angle=( ((test_angle <= ANGLE_45) || (test_angle >=ANGLE_135)) ? TRUE : FALSE);
  800.    // based on that decision, run two different loops to get distance and column values
  801.    if (is_y_angle) {
  802.       MYFIXED base_y, subs_y;
  803.  
  804.       base_y=base_v->y;
  805.       for (short cur_ray=proj_left; cur_ray < proj_right; cur_ray++) {
  806.          
  807.          cur_intersect=intersects+cur_ray;
  808.          cur_intersect->distance=Get_Intersection_Y(cur_ray);
  809.          Assert((cur_intersect->distance <= 0), "Negative column distance");
  810.          subs_y=cur_intersect->distance-base_y;
  811.                              
  812.          cur_intersect->xpos=convtoLONG(fixeddiv(subs_y << W_TEX_SHIFT,
  813.                 rcos_table[angle_diff]));
  814.          cur_intersect->increment=fixedmult(cur_intersect->distance, y_inv_trans);
  815.       } /* endfor */
  816.    } else {
  817.       MYFIXED base_x, subs_x;
  818.       base_x=base_v->x;
  819.       for (short cur_ray=proj_left; cur_ray < proj_right; cur_ray++) {
  820.          
  821.          cur_intersect=intersects+cur_ray;
  822.          cur_intersect->distance=Get_Intersection_Y(cur_ray);
  823.          Assert((cur_intersect->distance <=0), "Negative column distance");
  824.          subs_x=Get_Intersection_X()-base_x;
  825.          cur_intersect->xpos=convtoLONG(fixeddiv(subs_x << W_TEX_SHIFT,
  826.                 rsin_table[angle_diff]));
  827.          cur_intersect->increment=fixedmult(cur_intersect->distance, y_inv_trans);
  828.       } /* endfor */
  829.    } /* endif */
  830. }
  831. void Draw_Sub_Sector_Setup()
  832. {                    
  833.    intersects=(intersect_struct *)NewPtr(Get_Phys_Screen_Width() * sizeof(intersect_struct));
  834.    floor_offsets_x=(MYFIXED *)NewPtr((Get_Phys_Screen_Width()) * sizeof(MYFIXED));
  835.    floor_offsets_y=(MYFIXED *)NewPtr((Get_Phys_Screen_Width()) * sizeof(MYFIXED));
  836. }
  837. void Draw_Sub_Sector_Close()
  838. {
  839.    DelPtr(intersects);
  840.    DelPtr(floor_offsets_x);
  841.    DelPtr(floor_offsets_y);
  842. }
  843. /*
  844. Ok, if you had the patience to read all the way down here, I feel obligated
  845. to tell you that an international communist revolution is going on right
  846. now. You are the only one who can save America. I am now dead.
  847. Some Tips:
  848. 1. Trust no one, and shoot most people on sight.
  849. 2. Try to disregard issues of morality, and instead protect national
  850.    security.
  851. 3. Shoot first, then ask questions.
  852. 4. Your enemy has no respect whatsoever for human life.
  853. Right now, I'm being taken in by the communist leader, to be brainwashed.
  854. Except that I'm already dead. So this is somewhat irrelevant.
  855. Some details on the revolution:
  856. 1. The communist goal is to make the U.S. capsize. They are going to
  857. bomb only one side of the U.S. in hopes that they can make the weight
  858. distribution of the country so lopsided that it tips over.
  859. 2. They will drop pianos on everyone in Cleveland because the strained
  860. Soviet budget cannot afford missiles.
  861. 3. Soviets claim to have a weapon with the power to wipe out an entire
  862. continent. As proof of this, they will demonstrate the weapon on the
  863. plains of Siberia.
  864. 4. The Soviet amphibious forces are out of date. However, they have
  865. discovered that a large group of hypnotized frogs makes for an effective
  866. amphibian weapon.
  867. 5. They will shoot Jay Leno and give Letterman the NBC spot he deserves.
  868. Note: We actually want them to succeed here
  869. In any case, I have now been knocked unconcious by an unknown assailant.
  870. Except that I was already taken in by the communist leader. And that
  871. I'm already dead. But don't worry about me. Save your country. You'll
  872. be paid handsomely.
  873. */