?? voxrend.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 + -