📄 raycast.cpp
字号:
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 + -