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

📄 voxrend.cpp

📁 quake 游戏原代码
💻 CPP
字号:
#include <mem.h>
#include "ray.h"
#include "globals.h"
#include "voxel.h"
#include "rayrend.h"
#include "asm.h"
#include "screen.h"
#include "mymem.h"
#include "shading.h"
#include "sprvox.h"
#include "scrconf.h"
#include "voxsky.h"
#include "rcvars.h"
#include "sortseg.h"
#include "fixed.h"
#include "prevarr.h"
#include "skipping.h"

#define XT_TO_VOX_SHIFT 4
#define NORM_TO_VOX 2
#define SMOOTH_DELIMATOR_X 0x00004000
#define SMOOTH_DELIMATOR_Y 0x00400000
#define BLUE_COLOR 0x3f
#define DIST_MIN_FIXED (DIST_SCALER*DIST_MIN<<SHIFT)
#define DIST_MAX_FIXED (DIST_SCALER*DIST_MAX<<SHIFT)
#define DIST_INC (DIST_SCALER<<SHIFT)
#define MAX_SS_VECTORS 100
#define DOUBLE_DIS 30
#define QUAD_DIS 60

typedef struct VOX_RUN * pvox_run;
typedef struct VOX_RUN{
   short left, right;
   } vox_run;

shade_mode do_shading;
skipping_mode do_skipping;

void Set_Shading(shade_mode new_mode)
{
do_shading=new_mode;
}

void Set_Skipping(skipping_mode new_mode)
{
do_skipping=new_mode;
}

void Transform_Points(pvector2 start_list, pvector2 dest_list, short vector_count);
short Clip_Points_Max(pvector2 start_list, pvector2 dest_list, short vector_count);
short Clip_Points_Min(pvector2 start_list, pvector2 dest_list, short vector_count);

void Make_Vox_Runs(
   pvector2 point_list,
   short point_count,
   pvox_run dest_runs,
   short & start_line,
   short & end_line);

void Render_Vox_Runs(
   pssector vox_ssector,
   pvox_run screen_runs,
   short start_line,
   short end_line);

void Render_Voxel_Sub_Sector(pssector vox_ssector)
{
   vector2 trans_list[MAX_SS_VECTORS];
   vector2 clipped_points[MAX_SS_VECTORS];
   vector2 clipped_intermediates[MAX_SS_VECTORS];
   vox_run screen_runs[DIST_MAX];
   short start_line, end_line;
   psorted_vector_type start_list;
   short clipped_point_count;

   start_list=(psorted_vector_type)vox_ssector->extra_data;

   // transform points relative to viewer
   Transform_Points(start_list->vectors, trans_list, start_list->vector_count);

   // perform clipping, first against maximum distance, and then against minimum distance

   clipped_point_count=Clip_Points_Max(trans_list, clipped_intermediates, 
      start_list->vector_count);
   // has polygon been clipped out of existence?
   if (clipped_point_count==0)
      return;

   clipped_point_count=Clip_Points_Min(clipped_intermediates, clipped_points,
      clipped_point_count);
   // has polygon been clipped out of existence?
   if (clipped_point_count==0)
      return;

   Make_Vox_Runs(
      clipped_points,
      clipped_point_count,
      screen_runs,
      start_line,
      end_line);
   Render_Vox_Runs( 
      vox_ssector,
      screen_runs,
      start_line,
      end_line);
}

void Transform_Points(pvector2 start_list, pvector2 dest_list, short vector_count) {
   short vec_index;
   // get a translated list
   for (vec_index=0; vec_index<vector_count; vec_index++) {
      rotate_x=((start_list[vec_index].x<<SHIFT)-render_x);
      rotate_y=((start_list[vec_index].y<<SHIFT)-render_y);
      rotate_angle=render_view_angle;
      dest_list[vec_index].x=FixedRotateY();
      dest_list[vec_index].y=FixedRotateX();
      }
}

short Clip_Points_Max(pvector2 start_list, pvector2 dest_list, short vector_count) {
   pvector2 cur_vec, next_vec;
   short vec_index;
   short clip_counter;

   clip_counter=0;
   cur_vec=start_list+(vector_count-1);
   for (vec_index=0; vec_index<vector_count; vec_index++) {
      next_vec=start_list+vec_index;

      // categorize edges by types

      if ((cur_vec->y <= DIST_MAX_FIXED) && (next_vec->y <= DIST_MAX_FIXED)) {
         // edge not at all behind view volume
         dest_list[clip_counter].x=next_vec->x;
         dest_list[clip_counter++].y=next_vec->y;
      } /* endif */

      if ((cur_vec->y > DIST_MAX_FIXED) && (next_vec->y > DIST_MAX_FIXED)) {
         // all behind volume, so go on
         }

      if ((cur_vec->y <= DIST_MAX_FIXED) && (next_vec->y > DIST_MAX_FIXED)) {
         // edge is leaving view volume
         MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
         dest_list[clip_counter].y=DIST_MAX_FIXED;
         dest_list[clip_counter++].x=cur_vec->x +
            fixedmult(slope, DIST_MAX_FIXED-cur_vec->y);
         }

      if ((cur_vec->y > DIST_MAX_FIXED) && (next_vec->y <=DIST_MAX_FIXED)) {
         // edge is entering view volume
         MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
         dest_list[clip_counter].y=DIST_MAX_FIXED;
         dest_list[clip_counter++].x=cur_vec->x + 
            fixedmult(slope, DIST_MAX_FIXED-cur_vec->y);
         dest_list[clip_counter].x=next_vec->x;
         dest_list[clip_counter++].y=next_vec->y;
         }
      cur_vec=next_vec;
      }

return clip_counter;
}

short Clip_Points_Min(pvector2 start_list, pvector2 dest_list, short vector_count) {
   pvector2 cur_vec, next_vec;
   short vec_index;
   short clip_counter;

   clip_counter=0;
   cur_vec=start_list+(vector_count-1);
   for (vec_index=0; vec_index<vector_count; vec_index++) {
      next_vec=start_list+vec_index;

      // categorize edges by types

      if ((cur_vec->y >= DIST_MIN_FIXED) && (next_vec->y >= DIST_MIN_FIXED)) {
         // edge not at all inf front of view volume
         dest_list[clip_counter].x=next_vec->x;
         dest_list[clip_counter++].y=next_vec->y;
      } /* endif */

      if ((cur_vec->y < DIST_MIN_FIXED) && (next_vec->y < DIST_MIN_FIXED)) {
         // all in front of volume, so go on
         }

      if ((cur_vec->y >= DIST_MIN_FIXED) && (next_vec->y < DIST_MIN_FIXED)) {
         // edge is leaving view volume
         MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
         dest_list[clip_counter].y=DIST_MIN_FIXED;
         dest_list[clip_counter++].x=cur_vec->x +
            fixedmult(slope, DIST_MIN_FIXED-cur_vec->y);
         }

      if ((cur_vec->y < DIST_MIN_FIXED) && (next_vec->y >=DIST_MIN_FIXED)) {
         // edge is entering view volume
         MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
         dest_list[clip_counter].y=DIST_MIN_FIXED;
         dest_list[clip_counter++].x=cur_vec->x + 
            fixedmult(slope, DIST_MIN_FIXED-cur_vec->y);
         dest_list[clip_counter].x=next_vec->x;
         dest_list[clip_counter++].y=next_vec->y;
         }
      cur_vec=next_vec;
      }

return clip_counter;
}

void Make_Vox_Runs(
   pvector2 point_list,
   short point_count,
   pvox_run dest_runs,
   short & start_line,
   short & end_line) {

   short vec_index;
   short cur_dist;
   MYFIXED max_dist, min_dist;
   MYFIXED left_x, right_x;
   MYFIXED left_slope, right_slope;
   MYFIXED fixed_dist;
   short max_dist_index, left_vec, right_vec, last_vec;
 
   max_dist=0; 
   min_dist=MAXMYFIXED;
   max_dist_index=0;
   for (vec_index=0; vec_index<point_count; vec_index++) {
      if (point_list[vec_index].y<min_dist) {
         min_dist=point_list[vec_index].y;
      }
      if (point_list[vec_index].y>max_dist) {
         max_dist=point_list[vec_index].y;
         max_dist_index=vec_index;
      }
   }

   start_line=(min_dist+(DIST_INC-1))/DIST_INC;
   end_line=(max_dist+(DIST_INC-1))/DIST_INC;

   left_vec=max_dist_index;
   right_vec=max_dist_index;
   for (cur_dist=end_line-1; cur_dist>=start_line; cur_dist--) {
      fixed_dist=cur_dist*DIST_INC;

      // get on the correct left edge
      if (point_list[left_vec].y>fixed_dist) {
         while (point_list[left_vec].y>fixed_dist) {
            last_vec=left_vec;
            left_vec=(left_vec-1+point_count)%point_count;
            }
         left_slope=fixeddiv(point_list[left_vec].x-point_list[last_vec].x,
                           point_list[left_vec].y-point_list[last_vec].y);
         left_x=point_list[last_vec].x-fixedmult(left_slope, point_list[last_vec].y-fixed_dist);
      }

      // get on the correct right edge
      if (point_list[right_vec].y>fixed_dist) {
         while (point_list[right_vec].y>fixed_dist) {
            last_vec=right_vec;
            right_vec=(right_vec+1)%point_count;
            }
         right_slope=fixeddiv(point_list[right_vec].x-point_list[last_vec].x,
                           point_list[right_vec].y-point_list[last_vec].y);
         right_x=point_list[last_vec].x-fixedmult(right_slope, point_list[last_vec].y-fixed_dist);
      }

      // project values and put them in runs
      dest_runs[cur_dist].left=Project(left_x, fixed_dist);
      if (dest_runs[cur_dist].left<0) {
         dest_runs[cur_dist].left=0;
      }
      dest_runs[cur_dist].right=Project(right_x, fixed_dist);
      if (dest_runs[cur_dist].right>WINDOW_WIDTH) {
         dest_runs[cur_dist].right=WINDOW_WIDTH;
      }

      // update x values
      left_x-=fixedmult(left_slope, DIST_INC);
      right_x-=fixedmult(right_slope, DIST_INC);
   }
}

void Render_Vox_Runs(
   pssector vox_ssector,
   pvox_run screen_runs,
   short start_line,
   short end_line) {

   MYFIXED inc_scaler_x, inc_scaler_y;
   MYFIXED fixed_x, fixed_y;
   short left, right;
   psector vox_sector;
   short temp_light;

   vox_sector=GetSecFromSSec(vox_ssector);

   alt_array=(PUCHAR)vox_sector->extra_data;
   Setup_Vox_Sprite_Rend(vox_ssector->objects, start_line, end_line);
   // make sure previous run causes no drawing

   // setup constants for getting positions in map
   fixed_x=(render_x/VOXEL_SPEED_SCALE)<<(VOX_FP_SHIFT-SHIFT);
   fixed_y=(render_y/VOXEL_SPEED_SCALE)<<(VOX_FP_SHIFT-SHIFT);
 
   inc_scaler_x=(-floor_trans_x)>>XT_TO_VOX_SHIFT;
   inc_scaler_y=(-floor_trans_y)>>XT_TO_VOX_SHIFT;

   // file in any sprites before first line
   for (long cur_dis=0; cur_dis<start_line; cur_dis++)
      Do_Vox_Sprite_Line(0);

   short dist_inc;
   if (do_skipping) {
   if (start_line>DOUBLE_DIS) {
      if (start_line>QUAD_DIS) {
         dist_inc=4;
      } else {
         dist_inc=2;
      }
   } else {
      dist_inc=1;
   }
   } else dist_inc=1;

   // loop through a constant number of distances, draw a voxel row at each distance
   for (cur_dis=start_line; cur_dis<end_line; cur_dis+=dist_inc) {
      
      // Do them's sprites
      for (short cur_line=cur_dis-dist_inc+1; cur_line<=cur_dis; cur_line++)
        Do_Vox_Sprite_Line(cur_line*DIST_SCALER);

      // setup light table
      temp_light=(SecLight(vox_sector)-
         ((cur_dis*DIST_SCALER) >> (SecLTSpeed(vox_sector))) );
      if (temp_light<0) temp_light=0;
      if (temp_light>MAX_LIGHT) temp_light=MAX_LIGHT;
      v_light_table=pal_table[temp_light];
      // Setup correct scaling table
      cur_scaler=alt_scaler[cur_dis];

      // Setup top value for drawing
      starting_y=(SHORT)(GetZScVal(ALT_MAX*HEIGHT_SCALER, (cur_dis*DIST_SCALER)<<SHIFT)
         >> SHIFT);

      // get horizontal positions from run list
      left=screen_runs[cur_dis].left;
      right=screen_runs[cur_dis].right;

      // Get map positions at start of ray
      x_loc=(((rcos_table[render_view_angle]+floor_offsets_x[right-1]) * cur_dis)<<NORM_TO_VOX)+
         (fixed_x);
      y_loc=(((rsin_table[render_view_angle]+floor_offsets_y[right-1]) * cur_dis)<<NORM_TO_VOX)+
         (fixed_y);

      // Get increment in map
      x_inc=(cur_dis * inc_scaler_x);
      y_inc=(cur_dis * inc_scaler_y);

      // set horizontal render constants
      v_horiz_length=right-left;
      if (v_horiz_length<=0)
         continue;
      vox_buff=buff+left;
      prev_vox_colors=prev_colors+left;
      prev_vox_heights=win_bottoms+left;

      // adjust y to scale correctly through altitude bitmap
      y_loc<<=8;
      y_inc<<=8;


      if (do_shading) {
        //if ((ABS(x_inc)<SMOOTH_DELIMATOR_X)&&(ABS(y_inc)<SMOOTH_DELIMATOR_Y))
           Draw_Vox_Row_Smooth();
        //else Draw_Vox_Row();
      } else {
        Draw_Vox_Row_Fast();
      } /* endif */

      if (do_skipping) {
      if (cur_dis==DOUBLE_DIS) {
        dist_inc=2;
      }
      if (cur_dis==QUAD_DIS) {
        dist_inc=4;
      }
      }
   } /* endfor */

}

⌨️ 快捷键说明

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