VOXREND.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:12k
- #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 */
- }