home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / RAYCAST.ZIP / VOXREND.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-03  |  12.1 KB  |  393 lines

  1. #include <mem.h>
  2. #include "ray.h"
  3. #include "globals.h"
  4. #include "voxel.h"
  5. #include "rayrend.h"
  6. #include "asm.h"
  7. #include "screen.h"
  8. #include "mymem.h"
  9. #include "shading.h"
  10. #include "sprvox.h"
  11. #include "scrconf.h"
  12. #include "voxsky.h"
  13. #include "rcvars.h"
  14. #include "sortseg.h"
  15. #include "fixed.h"
  16. #include "prevarr.h"
  17. #include "skipping.h"
  18.  
  19. #define XT_TO_VOX_SHIFT 4
  20. #define NORM_TO_VOX 2
  21. #define SMOOTH_DELIMATOR_X 0x00004000
  22. #define SMOOTH_DELIMATOR_Y 0x00400000
  23. #define BLUE_COLOR 0x3f
  24. #define DIST_MIN_FIXED (DIST_SCALER*DIST_MIN<<SHIFT)
  25. #define DIST_MAX_FIXED (DIST_SCALER*DIST_MAX<<SHIFT)
  26. #define DIST_INC (DIST_SCALER<<SHIFT)
  27. #define MAX_SS_VECTORS 100
  28. #define DOUBLE_DIS 30
  29. #define QUAD_DIS 60
  30.  
  31. typedef struct VOX_RUN * pvox_run;
  32. typedef struct VOX_RUN{
  33.    short left, right;
  34.    } vox_run;
  35.  
  36. shade_mode do_shading;
  37. skipping_mode do_skipping;
  38.  
  39. void Set_Shading(shade_mode new_mode)
  40. {
  41. do_shading=new_mode;
  42. }
  43.  
  44. void Set_Skipping(skipping_mode new_mode)
  45. {
  46. do_skipping=new_mode;
  47. }
  48.  
  49. void Transform_Points(pvector2 start_list, pvector2 dest_list, short vector_count);
  50. short Clip_Points_Max(pvector2 start_list, pvector2 dest_list, short vector_count);
  51. short Clip_Points_Min(pvector2 start_list, pvector2 dest_list, short vector_count);
  52.  
  53. void Make_Vox_Runs(
  54.    pvector2 point_list,
  55.    short point_count,
  56.    pvox_run dest_runs,
  57.    short & start_line,
  58.    short & end_line);
  59.  
  60. void Render_Vox_Runs(
  61.    pssector vox_ssector,
  62.    pvox_run screen_runs,
  63.    short start_line,
  64.    short end_line);
  65.  
  66. void Render_Voxel_Sub_Sector(pssector vox_ssector)
  67. {
  68.    vector2 trans_list[MAX_SS_VECTORS];
  69.    vector2 clipped_points[MAX_SS_VECTORS];
  70.    vector2 clipped_intermediates[MAX_SS_VECTORS];
  71.    vox_run screen_runs[DIST_MAX];
  72.    short start_line, end_line;
  73.    psorted_vector_type start_list;
  74.    short clipped_point_count;
  75.  
  76.    start_list=(psorted_vector_type)vox_ssector->extra_data;
  77.  
  78.    // transform points relative to viewer
  79.    Transform_Points(start_list->vectors, trans_list, start_list->vector_count);
  80.  
  81.    // perform clipping, first against maximum distance, and then against minimum distance
  82.  
  83.    clipped_point_count=Clip_Points_Max(trans_list, clipped_intermediates, 
  84.       start_list->vector_count);
  85.    // has polygon been clipped out of existence?
  86.    if (clipped_point_count==0)
  87.       return;
  88.  
  89.    clipped_point_count=Clip_Points_Min(clipped_intermediates, clipped_points,
  90.       clipped_point_count);
  91.    // has polygon been clipped out of existence?
  92.    if (clipped_point_count==0)
  93.       return;
  94.  
  95.    Make_Vox_Runs(
  96.       clipped_points,
  97.       clipped_point_count,
  98.       screen_runs,
  99.       start_line,
  100.       end_line);
  101.    Render_Vox_Runs( 
  102.       vox_ssector,
  103.       screen_runs,
  104.       start_line,
  105.       end_line);
  106. }
  107.  
  108. void Transform_Points(pvector2 start_list, pvector2 dest_list, short vector_count) {
  109.    short vec_index;
  110.    // get a translated list
  111.    for (vec_index=0; vec_index<vector_count; vec_index++) {
  112.       rotate_x=((start_list[vec_index].x<<SHIFT)-render_x);
  113.       rotate_y=((start_list[vec_index].y<<SHIFT)-render_y);
  114.       rotate_angle=render_view_angle;
  115.       dest_list[vec_index].x=FixedRotateY();
  116.       dest_list[vec_index].y=FixedRotateX();
  117.       }
  118. }
  119.  
  120. short Clip_Points_Max(pvector2 start_list, pvector2 dest_list, short vector_count) {
  121.    pvector2 cur_vec, next_vec;
  122.    short vec_index;
  123.    short clip_counter;
  124.  
  125.    clip_counter=0;
  126.    cur_vec=start_list+(vector_count-1);
  127.    for (vec_index=0; vec_index<vector_count; vec_index++) {
  128.       next_vec=start_list+vec_index;
  129.  
  130.       // categorize edges by types
  131.  
  132.       if ((cur_vec->y <= DIST_MAX_FIXED) && (next_vec->y <= DIST_MAX_FIXED)) {
  133.          // edge not at all behind view volume
  134.          dest_list[clip_counter].x=next_vec->x;
  135.          dest_list[clip_counter++].y=next_vec->y;
  136.       } /* endif */
  137.  
  138.       if ((cur_vec->y > DIST_MAX_FIXED) && (next_vec->y > DIST_MAX_FIXED)) {
  139.          // all behind volume, so go on
  140.          }
  141.  
  142.       if ((cur_vec->y <= DIST_MAX_FIXED) && (next_vec->y > DIST_MAX_FIXED)) {
  143.          // edge is leaving view volume
  144.          MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
  145.          dest_list[clip_counter].y=DIST_MAX_FIXED;
  146.          dest_list[clip_counter++].x=cur_vec->x +
  147.             fixedmult(slope, DIST_MAX_FIXED-cur_vec->y);
  148.          }
  149.  
  150.       if ((cur_vec->y > DIST_MAX_FIXED) && (next_vec->y <=DIST_MAX_FIXED)) {
  151.          // edge is entering view volume
  152.          MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
  153.          dest_list[clip_counter].y=DIST_MAX_FIXED;
  154.          dest_list[clip_counter++].x=cur_vec->x + 
  155.             fixedmult(slope, DIST_MAX_FIXED-cur_vec->y);
  156.          dest_list[clip_counter].x=next_vec->x;
  157.          dest_list[clip_counter++].y=next_vec->y;
  158.          }
  159.       cur_vec=next_vec;
  160.       }
  161.  
  162. return clip_counter;
  163. }
  164.  
  165. short Clip_Points_Min(pvector2 start_list, pvector2 dest_list, short vector_count) {
  166.    pvector2 cur_vec, next_vec;
  167.    short vec_index;
  168.    short clip_counter;
  169.  
  170.    clip_counter=0;
  171.    cur_vec=start_list+(vector_count-1);
  172.    for (vec_index=0; vec_index<vector_count; vec_index++) {
  173.       next_vec=start_list+vec_index;
  174.  
  175.       // categorize edges by types
  176.  
  177.       if ((cur_vec->y >= DIST_MIN_FIXED) && (next_vec->y >= DIST_MIN_FIXED)) {
  178.          // edge not at all inf front of view volume
  179.          dest_list[clip_counter].x=next_vec->x;
  180.          dest_list[clip_counter++].y=next_vec->y;
  181.       } /* endif */
  182.  
  183.       if ((cur_vec->y < DIST_MIN_FIXED) && (next_vec->y < DIST_MIN_FIXED)) {
  184.          // all in front of volume, so go on
  185.          }
  186.  
  187.       if ((cur_vec->y >= DIST_MIN_FIXED) && (next_vec->y < DIST_MIN_FIXED)) {
  188.          // edge is leaving view volume
  189.          MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
  190.          dest_list[clip_counter].y=DIST_MIN_FIXED;
  191.          dest_list[clip_counter++].x=cur_vec->x +
  192.             fixedmult(slope, DIST_MIN_FIXED-cur_vec->y);
  193.          }
  194.  
  195.       if ((cur_vec->y < DIST_MIN_FIXED) && (next_vec->y >=DIST_MIN_FIXED)) {
  196.          // edge is entering view volume
  197.          MYFIXED slope=fixeddiv(next_vec->x-cur_vec->x, next_vec->y-cur_vec->y);
  198.          dest_list[clip_counter].y=DIST_MIN_FIXED;
  199.          dest_list[clip_counter++].x=cur_vec->x + 
  200.             fixedmult(slope, DIST_MIN_FIXED-cur_vec->y);
  201.          dest_list[clip_counter].x=next_vec->x;
  202.          dest_list[clip_counter++].y=next_vec->y;
  203.          }
  204.       cur_vec=next_vec;
  205.       }
  206.  
  207. return clip_counter;
  208. }
  209.  
  210. void Make_Vox_Runs(
  211.    pvector2 point_list,
  212.    short point_count,
  213.    pvox_run dest_runs,
  214.    short & start_line,
  215.    short & end_line) {
  216.  
  217.    short vec_index;
  218.    short cur_dist;
  219.    MYFIXED max_dist, min_dist;
  220.    MYFIXED left_x, right_x;
  221.    MYFIXED left_slope, right_slope;
  222.    MYFIXED fixed_dist;
  223.    short max_dist_index, left_vec, right_vec, last_vec;
  224.  
  225.    max_dist=0; 
  226.    min_dist=MAXMYFIXED;
  227.    max_dist_index=0;
  228.    for (vec_index=0; vec_index<point_count; vec_index++) {
  229.       if (point_list[vec_index].y<min_dist) {
  230.          min_dist=point_list[vec_index].y;
  231.       }
  232.       if (point_list[vec_index].y>max_dist) {
  233.          max_dist=point_list[vec_index].y;
  234.          max_dist_index=vec_index;
  235.       }
  236.    }
  237.  
  238.    start_line=(min_dist+(DIST_INC-1))/DIST_INC;
  239.    end_line=(max_dist+(DIST_INC-1))/DIST_INC;
  240.  
  241.    left_vec=max_dist_index;
  242.    right_vec=max_dist_index;
  243.    for (cur_dist=end_line-1; cur_dist>=start_line; cur_dist--) {
  244.       fixed_dist=cur_dist*DIST_INC;
  245.  
  246.       // get on the correct left edge
  247.       if (point_list[left_vec].y>fixed_dist) {
  248.          while (point_list[left_vec].y>fixed_dist) {
  249.             last_vec=left_vec;
  250.             left_vec=(left_vec-1+point_count)%point_count;
  251.             }
  252.          left_slope=fixeddiv(point_list[left_vec].x-point_list[last_vec].x,
  253.                            point_list[left_vec].y-point_list[last_vec].y);
  254.          left_x=point_list[last_vec].x-fixedmult(left_slope, point_list[last_vec].y-fixed_dist);
  255.       }
  256.  
  257.       // get on the correct right edge
  258.       if (point_list[right_vec].y>fixed_dist) {
  259.          while (point_list[right_vec].y>fixed_dist) {
  260.             last_vec=right_vec;
  261.             right_vec=(right_vec+1)%point_count;
  262.             }
  263.          right_slope=fixeddiv(point_list[right_vec].x-point_list[last_vec].x,
  264.                            point_list[right_vec].y-point_list[last_vec].y);
  265.          right_x=point_list[last_vec].x-fixedmult(right_slope, point_list[last_vec].y-fixed_dist);
  266.       }
  267.  
  268.       // project values and put them in runs
  269.       dest_runs[cur_dist].left=Project(left_x, fixed_dist);
  270.       if (dest_runs[cur_dist].left<0) {
  271.          dest_runs[cur_dist].left=0;
  272.       }
  273.       dest_runs[cur_dist].right=Project(right_x, fixed_dist);
  274.       if (dest_runs[cur_dist].right>WINDOW_WIDTH) {
  275.          dest_runs[cur_dist].right=WINDOW_WIDTH;
  276.       }
  277.  
  278.       // update x values
  279.       left_x-=fixedmult(left_slope, DIST_INC);
  280.       right_x-=fixedmult(right_slope, DIST_INC);
  281.    }
  282. }
  283.  
  284. void Render_Vox_Runs(
  285.    pssector vox_ssector,
  286.    pvox_run screen_runs,
  287.    short start_line,
  288.    short end_line) {
  289.  
  290.    MYFIXED inc_scaler_x, inc_scaler_y;
  291.    MYFIXED fixed_x, fixed_y;
  292.    short left, right;
  293.    psector vox_sector;
  294.    short temp_light;
  295.  
  296.    vox_sector=GetSecFromSSec(vox_ssector);
  297.  
  298.    alt_array=(PUCHAR)vox_sector->extra_data;
  299.    Setup_Vox_Sprite_Rend(vox_ssector->objects, start_line, end_line);
  300.    // make sure previous run causes no drawing
  301.  
  302.    // setup constants for getting positions in map
  303.    fixed_x=(render_x/VOXEL_SPEED_SCALE)<<(VOX_FP_SHIFT-SHIFT);
  304.    fixed_y=(render_y/VOXEL_SPEED_SCALE)<<(VOX_FP_SHIFT-SHIFT);
  305.  
  306.    inc_scaler_x=(-floor_trans_x)>>XT_TO_VOX_SHIFT;
  307.    inc_scaler_y=(-floor_trans_y)>>XT_TO_VOX_SHIFT;
  308.  
  309.    // file in any sprites before first line
  310.    for (long cur_dis=0; cur_dis<start_line; cur_dis++)
  311.       Do_Vox_Sprite_Line(0);
  312.  
  313.    short dist_inc;
  314.    if (do_skipping) {
  315.    if (start_line>DOUBLE_DIS) {
  316.       if (start_line>QUAD_DIS) {
  317.          dist_inc=4;
  318.       } else {
  319.          dist_inc=2;
  320.       }
  321.    } else {
  322.       dist_inc=1;
  323.    }
  324.    } else dist_inc=1;
  325.  
  326.    // loop through a constant number of distances, draw a voxel row at each distance
  327.    for (cur_dis=start_line; cur_dis<end_line; cur_dis+=dist_inc) {
  328.       
  329.       // Do them's sprites
  330.       for (short cur_line=cur_dis-dist_inc+1; cur_line<=cur_dis; cur_line++)
  331.         Do_Vox_Sprite_Line(cur_line*DIST_SCALER);
  332.  
  333.       // setup light table
  334.       temp_light=(SecLight(vox_sector)-
  335.          ((cur_dis*DIST_SCALER) >> (SecLTSpeed(vox_sector))) );
  336.       if (temp_light<0) temp_light=0;
  337.       if (temp_light>MAX_LIGHT) temp_light=MAX_LIGHT;
  338.       v_light_table=pal_table[temp_light];
  339.       // Setup correct scaling table
  340.       cur_scaler=alt_scaler[cur_dis];
  341.  
  342.       // Setup top value for drawing
  343.       starting_y=(SHORT)(GetZScVal(ALT_MAX*HEIGHT_SCALER, (cur_dis*DIST_SCALER)<<SHIFT)
  344.          >> SHIFT);
  345.  
  346.       // get horizontal positions from run list
  347.       left=screen_runs[cur_dis].left;
  348.       right=screen_runs[cur_dis].right;
  349.  
  350.       // Get map positions at start of ray
  351.       x_loc=(((rcos_table[render_view_angle]+floor_offsets_x[right-1]) * cur_dis)<<NORM_TO_VOX)+
  352.          (fixed_x);
  353.       y_loc=(((rsin_table[render_view_angle]+floor_offsets_y[right-1]) * cur_dis)<<NORM_TO_VOX)+
  354.          (fixed_y);
  355.  
  356.       // Get increment in map
  357.       x_inc=(cur_dis * inc_scaler_x);
  358.       y_inc=(cur_dis * inc_scaler_y);
  359.  
  360.       // set horizontal render constants
  361.       v_horiz_length=right-left;
  362.       if (v_horiz_length<=0)
  363.          continue;
  364.       vox_buff=buff+left;
  365.       prev_vox_colors=prev_colors+left;
  366.       prev_vox_heights=win_bottoms+left;
  367.  
  368.       // adjust y to scale correctly through altitude bitmap
  369.       y_loc<<=8;
  370.       y_inc<<=8;
  371.  
  372.  
  373.       if (do_shading) {
  374.         //if ((ABS(x_inc)<SMOOTH_DELIMATOR_X)&&(ABS(y_inc)<SMOOTH_DELIMATOR_Y))
  375.            Draw_Vox_Row_Smooth();
  376.         //else Draw_Vox_Row();
  377.       } else {
  378.         Draw_Vox_Row_Fast();
  379.       } /* endif */
  380.  
  381.       if (do_skipping) {
  382.       if (cur_dis==DOUBLE_DIS) {
  383.         dist_inc=2;
  384.       }
  385.       if (cur_dis==QUAD_DIS) {
  386.         dist_inc=4;
  387.       }
  388.       }
  389.    } /* endfor */
  390.  
  391. }
  392.  
  393.