⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raycast.cpp

📁 quake 游戏原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -