home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / PCGLOVE / GLOVE / OBJGLV.ZIP / SRC / DEMO4B / INT / RENDREP.CPP < prev    next >
C/C++ Source or Header  |  1993-05-02  |  57KB  |  2,828 lines

  1. /* 3D graphics routines */
  2.  
  3. /* Written by Bernie Roehl and Dave Stampe, December 1991 */
  4. /* updated 10/1/91 to do first clip pass */
  5. /* completely operational 19/1/92 incl. integerization */
  6.  
  7. /* Contact: broehl@sunee.waterloo.edu or dstampe@sunee.waterloo.edu */
  8.  
  9. #pragma inline
  10.  
  11. #include <stdio.h>
  12. #include <math.h>
  13. #include <ctype.h>
  14. #include <assert.h>
  15. #include <alloc.h>
  16. #include <dos.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19.  
  20. #include "3dstruct.hpp"
  21. #include "intmath.h"
  22. #include "vd2.hpp"
  23. #include "mathinit.hpp"
  24. #include "colormap.hpp"
  25.  
  26. static VIEW *current_view;
  27.  
  28. int wireframe = 0;
  29.  
  30. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  31. static float xfsc = XFSC;
  32.  
  33.  
  34.  
  35.  
  36. /**************** SET AND COMPUTE VIEWPORT **************/
  37.  
  38.       /* static viewport data copies (assembly speed) */
  39.  
  40. static long  fact1, fact2, fact3, fact4, fact5, fact6, fact7, fact8, fact9;
  41. static long  fac1, fac2, fac3, fac4, fac5, fac6, fac7, fac8, fac9;
  42.  
  43. static long  iview_x, iview_y, iview_z;
  44. static long  ilight_x, ilight_y, ilight_z;
  45.  
  46. static long  hither,yon,left,right,top,bottom;
  47. static long  hither4,yon4,left4,right4,top4,bottom4; /* prescaled */
  48.  
  49. static long left_C, left_M;     /* spherical object clip coefficients */
  50. static long right_C, right_M;
  51. static long top_C, top_M;
  52. static long bot_C, bot_M;
  53.  
  54. static long hsw, hsh;        /* half screen width, height */
  55. static long hsc, vsc;        /* screen center with offset */
  56.  
  57. static int xshift, yshift;      /* binary exponent factors */
  58. static long sx,sy;              /* screen scale mantissa */
  59. static long scx,scy;
  60.  
  61. static int orientation;        /* flipping for weird displays */
  62.  
  63. int ambient_light = 72;        /* viewport ambient light */
  64. static int directional_light = 0;    /* directional or point light */
  65.  
  66.  
  67. void render_set_view(VIEW *v)    /* copy viewport data to fast access area */
  68. {
  69.  current_view = v;
  70.  
  71.  ambient_light = v->ambient;
  72.  directional_light = v->directional;
  73.  
  74.  sx = v->sx;
  75.  sy = v->sy;
  76.  scx = v->scx;
  77.  scy = v->scy;
  78.  orientation = v->orientation;
  79.  if(orientation & XFLIP) sx = -sx;
  80.  if(orientation & YFLIP) sy = -sy;
  81.  
  82.  fac1 = v->eye_xform[0][0];
  83.  fac2 = v->eye_xform[0][1];
  84.  fac3 = v->eye_xform[0][2];
  85.  fac4 = v->eye_xform[1][0];
  86.  fac5 = v->eye_xform[1][1];
  87.  fac6 = v->eye_xform[1][2];
  88.  fact7 = fac7 = v->eye_xform[2][0];
  89.  fact8 = fac8 = v->eye_xform[2][1];
  90.  fact9 = fac9 = v->eye_xform[2][2];
  91.  
  92.  asm {
  93.     .386                  /* produce scaled matrix for screen size */
  94.     mov    eax,DWORD PTR sx
  95.     imul    DWORD PTR fac1
  96.     shrd    eax,edx,16
  97.     adc    eax,0
  98.     mov    DWORD PTR fact1,eax
  99.  
  100.     mov    eax,DWORD PTR sx
  101.     imul    DWORD PTR fac2
  102.     shrd    eax,edx,16
  103.     adc    eax,0
  104.     mov    DWORD PTR fact2,eax
  105.  
  106.     mov    eax,DWORD PTR sx
  107.     imul    DWORD PTR fac3
  108.     shrd    eax,edx,16
  109.     adc    eax,0
  110.     mov    DWORD PTR fact3,eax
  111.  
  112.     mov    eax,DWORD PTR sy
  113.     imul    DWORD PTR fac4
  114.     shrd    eax,edx,16
  115.     adc    eax,0
  116.     mov    DWORD PTR fact4,eax
  117.  
  118.     mov    eax,DWORD PTR sy
  119.     imul    DWORD PTR fac5
  120.     shrd    eax,edx,16
  121.     adc    eax,0
  122.     mov    DWORD PTR fact5,eax
  123.  
  124.     mov    eax,DWORD PTR sy
  125.     imul    DWORD PTR fac6
  126.     shrd    eax,edx,16
  127.     adc    eax,0
  128.     mov    DWORD PTR fact6,eax
  129.      }
  130.  
  131.  iview_x = v->eye_xform[3][0];   /* viewport center */
  132.  iview_y = v->eye_xform[3][1];
  133.  iview_z = v->eye_xform[3][2];
  134.  
  135.  ilight_x = v->lx;               /* light source */
  136.  ilight_y = v->ly;
  137.  ilight_z = v->lz;
  138.  
  139.  hither  = v->hither;            /* clipping planes */
  140.  left    = v->left;
  141.  yon     = v->yon;
  142.  top     = v->top;
  143.  right   = v->right;
  144.  bottom  = v->bottom;
  145.  
  146. /* yon4    = yon    << PRESCALEZ;   /* prescaled clipping planes for tests */
  147. /* hither4 = hither << PRESCALEZ;   */
  148. /* top4    = top    << PRESCALE;    */
  149. /* bottom4 = bottom << PRESCALE;    */
  150. /* left4   = left   << PRESCALE;    */
  151. /* right4  = right  << PRESCALE;    */
  152.  
  153.  _CX = PRESCALEZ;
  154.  asm {
  155.     mov    eax,DWORD PTR yon
  156.     shl    eax,cl
  157.     mov    DWORD PTR yon4,eax
  158.  
  159.     mov    eax,DWORD PTR hither
  160.     shl    eax,cl
  161.     mov    DWORD PTR hither4,eax
  162.      }
  163.  
  164.   _CX = PRESCALE;
  165.   asm {
  166.     mov    eax,DWORD PTR top
  167.     shl    eax,cl
  168.     mov    DWORD PTR top4,eax
  169.  
  170.     mov    eax,DWORD PTR bottom
  171.     shl    eax,cl
  172.     mov    DWORD PTR bottom4,eax
  173.  
  174.     mov    eax,DWORD PTR left
  175.     shl    eax,cl
  176.     mov    DWORD PTR left4,eax
  177.  
  178.     mov    eax,DWORD PTR right
  179.     shl    eax,cl
  180.     mov     DWORD PTR right4,eax
  181.        }
  182.  
  183.  left_C  = v->left_C;             /* spherical clip coefficients */
  184.  left_M  = v->left_M;
  185.  right_C = v->right_C;
  186.  right_M = v->right_M;
  187.  top_C   = v->top_C;
  188.  top_M   = v->top_M;
  189.  bot_C   = v->bot_C;
  190.  bot_M   = v->bot_M;
  191.  
  192.  hsw = v->hsw;
  193.  hsh = v->hsh;            /* half screen width, height*/
  194.  hsc = v->hsc;
  195.  vsc = v->vsc;            /* screen center */
  196.  
  197.  _CX = PRESCALE;
  198.  asm {
  199.     mov    eax,DWORD PTR hsc
  200.     shl    eax,cl
  201.     mov    DWORD PTR hsc,eax
  202.  
  203.     mov    eax,DWORD PTR vsc
  204.     shl    eax,cl
  205.     mov    DWORD PTR vsc,eax
  206.      }
  207.  
  208.  xshift = v->xshift;
  209.  yshift = v->yshift;           /* binary part of form factors */
  210.  
  211.  wireframe = v->flags & WIREFRAME;
  212. }
  213.  
  214.  
  215.  
  216.                  /* tables for sphere object clipping:   */
  217. extern long sclip_C[800]; /* 1/sqrt(zoom^2 + 1) table           */
  218. extern long sclip_M[800]; /* zoom * C table  (table: i = 32*zoom) */
  219.                  /* range: FOV = 2*atan(1/zoom)          */
  220.                  /* or about 150 to 7 degrees         */
  221. /* thus: for smaller window, divide zoom by fraction of h. screen */
  222.  
  223.                     /* compute screen and viewport   */
  224.                     /* factors.  These stay constant */
  225.                     /* over eye point changes        */
  226. void initialize_screen_factors(VIEW *v)
  227. {
  228.  long sx,sy;
  229.  int ti,bi,li,ri;
  230.  long sh,sw;
  231.  int xshift,yshift;
  232.  
  233.  long zoom = v->zoom;
  234.  long aspect = v->aspect;
  235.  int x_offset = v->x_offset;
  236.  int y_offset = v->y_offset;
  237.  long tt = v->top;
  238.  long bb = v->bottom;
  239.  long ll = v->left;
  240.  long rr = v->right;
  241.  long r1,r2;
  242.  long scx, scy;
  243.  
  244. /*
  245.  v->hsc = (v->left + v->right)/2 + v->x_offset;
  246.  v->vsc = (v->top + v->bottom)/2 + v->y_offset;
  247.  v->hsw = sw = (v->right - v->left)/2;
  248.  v->hsh = sh = (v->bottom - v->top)/2;
  249.                     */
  250.  asm {
  251.     mov    eax,ll
  252.     add    eax,rr
  253.     shr    eax,1
  254.     add    ax,x_offset
  255.     mov    r1,eax
  256.  
  257.     mov    eax,tt
  258.     add    eax,bb
  259.     shr    eax,1
  260.     add    ax,y_offset
  261.     mov    r2,eax
  262.  
  263.     mov    eax,rr
  264.     sub    eax,ll
  265.     shr    eax,1
  266.     mov     sw,eax
  267.  
  268.     mov    eax,bb
  269.     sub    eax,tt
  270.     shr    eax,1
  271.     mov     sh,eax
  272.      }
  273.  v->hsc = r1;
  274.  v->vsc = r2;
  275.  v->hsw = sw;
  276.  v->hsh = sh;
  277.  
  278.              /* setup zoom (FOV) */
  279.  if(zoom > 16*65536L) zoom = 16*65536L;     /* clip zoom to < 16 */
  280.  if(zoom < 32768L)  zoom = 32768L;     /* clip zoom to > 0.5 */
  281.  
  282.  if(v->orientation&XFLIP) x_offset = -x_offset;
  283.  if(v->orientation&YFLIP) y_offset = -y_offset;
  284.  
  285.  asm {
  286.     .386
  287.  
  288.     mov    eax,zoom     /* left pc = z*w/(w+xo) */
  289.     mov    edx,sw
  290.     imul    edx
  291.     push    eax
  292.     push    edx
  293.  
  294.     mov    ebx,sw
  295.     add    bx,x_offset
  296.     movzx    ebx,bx
  297.     idiv    ebx
  298.     shr    eax,12
  299.     mov    li,ax
  300.  
  301.     pop    edx
  302.     pop    eax
  303.     mov    ebx,sw       /* right pc = z*w/(w-xo) */
  304.     sub    bx,x_offset
  305.     movzx    ebx,bx
  306.     idiv    ebx
  307.     shr    eax,12
  308.     mov    ri,ax
  309.                  /* compute vert. scale zoom */
  310. /* zoom * sw / sh * (aspect/65536.0); */
  311.     mov    eax,zoom        /* <16.16> */
  312.     mul    DWORD PTR aspect        /* <16.16> -> <32.32> */
  313.     shrd    eax,edx,16        /* -> <16.16> */
  314.     mul    DWORD PTR sw
  315.     div    DWORD PTR sh        /* still <16.16> */
  316.  
  317.     mov    edx,sh      /* top pc = z*h/(h+yo) */
  318.     imul    edx
  319.     push    edx
  320.     push    eax
  321.  
  322.     mov    ebx,sh
  323.     add    bx,y_offset
  324.     movzx    ebx,bx
  325.     idiv    ebx
  326.     shr    eax,12
  327.     mov    ti,ax
  328.  
  329.     pop    eax          /* bot pc = z*h/(h-yo) */
  330.     pop    edx
  331.     mov    ebx,sh
  332.     sub    bx,y_offset
  333.     movzx    ebx,bx
  334.     idiv    ebx
  335.     shr    eax,12
  336.     mov    bi,ax
  337.       }
  338.  
  339.  if(li>799)li=799;
  340.  if(ri>799)ri=799;
  341.  if(ti>799)ti=799;
  342.  if(bi>799)bi=799;
  343.  
  344.  v->left_C  = sclip_C[li];             /* spherical clip coefficients */
  345.  v->left_M  = sclip_M[li];
  346.  v->right_C = sclip_C[ri];
  347.  v->right_M = sclip_M[ri];
  348.  v->top_C   = sclip_C[ti];
  349.  v->top_M   = sclip_M[ti];
  350.  v->bot_C   = sclip_C[bi];
  351.  v->bot_M   = sclip_M[bi];
  352.  
  353.  xshift = yshift = PRESCALEZ;    /* preset shifts */
  354.             /* compute screen scaling factors  */
  355.             /* which are pseudo-floating point */
  356.             /* to maximize precision and range */
  357.             /* width sets overall scaling      */
  358.  
  359. /* sx = v->hsw * (zoom/65536.0);                       */
  360. /* sy = v->hsw * (zoom/65536.0) * (v->aspect/65536.0); */
  361.  asm {
  362.     mov    eax,zoom        /* <16.16>            */
  363.     mul    DWORD PTR aspect        /* <16.16> -> <32.32> */
  364.     shrd    eax,edx,16        /* -> <16.16>         */
  365.     mul    DWORD PTR sw            /* <16.0> -> <48.16>  */
  366.     mov    scy, eax
  367.     bsr    ecx,eax
  368.     sub    cx,15
  369.     jle    nofixs
  370.     add     yshift,cx        /* and record shift */
  371.     shrd    eax,edx,cl        /* normalize to <16.16> */
  372.      }
  373. nofixs:
  374.  asm {
  375.     mov    DWORD PTR sy,eax
  376.  
  377.     mov    eax,zoom        /* <16.16>            */
  378.     mul    DWORD PTR sw            /* <16.0> -> <48.16>  */
  379.     mov    scx,eax
  380.     bsr    ecx,eax
  381.     sub    cx,15
  382.     jle    nofixs2
  383.     add     xshift,cx        /* and record shift */
  384.     shrd    eax,edx,cl        /* normalize to <16.16> */
  385.      }
  386. nofixs2:
  387.  asm {
  388.     mov    DWORD PTR sx,eax
  389.      }
  390.  
  391.  v->xshift = xshift;
  392.  v->yshift = yshift;
  393.  v->sx = sx;
  394.  v->sy = sy;
  395.  v->scx = scx;
  396.  v->scy = scy;
  397. }
  398.  
  399.  
  400.     /* compute eye point/ angle movement factors only */
  401.  
  402. void fast_view_factors(VIEW *v)
  403. {
  404.  MATRIX m;
  405.  
  406.  std_matrix(m, v->tilt,v->pan,v->roll,v->ex,v->ey,v->ez);
  407.  matrix_transpose(m, v->eye_xform);   /* copy matrix rotational inverse */
  408.  v->eye_xform[3][0] = m[3][0];
  409.  v->eye_xform[3][1] = m[3][1];
  410.  v->eye_xform[3][2] = m[3][2];
  411. }
  412.  
  413.     /* compute viewport factors (lotsa room for improvement, but */
  414.     /* this is only done once.  Some stuff will not change       */
  415.     /* 100% compatible with original (bit of a waste of time)    */
  416.  
  417. void compute_view_factors(VIEW *v)
  418. {
  419.  v->orientation = NOFLIP;
  420.  v->x_offset = 0;
  421.  v->y_offset = 0;
  422.  initialize_screen_factors(v);
  423.  fast_view_factors(v);
  424. }
  425.  
  426.                                                         /* matrix gives view vector and origin */
  427.                                                         /* while viewpoint matrix is world->cam xform */
  428.  
  429. void matrix_view_factors(VIEW *v,MATRIX m) /* set up from matrix xform */
  430. {
  431.  matrix_transpose(m, v->eye_xform);   /* copy matrix rotational inverse */
  432.  v->eye_xform[3][0] = m[3][0];
  433.  v->eye_xform[3][1] = m[3][1];
  434.  v->eye_xform[3][2] = m[3][2];
  435. }
  436.  
  437.  
  438. void view_to_matrix(VIEW *v,MATRIX m)      /* view matrix to xform matrix */
  439. {
  440.  matrix_transpose(v->eye_xform, m);   /* copy matrix rotational inverse */
  441.  m[3][0] = v->eye_xform[3][0];
  442.  m[3][1] = v->eye_xform[3][1];
  443.  m[3][2] = v->eye_xform[3][2];
  444. }
  445.  
  446.  
  447. /************ HORIZON IMPLEMENTATION MATH *****************/
  448.  
  449. int above_horizon(long x, long y, VIEW *v)
  450. {
  451.  long scx = v->scx;
  452.  long scy = v->scy;
  453.  long B = v->eye_xform[0][1];
  454.  long E = v->eye_xform[1][1];
  455.  long H = v->eye_xform[2][1];
  456.  
  457.  x -= v->hsc;
  458.  y = -y + v->vsc;
  459.  
  460.  if(v->orientation & XFLIP) scx = -scx;
  461.  if(v->orientation & YFLIP) scy = -scy;
  462.  
  463.  asm {
  464.     mov    eax,x
  465.     imul    DWORD PTR B
  466.     idiv    DWORD PTR scx
  467.     mov    ecx,eax
  468.     mov    eax,y
  469.     imul    DWORD PTR E
  470.     idiv    DWORD PTR scy
  471.     add    ecx,eax
  472.     mov    eax, H
  473.     neg    eax
  474.     sar    eax,16
  475.     cmp    ecx,eax
  476.     jge    above
  477.      }
  478.  return 0;
  479. above:
  480.  return 1;
  481. }
  482.  
  483.  
  484. long y_horizon(long x, VIEW *v)
  485. {
  486.  long scx = v->scx;
  487.  long scy = v->scy;
  488.  long B = v->eye_xform[0][1];
  489.  long E = v->eye_xform[1][1];
  490.  long H = v->eye_xform[2][1];
  491.  long result;
  492.  
  493.  x -= v->hsc;
  494.  
  495.  if(v->orientation & XFLIP) scx = -scx;
  496.  if(v->orientation & YFLIP) scy = -scy;
  497.  
  498.  asm {
  499.     mov    eax,x
  500.     imul    DWORD PTR B
  501.     idiv    DWORD PTR scx
  502.     mov    edx, H
  503.     sar    edx,16
  504.     add    eax,edx
  505.     neg    eax
  506.     imul    DWORD PTR scy
  507.     idiv     DWORD PTR E
  508.     mov    result,eax
  509.      }
  510.  return -result + v->vsc;
  511. }
  512.  
  513.  
  514. long x_horizon(long y, VIEW *v)
  515. {
  516.  long scx = v->scx;
  517.  long scy = v->scy;
  518.  long B = v->eye_xform[0][1];
  519.  long E = v->eye_xform[1][1];
  520.  long H = v->eye_xform[2][1];
  521.  long result;
  522.  
  523.  y = -y + v->vsc;
  524.  
  525.  if(v->orientation & XFLIP) scx = -scx;
  526.  if(v->orientation & YFLIP) scy = -scy;
  527.  
  528.  asm {
  529.     mov    eax,y
  530.     imul    DWORD PTR E
  531.     idiv    DWORD PTR scy
  532.     mov    edx, H
  533.     sar    edx,16
  534.     add    eax,edx
  535.     neg    eax
  536.     imul    DWORD PTR scx
  537.     idiv     DWORD PTR B
  538.     mov    result,eax
  539.      }
  540.  return result + v->hsc;
  541. ;
  542. }
  543.  
  544.  
  545.  
  546. /************ VERTEX AND POLY COPY MEMORY ALLOCATION ************/
  547.  
  548. static int r_objects_tested;
  549. static int r_objects_passed;
  550. static int r_polys_tested;
  551. static int r_polys_passed;
  552. static int r_polys_xyclipped;
  553. static int r_polys_drawn;
  554. static int r_vertices;
  555. static int r_new_vertices;
  556.  
  557.  
  558. DSORT *vispolys;       /* an array of pointers to visible polygons */
  559. DSORT *visobjs;
  560. DSORT *polist;        /* which array to put polys in */
  561.  
  562. int npols = 0;
  563.  
  564. static NVERTEX *vtxram;       /* memory allocation area start */
  565. static NVERTEX *nvalloc;      /* memory alloc ptrs */
  566. static NPOLY *npalloc;
  567. static OK;              /* cleared if too many vertices */
  568.  
  569. static int maxpolys = 1200;
  570.  
  571. void reset_render()           /* free copy space */
  572. {
  573.  free(vtxram);
  574.  free(vispolys);
  575.  free(visobjs);
  576. }
  577.  
  578. static unsigned render_mem;
  579.  
  580.                 /* get space for poly and vertex working
  581.                    copies */
  582. void setup_render(unsigned mem, int polys)
  583. {
  584.  maxpolys = polys;
  585.  render_mem = mem<<10;
  586.  if(mem>63) abort();
  587.  if(NULL==(vtxram = (NVERTEX *)calloc(mem,1024))) goto emem;
  588.  if(NULL==(vispolys = (DSORT *)calloc(maxpolys,sizeof(DSORT))))
  589.   {
  590.    free(vtxram);
  591.    goto emem;
  592.   }
  593.  if(NULL ==(visobjs = (DSORT *)calloc(maxpolys,sizeof(DSORT))))
  594.   {
  595.    free(vtxram);
  596.    free(vispolys);
  597.    goto emem;
  598.   }
  599.  else goto nemem;
  600.  
  601. emem:
  602.   {
  603.    printf("\nCannot allocate memory for renderer!\n");
  604.    abort();
  605.   }
  606.  
  607. nemem:
  608.  npalloc = (NPOLY *)vtxram;
  609.  nvalloc = (NVERTEX *)((char *)vtxram+render_mem-50);
  610.  fill_sqrt();
  611.  fill_sine();
  612.  fill_sclip();
  613. }
  614.  
  615.  
  616. static void init_render()               /* reclaim all vertex and poly space */
  617. {
  618.  npalloc = (NPOLY *)vtxram;
  619.  nvalloc = (NVERTEX *)((char *)vtxram+render_mem-50);
  620. }
  621.  
  622.  
  623.  
  624. static NVERTEX *newvertex()             /* alloc space for new vertex copy */
  625. {
  626.  NVERTEX *v;
  627.  
  628.  
  629. r_new_vertices++;
  630.  
  631.  
  632.  _CX = sizeof(NVERTEX);
  633.  asm {
  634.     mov    eax,DWORD PTR nvalloc     /* save address to v */
  635.     sub    ax,cx
  636.     mov    DWORD PTR v,eax
  637.     mov    DWORD PTR nvalloc,eax     /* update pointer */
  638.     les    bx,DWORD PTR v
  639.     mov    BYTE PTR es:[bx].(NVERTEX)perspect,0    /* reset flags */
  640.     sub    ax,200
  641.     cmp    ax,WORD PTR npalloc
  642.     ja    ok_v
  643.     xor    ax,ax
  644.     mov    WORD PTR OK,ax
  645.      }
  646. ok_v:
  647.  return(v);
  648. }
  649.  
  650. static NPOLY *newpoly()             /* alloc space for new poly copy */
  651. {
  652.  NPOLY *p;
  653.  
  654.  _CX = sizeof(NPOLY);
  655.  asm {
  656.     mov    eax,DWORD PTR npalloc     /* save address to v */
  657.     mov    DWORD PTR p,eax
  658.     add     ax,cx
  659.     mov    DWORD PTR npalloc,eax     /* update pointer */
  660.     add    ax,200
  661.     cmp    ax,WORD PTR nvalloc
  662.     jb    ok_p
  663.     xor    ax,ax
  664.     mov    WORD PTR OK,ax
  665.      }
  666. ok_p:
  667.  return(p);
  668. }
  669.  
  670.  
  671.  
  672.  
  673. /*********** TRANSFORMS 'N THINGS ************/
  674.  
  675.     /* X, Y viewport xform, create new vertex copy if needed */
  676.     /* used during Z clip pass only */
  677.  
  678. static NVERTEX *xy_transform(VERTEX *v)
  679. {
  680.  NVERTEX *nv;
  681.  
  682.  long wx,wy,wz;
  683.  
  684.  asm {                               /* quick test if conv. needed */
  685.     les    bx,DWORD PTR v
  686.     mov    eax,DWORD PTR es:[bx].(VERTEX)new_copy
  687.     mov    DWORD PTR nv,eax
  688.     or    eax,eax
  689.     jz    need_new_one
  690.      }
  691.  return(nv);
  692.  
  693. need_new_one:
  694.  
  695.  nv = newvertex();
  696.  
  697.  asm {
  698.     .386
  699.     push    si
  700.     push    di
  701.     les    bx,DWORD PTR v
  702.     mov    eax,DWORD PTR es:[bx].(VERTEX)x
  703.     sub    eax,DWORD PTR iview_x
  704.     mov    DWORD PTR wx,eax
  705.  
  706.     mov    eax,DWORD PTR es:[bx].(VERTEX)y
  707.     sub    eax,DWORD PTR iview_y
  708.     mov    DWORD PTR wy,eax
  709.  
  710.     mov    eax,DWORD PTR es:[bx].(VERTEX)z
  711.     sub    eax,DWORD PTR iview_z
  712.     mov    DWORD PTR wz,eax
  713.  
  714.     mov    eax,DWORD PTR fact1
  715.     mov    edx,DWORD PTR wx
  716.     imul    edx
  717.     mov    esi,eax
  718.     mov    edi,edx
  719.  
  720.     mov    eax,DWORD PTR fact2
  721.     mov    edx,DWORD PTR wy
  722.     imul    edx
  723.     add    esi,eax
  724.     adc    edi,edx
  725.  
  726.     mov    eax,DWORD PTR fact3
  727.     mov    edx,DWORD PTR wz
  728.     imul    edx
  729.     add    esi,eax
  730.     adc    edi,edx
  731.  
  732.     shrd    esi,edi,27        /* 29 - PRESCALE */
  733.     adc    esi,0
  734.     mov    ecx,esi
  735.  
  736.     mov    eax,DWORD PTR fact4
  737.     mov    edx,DWORD PTR wx
  738.     imul    edx
  739.     mov    esi,eax
  740.     mov    edi,edx
  741.  
  742.     mov    eax,DWORD PTR fact5
  743.     mov    edx,DWORD PTR wy
  744.     imul    edx
  745.     add    esi,eax
  746.     adc    edi,edx
  747.  
  748.     mov    eax,DWORD PTR fact6
  749.     mov    edx,DWORD PTR wz
  750.     imul    edx
  751.     add    esi,eax
  752.     adc    edi,edx
  753.  
  754.     shrd    esi,edi,27        /* 29 - PRESCALE */
  755.     adc    esi,0
  756.     mov    eax,esi
  757.  
  758.     mov    esi,DWORD PTR nv
  759.     mov    DWORD PTR es:[bx].(VERTEX)new_copy,esi
  760.     mov    esi,DWORD PTR es:[bx].(VERTEX)cz   /* copy z (conv before) */
  761.  
  762.     les    bx, DWORD PTR nv
  763.     mov    DWORD PTR es:[bx].(NVERTEX)x,ecx    /* new x,y */
  764.     mov    DWORD PTR es:[bx].(NVERTEX)y,eax
  765.     mov    DWORD PTR es:[bx].(NVERTEX)z,esi
  766.  
  767.     pop     di
  768.     pop    si
  769.    }
  770.  return(nv);                   /* pointer to xformed copy */
  771. }
  772.  
  773.  
  774.  
  775.  
  776. /********* Z CLIP AND VERTEX COPY *********/
  777.  
  778. static NVERTEX *nvert[20];     /* table of new poly vertices created */
  779. static int nvcount;            /* table pointer/count (Z clip pass) */
  780. static int nvcptr;        /* pointer for XY clip pass */
  781.  
  782. static unsigned char xy_outcode_and;     /* XY outcode accums used for reject etc */
  783. static unsigned char xy_outcode_or;
  784.  
  785.  
  786.  
  787.  
  788.              /* int. of edge v1->v2 with hither */
  789.  
  790. static NVERTEX *clip_z_int(VERTEX *v1, VERTEX *v2)
  791. {
  792.  NVERTEX *nv1, *nv2, *nv3;
  793.  long  x1,y1,z1,x2,y2,z2;
  794.             /* copy/xform points if not yet done */
  795.             /* nothing done if already processed */
  796.  
  797.  asm {                               /* quick test if conv. needed */
  798.     les    bx,DWORD PTR v1
  799.     mov    eax,DWORD PTR es:[bx].(VERTEX)new_copy
  800.     mov    DWORD PTR nv1,eax
  801.     or    eax,eax
  802.     jnz    need_new_1
  803.      }
  804.  nv1 = xy_transform(v1);
  805. need_new_1:
  806.  asm {                               /* quick test if conv. needed */
  807.     les    bx,DWORD PTR v2
  808.     mov    eax,DWORD PTR es:[bx].(VERTEX)new_copy
  809.     mov    DWORD PTR nv2,eax
  810.     or    eax,eax
  811.     jnz    need_new_2
  812.      }
  813.  nv2 = xy_transform(v2);
  814. need_new_2:
  815.  
  816.  nv3 = newvertex();
  817.  
  818.  asm {
  819.     les    bx,DWORD PTR nv1
  820.     mov    eax,DWORD PTR es:[bx].(NVERTEX)x
  821.     mov    DWORD PTR x1,eax
  822.     mov    eax,DWORD PTR es:[bx].(NVERTEX)y
  823.     mov    DWORD PTR y1,eax
  824.     mov    eax,DWORD PTR es:[bx].(NVERTEX)z
  825.     mov    DWORD PTR z1,eax
  826.  
  827.     les    bx,DWORD PTR nv2
  828.     mov    eax,DWORD PTR es:[bx].(NVERTEX)x
  829.     mov    DWORD PTR x2,eax
  830.     mov    eax,DWORD PTR es:[bx].(NVERTEX)y
  831.     mov    DWORD PTR y2,eax
  832.     mov    eax,DWORD PTR es:[bx].(NVERTEX)z
  833.     mov    DWORD PTR z2,eax
  834.  
  835.     cmp    eax,z1
  836.     jg    other_way
  837.  
  838.     mov    ecx,z1       /* compute denominator */
  839.     sub    ecx,z2
  840.     je    zcltza
  841.  
  842.     mov    eax,DWORD PTR hither4   /* compute new x */
  843.     sub    eax,z2
  844.     mov    edx,x1
  845.     sub    edx,x2
  846.     imul    edx
  847.     idiv    ecx
  848.     add    eax,x2
  849.     mov    x1,eax
  850.  
  851.     mov    eax,DWORD PTR hither4   /* compute new y */
  852.     sub    eax,z2
  853.     mov    edx,y1
  854.     sub    edx,y2
  855.     imul    edx
  856.     idiv    ecx
  857.     add    eax,y2
  858.     mov     y1,eax
  859.      }
  860. zcltza: goto zcltz;
  861.  
  862. other_way:
  863.  asm {
  864.     mov    ecx,z2       /* compute denominator */
  865.     sub    ecx,z1
  866.     je    zcltz
  867.  
  868.     mov    eax,DWORD PTR hither4   /* compute new x */
  869.     sub    eax,z1
  870.     mov    edx,x2
  871.     sub    edx,x1
  872.     imul    edx
  873.     idiv    ecx
  874.     add    eax,x1
  875.     mov    x1,eax
  876.  
  877.     mov    eax,DWORD PTR hither4   /* compute new y */
  878.     sub    eax,z1
  879.     mov    edx,y2
  880.     sub    edx,y1
  881.     imul    edx
  882.     idiv    ecx
  883.     add    eax,y1
  884.     mov     y1,eax
  885.      }
  886.  
  887. zcltz:           /* no clipping: just transfer if zero denom. */
  888.  
  889.  asm {
  890.     les    bx,DWORD PTR nv3
  891.     mov    eax,x1
  892.     mov    DWORD PTR es:[bx].(NVERTEX)x,eax
  893.     mov    eax,y1
  894.     mov    DWORD PTR es:[bx].(NVERTEX)y,eax
  895.     mov    eax,DWORD PTR hither4
  896.     mov    DWORD PTR es:[bx].(NVERTEX)z,eax
  897.      }
  898.  
  899.  return(nv3);
  900. }
  901.  
  902.  
  903.                       /* final processing for vertex passed */
  904. static NVERTEX *z_output(NVERTEX *nv) /* by clipper.  Figure perspective    */
  905. {                                     /* screen positions and poly outcodes */
  906.  
  907.  asm {
  908.     les    bx,DWORD PTR nv
  909.     test    BYTE PTR es:[bx].(NVERTEX)perspect,0FFh
  910.     je    do_perspective
  911.      }
  912.  goto skip_perspective;
  913.  
  914. do_perspective:
  915.  
  916.    asm {                        /* es:[bx] = nv */
  917.     mov    esi,DWORD PTR es:[bx].(NVERTEX)z
  918.     mov    cl,BYTE PTR xshift          /* prescale x, y for accuracy  */
  919.     mov    eax,DWORD PTR es:[bx].(NVERTEX)x
  920.     cdq
  921.     shld    edx,eax,cl
  922.     shl    eax,cl
  923.     idiv    esi                         /* divide by z */
  924.     add    eax,DWORD PTR hsc           /* add prescaled screen center */
  925.     and    eax,0FFFFFFFCh            /* lock to integer */
  926.     mov    DWORD PTR es:[bx].(NVERTEX)xs,eax     /* and store */
  927.  
  928.     xor    ch,ch
  929.     cmp    eax,DWORD PTR right4
  930.     jle    nsro                   /* check outcodes */
  931.     or    ch,RIGHT
  932.        }
  933. nsro:
  934.    asm {
  935.     cmp    eax,DWORD PTR left4
  936.     jge     nslo
  937.     or    ch,LEFT
  938.        }
  939. nslo:
  940.    asm {
  941.     mov    cl,BYTE PTR yshift;           /* same deal for y */
  942.     mov    eax,DWORD PTR es:[bx].(NVERTEX)y
  943.     cdq
  944.     shld    edx,eax,cl
  945.     shl    eax,cl
  946.     idiv    esi
  947.     neg    eax                           /* except upside down */
  948.     add    eax,DWORD PTR vsc
  949.     and    eax,0FFFFFFFCh            /* lock to integer */
  950.     mov    DWORD PTR es:[bx].(NVERTEX)ys,eax
  951.  
  952.     cmp    eax,DWORD PTR bottom4
  953.     jle    nsbo
  954.     or    ch,BOTTOM
  955.        }
  956. nsbo:
  957.    asm {                                      /* check outcodes */
  958.     cmp    eax,DWORD PTR top4
  959.     jge     nsto
  960.     or    ch,TOP
  961.        }
  962. nsto:
  963.    asm {
  964.     mov    BYTE PTR es:[bx].(NVERTEX)outcode,ch
  965.     mov    BYTE PTR es:[bx].(NVERTEX)perspect,1
  966.        }
  967.  
  968. skip_perspective:
  969.  
  970.  asm {
  971.     mov    al, es:[bx].(NVERTEX)outcode  /* update accum. outcodes */
  972.     or    BYTE PTR xy_outcode_or,al
  973.     and    BYTE PTR xy_outcode_and,al
  974.      }
  975.  
  976.  nvert[nvcount] = nv;
  977.  if(nvcount > 20) OK = 0;
  978.  nvcount++;
  979.  return(nv);
  980. }
  981.  
  982.  
  983.  
  984.  
  985. /*************** XY POLYGON CLIPPER **************/
  986.  
  987.      /* clipper record variables: */
  988.                    /* top clipper: */
  989. static int first_top;              /* 1 if first vertex in pass  */
  990. static NVERTEX *first_top_vtx;     /* first vertex */
  991. static NVERTEX *last_top_vtx;      /* prev. vertex */
  992.  
  993.   /* bottom clipper */
  994. static NVERTEX *first_bottom_vtx;
  995. static NVERTEX *last_bottom_vtx;
  996.  
  997.  
  998. static NVERTEX *first_left_vtx;    /* left clipper */
  999. static NVERTEX *last_left_vtx;
  1000.  
  1001.  
  1002. static NVERTEX *first_right_vtx;   /* right clipper */
  1003. static NVERTEX *last_right_vtx;
  1004.  
  1005. static NVERTEX **vpoly;           /* where to put output */
  1006.  
  1007.  
  1008.  
  1009. static NVERTEX *y_intercept(NVERTEX *v1, NVERTEX *v2, long edge)
  1010. {
  1011.  NVERTEX *nv = newvertex();      /* create new vertex */
  1012.  
  1013.  long  x1 = v1->xs;               /* get values (BC can't do it inline) */
  1014.  long  y1 = v1->ys;
  1015.  long  z1 = v1->z;
  1016.  
  1017.  long  x2 = v2->xs;
  1018.  long  y2 = v2->ys;
  1019.  long  z2 = v2->z;
  1020.  
  1021.  if(y1<y2) goto fwd_clip;    /* always clip in same dir. to fix roundoff */
  1022.  
  1023.  asm {
  1024.     mov    ecx,y1       /* compute denominator */
  1025.     sub    ecx,y2
  1026.     je    zcltlz
  1027.  
  1028.     mov    eax,edge     /* compute new z */
  1029.     sub    eax,y2
  1030.     mov    edx,z1
  1031.     sub    edx,z2
  1032.     imul    edx
  1033.     idiv    ecx
  1034.     add    eax,z2
  1035.     mov    z1,eax
  1036.  
  1037.     mov    eax,edge     /* compute new x */
  1038.     sub    eax,y2
  1039.     mov    edx,x1
  1040.     sub    edx,x2
  1041.     imul    edx
  1042.     idiv    ecx
  1043.     add    eax,x2
  1044.     mov     x1,eax
  1045.  
  1046.      }
  1047. zcltlz:
  1048.  goto zcltz;
  1049.  
  1050. fwd_clip:
  1051.  asm {
  1052.     mov    ecx,y2       /* compute denominator */
  1053.     sub    ecx,y1
  1054.     je    zcltz
  1055.  
  1056.     mov    eax,edge     /* compute new z */
  1057.     sub    eax,y1
  1058.     mov    edx,z2
  1059.     sub    edx,z1
  1060.     imul    edx
  1061.     idiv    ecx
  1062.     add    eax,z1
  1063.     mov    z1,eax
  1064.  
  1065.     mov    eax,edge     /* compute new x */
  1066.     sub    eax,y1
  1067.     mov    edx,x2
  1068.     sub    edx,x1
  1069.     imul    edx
  1070.     idiv    ecx
  1071.     add    eax,x1
  1072.     mov     x1,eax
  1073.      }
  1074. zcltz:       /* no clipping: just transfer if zero denom. */
  1075.  
  1076.  nv->xs = x1;
  1077.  nv->ys = edge;
  1078.  nv->z = z1;
  1079.  return(nv);
  1080. }
  1081.  
  1082.  
  1083. static NVERTEX *x_intercept(NVERTEX *v1, NVERTEX *v2, long edge)
  1084. {
  1085.  NVERTEX *nv = newvertex();      /* create new vertex */
  1086.  
  1087.  long  x1 = v1->xs;               /* get values (BC can't do it inline) */
  1088.  long  y1 = v1->ys;
  1089.  long  z1 = v1->z;
  1090.  
  1091.  long  x2 = v2->xs;
  1092.  long  y2 = v2->ys;
  1093.  long  z2 = v2->z;
  1094.  
  1095.  if(x1<x2) goto fwd_clip;
  1096.  
  1097.  asm {
  1098.     mov    ecx,x1       /* compute denominator */
  1099.     sub    ecx,x2
  1100.     je    zcltlz
  1101.  
  1102.     mov    eax,edge     /* compute new z */
  1103.     sub    eax,x2
  1104.     mov    edx,z1
  1105.     sub    edx,z2
  1106.     imul    edx
  1107.     idiv    ecx
  1108.     add    eax,z2
  1109.     mov    z1,eax
  1110.  
  1111.     mov    eax,edge     /* compute new y */
  1112.     sub    eax,x2
  1113.     mov    edx,y1
  1114.     sub    edx,y2
  1115.     imul    edx
  1116.     idiv    ecx
  1117.     add    eax,y2
  1118.     mov     y1,eax
  1119.      }
  1120. zcltlz:
  1121.  goto zcltz;
  1122.  
  1123. fwd_clip:
  1124.  asm {
  1125.     mov    ecx,x2       /* compute denominator */
  1126.     sub    ecx,x1
  1127.     je    zcltz
  1128.  
  1129.     mov    eax,edge     /* compute new z */
  1130.     sub    eax,x1
  1131.     mov    edx,z2
  1132.     sub    edx,z1
  1133.     imul    edx
  1134.     idiv    ecx
  1135.     add    eax,z1
  1136.     mov    z1,eax
  1137.  
  1138.     mov    eax,edge     /* compute new y */
  1139.     sub    eax,x1
  1140.     mov    edx,y2
  1141.     sub    edx,y1
  1142.     imul    edx
  1143.     idiv    ecx
  1144.     add    eax,y1
  1145.     mov     y1,eax
  1146.      }
  1147. zcltz:       /* no clipping: just transfer if zero denom. */
  1148.  
  1149.  nv->xs = edge;
  1150.  nv->ys = y1;
  1151.  nv->z = z1;
  1152.  return(nv);
  1153. }
  1154.  
  1155.  
  1156.  
  1157.  
  1158. static void XY_clip(NVERTEX *v, int stage)   /* XY semirecursive clipper       */
  1159. {                      /* set last = NULL before first call */
  1160.                       /* call with all (copied) vertices  */
  1161.  NVERTEX *nv;                  /* call with NULL to flush       */
  1162.                       /* also copies output to poly table */
  1163.  
  1164.  switch(stage)
  1165.   {
  1166.    case BOTTOM: goto bottom_clip;
  1167.    case LEFT:   goto left_clip;
  1168.    case RIGHT:  goto right_clip;
  1169.   }
  1170.  
  1171. top_clip:
  1172.  asm {
  1173.     mov    eax,DWORD PTR last_top_vtx
  1174.     or    eax,eax
  1175.     jnz    not_first_top
  1176.     mov     eax,DWORD PTR v
  1177.     mov    DWORD PTR last_top_vtx,eax
  1178.     mov    DWORD PTR first_top_vtx,eax
  1179.     les    bx,DWORD PTR v
  1180.     mov    al,BYTE PTR es:[bx].(NVERTEX)outcode
  1181.     test    al,TOP
  1182.     jnz    stt
  1183.     jmp    right_clip
  1184.      }
  1185. stt:
  1186.  return;
  1187.  
  1188. not_first_top:
  1189.  asm {
  1190.     mov    eax,DWORD PTR v
  1191.     or    eax,eax
  1192.     jnz    not_flush_top
  1193.     les    bx,DWORD PTR first_top_vtx
  1194.     mov    al,BYTE PTR es:[bx].(NVERTEX)outcode
  1195.     les    bx,DWORD PTR last_top_vtx
  1196.     xor    al,BYTE PTR es:[bx].(NVERTEX)outcode
  1197.     test    al,TOP
  1198.     jnz    stt2
  1199.     jmp    right_clip
  1200.      }
  1201. stt2:
  1202.    nv = y_intercept(first_top_vtx, last_top_vtx, top4);
  1203.    XY_clip(nv,RIGHT);            /* process this new point */
  1204.    goto right_clip;                /* and continue flush */
  1205.  
  1206. not_flush_top:
  1207.  asm {
  1208.     les    bx,DWORD PTR v
  1209.     mov    al,BYTE PTR es:[bx].(NVERTEX)outcode
  1210.     push    ax
  1211.     les    bx,DWORD PTR last_top_vtx
  1212.     xor    al,BYTE PTR es:[bx].(NVERTEX)outcode
  1213.     test    al,TOP
  1214.     jz    do_top_clip
  1215.      }
  1216.    nv = y_intercept(v, last_top_vtx, top4);
  1217.    XY_clip(nv,RIGHT);            /* process this new point */
  1218.  
  1219. do_top_clip:
  1220.  asm {
  1221.     mov    eax,DWORD PTR v
  1222.     mov    DWORD PTR last_top_vtx,eax
  1223.     pop    ax
  1224.     test    al,TOP
  1225.     jz    right_clip
  1226.      }
  1227.  return;
  1228.  
  1229.  
  1230. right_clip:
  1231.  asm {
  1232.     mov    eax,DWORD PTR last_right_vtx
  1233.     or    eax,eax
  1234.     jnz    not_first_right
  1235.     mov     eax,DWORD PTR v
  1236.     mov    DWORD PTR last_right_vtx,eax
  1237.     mov    DWORD PTR first_right_vtx,eax
  1238.     les    bx,DWORD PTR v
  1239.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1240.     cmp    eax,DWORD PTR right4
  1241.     jg    str
  1242.     jmp    bottom_clip
  1243.      }
  1244. str:
  1245.  return;
  1246.  
  1247. not_first_right:
  1248.  asm {
  1249.     mov    eax,DWORD PTR v
  1250.     or    eax,eax
  1251.     jnz    not_flush_right
  1252.     les    bx,DWORD PTR first_right_vtx
  1253.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1254.     cmp    eax,DWORD PTR right4
  1255.     jle    pas1b
  1256.  
  1257.     les    bx,DWORD PTR last_right_vtx
  1258.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1259.     cmp    eax,DWORD PTR right4
  1260.     jle    pas2b
  1261.     jmp    bottom_clip
  1262.      }
  1263. pas1b:
  1264.  asm {
  1265.     les    bx,DWORD PTR last_right_vtx
  1266.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1267.     cmp    eax,DWORD PTR right4
  1268.     jg    pas2b
  1269.     jmp    bottom_clip
  1270.      }
  1271. pas2b:
  1272.    nv = x_intercept(first_right_vtx, last_right_vtx, right4);
  1273.    XY_clip(nv,BOTTOM);            /* process this new point */
  1274.    goto bottom_clip;                /* and continue flush */
  1275.  
  1276. not_flush_right:
  1277.  asm {
  1278.     les    bx,DWORD PTR v
  1279.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1280.     cmp    eax,DWORD PTR right4
  1281.     jle    pat1b
  1282.  
  1283.     les    bx,DWORD PTR last_right_vtx
  1284.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1285.     cmp    eax,DWORD PTR right4
  1286.     jg    no_right_clip
  1287.      }
  1288.    nv = x_intercept(v, last_right_vtx, right4);
  1289.    XY_clip(nv,BOTTOM);            /* process this new point */
  1290. no_right_clip:
  1291.  asm {
  1292.     mov    eax,DWORD PTR v
  1293.     mov    DWORD PTR last_right_vtx,eax
  1294.      }
  1295.  return;
  1296.  
  1297. pat1b:
  1298.  asm {
  1299.     les    bx,DWORD PTR last_right_vtx
  1300.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1301.     cmp    eax,DWORD PTR right4
  1302.     jle    do_right_clip
  1303.      }
  1304.    nv = x_intercept(v, last_right_vtx, right4);
  1305.    XY_clip(nv,BOTTOM);            /* process this new point */
  1306.  
  1307. do_right_clip:
  1308.  asm {
  1309.     mov    eax,DWORD PTR v
  1310.     mov    DWORD PTR last_right_vtx,eax
  1311.      }
  1312.  goto bottom_clip;
  1313.  
  1314.  
  1315.  
  1316. bottom_clip:
  1317.  asm {
  1318.     mov    eax,DWORD PTR last_bottom_vtx
  1319.     or    eax,eax
  1320.     jnz    not_first_bottom
  1321.     mov     eax,DWORD PTR v
  1322.     mov    DWORD PTR last_bottom_vtx,eax
  1323.     mov    DWORD PTR first_bottom_vtx,eax
  1324.     les    bx,DWORD PTR v
  1325.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1326.     cmp    eax,DWORD PTR bottom4
  1327.     jg    stb
  1328.     jmp    left_clip
  1329.      }
  1330. stb:
  1331.  return;
  1332.  
  1333. not_first_bottom:
  1334.  asm {
  1335.     mov    eax,DWORD PTR v
  1336.     or    eax,eax
  1337.     jnz    not_flush_bottom
  1338.     les    bx,DWORD PTR first_bottom_vtx
  1339.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1340.     cmp    eax,DWORD PTR bottom4
  1341.     jle    pas1bb
  1342.  
  1343.     les    bx,DWORD PTR last_bottom_vtx
  1344.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1345.     cmp    eax,DWORD PTR bottom4
  1346.     jle    pas2bb
  1347.     jmp     left_clip
  1348.      }
  1349. pas1bb:
  1350.  asm {
  1351.     les    bx,DWORD PTR last_bottom_vtx
  1352.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1353.     cmp    eax,DWORD PTR bottom4
  1354.     jg    pas2bb
  1355.     jmp    left_clip
  1356.      }
  1357. pas2bb:
  1358.    nv = y_intercept(first_bottom_vtx, last_bottom_vtx, bottom4);
  1359.    XY_clip(nv,LEFT);            /* process this new point */
  1360.    goto left_clip;                 /* and continue flush */
  1361.  
  1362. not_flush_bottom:
  1363.  asm {
  1364.     les    bx,DWORD PTR v
  1365.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1366.     cmp    eax,DWORD PTR bottom4
  1367.     jle    pat1t
  1368.  
  1369.     les    bx,DWORD PTR last_bottom_vtx
  1370.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1371.     cmp    eax,DWORD PTR bottom4
  1372.     jg    no_bottom_clip
  1373.      }
  1374.    nv = y_intercept(v, last_bottom_vtx, bottom4);
  1375.    XY_clip(nv,LEFT);            /* process this new point */
  1376. no_bottom_clip:
  1377.  asm {
  1378.     mov    eax,DWORD PTR v
  1379.     mov    DWORD PTR last_bottom_vtx,eax
  1380.      }
  1381.  return;
  1382.  
  1383. pat1t:
  1384.  asm {
  1385.     les    bx,DWORD PTR last_bottom_vtx
  1386.     mov    eax,DWORD PTR es:[bx].(NVERTEX)ys
  1387.     cmp    eax,DWORD PTR bottom4
  1388.     jle    do_bottom_clip
  1389.      }
  1390.    nv = y_intercept(v, last_bottom_vtx, bottom4);
  1391.    XY_clip(nv,LEFT);            /* process this new point */
  1392.  
  1393. do_bottom_clip:
  1394.  asm {
  1395.     mov    eax,DWORD PTR v
  1396.     mov    DWORD PTR last_bottom_vtx,eax
  1397.      }
  1398.  goto left_clip;
  1399.  
  1400.  
  1401.  
  1402. left_clip:
  1403.  asm {
  1404.     mov    eax,DWORD PTR last_left_vtx
  1405.     or    eax,eax
  1406.     jnz    not_first_left
  1407.     mov     eax,DWORD PTR v
  1408.     mov    DWORD PTR last_left_vtx,eax
  1409.     mov    DWORD PTR first_left_vtx,eax
  1410.     les    bx,DWORD PTR v
  1411.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1412.     cmp    eax,DWORD PTR left4
  1413.     jl    stl
  1414.     jmp    end_clip
  1415.      }
  1416. stl:
  1417.  return;
  1418.  
  1419. not_first_left:
  1420.  asm {
  1421.     mov    eax,DWORD PTR v
  1422.     or    eax,eax
  1423.     jnz    not_flush_left
  1424.     les    bx,DWORD PTR first_left_vtx
  1425.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1426.     cmp    eax,DWORD PTR left4
  1427.     jge    pas1x
  1428.  
  1429.     les    bx,DWORD PTR last_left_vtx
  1430.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1431.     cmp    eax,DWORD PTR left4
  1432.     jge     pas2x
  1433.     jmp    thru_flush
  1434.      }
  1435. pas1x:
  1436.  asm {
  1437.     les    bx,DWORD PTR last_left_vtx
  1438.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1439.     cmp    eax,DWORD PTR left4
  1440.     jge    thru_flush
  1441.      }
  1442. pas2x:
  1443.    nv = x_intercept(first_left_vtx, last_left_vtx, left4);
  1444.    *vpoly++ = nv;        /* store the vertex */
  1445.    nvcptr++;
  1446. thru_flush:
  1447.    return;
  1448.  
  1449. not_flush_left:
  1450.  asm {
  1451.     les    bx,DWORD PTR v
  1452.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1453.     cmp    eax,DWORD PTR left4
  1454.     jge    pat1x
  1455.  
  1456.     les    bx,DWORD PTR last_left_vtx
  1457.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1458.     cmp    eax,DWORD PTR left4
  1459.     jl    no_left_clip
  1460.      }
  1461.    nv = x_intercept(v, last_left_vtx, left4);
  1462.    *vpoly++ = nv;        /* store the vertex */
  1463.    nvcptr++;
  1464. no_left_clip:
  1465.  asm {
  1466.     mov    eax,DWORD PTR v
  1467.     mov    DWORD PTR last_left_vtx,eax
  1468.      }
  1469.  return;
  1470.  
  1471. pat1x:
  1472.  asm {
  1473.     les    bx,DWORD PTR last_left_vtx
  1474.     mov    eax,DWORD PTR es:[bx].(NVERTEX)xs
  1475.     cmp    eax,DWORD PTR left4
  1476.     jge    do_left_clip
  1477.      }
  1478.    nv = x_intercept(v, last_left_vtx, left4);
  1479.    *vpoly++ = nv;        /* store the vertex */
  1480.    nvcptr++;
  1481.  
  1482. do_left_clip:
  1483.  asm {
  1484.     mov    eax,DWORD PTR v
  1485.     mov    DWORD PTR last_left_vtx,eax
  1486.      }
  1487.  
  1488. end_clip:
  1489.  asm {
  1490.     mov    eax,DWORD PTR v
  1491.     mov    DWORD PTR last_left_vtx,eax
  1492.      }
  1493.  *vpoly++ = v;        /* store the vertex */
  1494.  nvcptr++;              /* ideal point to remove extra bits from XYZ */
  1495. }
  1496.  
  1497.  
  1498.  
  1499.  
  1500. /*************** POLYGON CLIP AND PROCESS *************/
  1501.  
  1502.  
  1503.  
  1504. extern int sqrtable[1024];
  1505.  
  1506.  
  1507. int poly_cosine(POLY *pp)   /* returns 128 * cos poly-light angle */
  1508. {
  1509.  
  1510.  VERTEX *v0 = pp->points[0];
  1511.  
  1512.  long nx = pp->normalx;
  1513.  long ny = pp->normaly;
  1514.  long nz = pp->normalz;
  1515.  
  1516.  long dlx = v0->x;
  1517.  long dly = v0->y;
  1518.  long dlz = v0->z;
  1519.  
  1520.  int light;
  1521.         /* directional light instead of point source */
  1522.  
  1523.  if(directional_light)  dlx = dly = dlz = 0;
  1524.  
  1525.     /* compute vector from light source to surface  */
  1526.     /* find dot product, normalize by vector length */
  1527.     /* returns -128<light<128 (signed 8-bit)        */
  1528.  
  1529.  asm {
  1530.     push si
  1531.     push di
  1532.     mov    eax,DWORD PTR ilight_x
  1533.     sub    eax,dlx
  1534.     mov     ecx,eax             /* delta X */
  1535.     jge    xnn
  1536.     neg    ecx
  1537.      }
  1538. xnn:
  1539.  asm {
  1540.     mov    dlx,ecx             /* abs value for scaling */
  1541.     mov    ebx,ecx
  1542.     imul    DWORD PTR nx
  1543.     mov    edi,edx
  1544.     mov    esi,eax
  1545.  
  1546.     mov    eax,DWORD PTR ilight_y
  1547.     sub    eax,dly
  1548.     mov     ecx,eax
  1549.     jge    ynn
  1550.     neg    ecx
  1551.      }
  1552. ynn:
  1553.  asm {
  1554.     mov    dly,ecx
  1555.     or    ebx,ecx            /* OR abs deltas for scaling test */
  1556.     imul    DWORD PTR ny
  1557.     add    esi,eax
  1558.     adc    edi,edx
  1559.  
  1560.     mov    eax,DWORD PTR ilight_z
  1561.     sub    eax,dlz
  1562.     mov     ecx,eax
  1563.     jge    znn
  1564.     neg    ecx
  1565.      }
  1566. znn:
  1567.  asm {
  1568.     mov    dlz,ecx           /* same for y, z */
  1569.     or    ebx,ecx
  1570.     jnz    golight          /* max light at zero distance */
  1571.     mov    ax,127
  1572.     mov    light,ax
  1573.      }
  1574.  goto fincos;
  1575.  
  1576. golight:
  1577.  asm {
  1578.     imul    DWORD PTR nz
  1579.     add    esi,eax
  1580.     adc    edi,edx           /* edi:esi now 64-bit dot product */
  1581.  
  1582.     shrd    esi,edi,16
  1583.     sar    edi,16
  1584.  
  1585.     xor    cx,cx
  1586.     test    ebx,0ff000000h           /* prescale by 16 bits */
  1587.     je    not32sig
  1588.     add    cx,16
  1589.     jmp    shft16sig
  1590.      }
  1591. not32sig:
  1592.  asm {
  1593.     test    ebx,0ffff0000h
  1594.     je    nonesig                  /* prescale by 8 bits */
  1595.     add    cx,8
  1596.      }
  1597. shft16sig:
  1598.  asm {
  1599.     shr    ebx,cl                   /* conv. test to word (save 2 us) */
  1600.      }
  1601. nonesig:
  1602.  asm {
  1603.     bsr    ax,bx
  1604.     add    cx,ax
  1605.     sub    cx,7                     /* how many bits to normalize? */
  1606.     je    noshiftn
  1607.     jl    bumpup
  1608.  
  1609.     shr    DWORD PTR dlx,cl         /* divide */
  1610.     shr    DWORD PTR dly,cl
  1611.     shr    DWORD PTR dlz,cl
  1612.     shrd    esi,edi,cl
  1613.     sar    edi,cl
  1614.     jmp    noshiftn
  1615.      }
  1616. bumpup:
  1617.  asm {
  1618.     neg    cl
  1619.     shl    DWORD PTR dlx,cl         /* multiply */
  1620.     shl    DWORD PTR dly,cl
  1621.     shl    DWORD PTR dlz,cl
  1622.     shld    edi,esi,cl
  1623.     shl    esi,cl
  1624.      }
  1625. noshiftn:
  1626.  asm {
  1627.     mov    al,BYTE PTR dlx          /* now 8-bit diff's: find mag */
  1628.     mul    al
  1629.     mov    bx,ax                    /* square */
  1630.     xor    dx,dx
  1631.  
  1632.     mov    al,BYTE PTR dly
  1633.     mul    al
  1634.     add    bx,ax
  1635.     adc    dx,0
  1636.  
  1637.     mov    al,BYTE PTR dlz
  1638.     mul    al
  1639.     add    bx,ax
  1640.     adc    dx,0
  1641.  
  1642.     shrd    bx,dx,7                  /* lookup in table */
  1643.     and     ebx,0FFFEh
  1644.     mov    ax,sqrtable[bx]
  1645.     cwde
  1646.     mov    ebx,eax
  1647.     mov    edx,edi
  1648.     mov    eax,esi
  1649.     idiv    ebx
  1650.     mov    light,ax
  1651.      }
  1652. fincos:
  1653. asm {
  1654.     pop di
  1655.     pop si
  1656.     }
  1657.  return light;
  1658. }
  1659.  
  1660.  
  1661.  
  1662.  
  1663. /* DO POLY PROCESSING - LOTS OF STUFF INLINE DUE TO HIGH USAGE */
  1664.  
  1665. static int depth_type;        /* selects depth sort style */
  1666.  
  1667.  
  1668. static void proc_poly(POLY *p)  /* accept/reject tests on polys */
  1669. {                               /* transforms vertices, clips   */
  1670.  int i,j,k;                     /* and computes screen coords   */
  1671.  char z_outcode_or  = 0;        /* Also copies polys and points */
  1672.  char z_outcode_and = 3;        /* for minimum disruption of    */
  1673.  VERTEX **vp;
  1674.  VERTEX *v;                     /* the world database           */
  1675.  NVERTEX *nv;
  1676.  NPOLY *np;
  1677.  long ny,nz;
  1678.  VERTEX **pv;
  1679.  
  1680.  char last_z_out;        /* previous vertex Z outcode  */
  1681.  VERTEX *last_z_vtx;     /* orig. (world) prev. vertex */
  1682.                 /* skip backfacing polygons */
  1683. /* return if (p->normalx * (current_view->ex - p->points[0]->x) +
  1684.      p->normaly * (current_view->ey - p->points[0]->y) +
  1685.      p->normalz * (current_view->ez - p->points[0]->z)) >= 0.0; */
  1686.  
  1687.  
  1688. r_polys_tested++;
  1689.  
  1690.  if(p->npoints<3) goto proceed;    /* don't test if it's a line! */
  1691.  
  1692.  asm {
  1693.     push    esi
  1694.     push    edi
  1695.     les    bx,DWORD PTR p
  1696.     mov     edx,DWORD PTR es:[bx].(POLY)normalx
  1697.     mov    eax,DWORD PTR es:[bx].(POLY)normaly
  1698.     mov    DWORD PTR ny,eax
  1699.     mov    eax,DWORD PTR es:[bx].(POLY)normalz
  1700.     mov    DWORD PTR nz,eax
  1701.     les    bx,DWORD PTR es:[bx].(POLY)points
  1702.     les    bx,es:[bx]
  1703.  
  1704.     mov    eax,DWORD PTR es:[bx].(VERTEX)x
  1705.     sub    eax,DWORD PTR iview_x
  1706.     imul    edx
  1707.     mov    esi,eax
  1708.     mov    edi,edx
  1709.  
  1710.     mov    eax,DWORD PTR es:[bx].(VERTEX)y
  1711.     sub    eax,DWORD PTR iview_y
  1712.     imul    DWORD PTR ny
  1713.     add    esi,eax
  1714.     adc    edi,edx
  1715.  
  1716.     mov    eax,DWORD PTR es:[bx].(VERTEX)z
  1717.     sub    eax,DWORD PTR iview_z
  1718.     imul    DWORD PTR nz
  1719.     add    esi,eax
  1720.     adc    edi,edx
  1721.     pop    edi
  1722.     pop    esi
  1723.     jl      proceed
  1724.      }
  1725.  return;
  1726.  
  1727. proceed:
  1728.  
  1729.  
  1730. r_polys_passed++;
  1731.  
  1732.         /* scan through the poly's points, transforming Z
  1733.             and doing outcode clipping to hither and yon   */
  1734.  
  1735.  asm {
  1736.     push    si            /* setup loop with # points, point table ptr */
  1737.     push    di
  1738.     les    bx,DWORD PTR p
  1739.     mov    ax,WORD PTR es:[bx].(POLY)npoints
  1740.     mov    WORD PTR j,ax
  1741.     mov    eax,DWORD PTR es:[bx].(POLY)points
  1742.     mov    pv,eax
  1743.      }
  1744.  
  1745.  loopz:
  1746.  asm {  les    si,DWORD PTR pv
  1747.     les    si,es:[si]
  1748.     test    BYTE PTR es:[si].(VERTEX)z_transformed,0ffh
  1749.     jnz    already_z
  1750.  
  1751.     /* Z coord transform, generate Z outcode      */
  1752.  
  1753.  
  1754. }
  1755. r_vertices++;
  1756. asm{
  1757.  
  1758.  
  1759.     mov    eax,DWORD PTR fact7
  1760.     mov    edx,DWORD PTR es:[si].(VERTEX)x
  1761.     sub    edx,DWORD PTR iview_x
  1762.     imul    edx
  1763.     mov    ecx,eax
  1764.     mov    edi,edx
  1765.  
  1766.     mov    eax,DWORD PTR fact8
  1767.     mov    edx,DWORD PTR es:[si].(VERTEX)y
  1768.     sub    edx,DWORD PTR iview_y
  1769.     imul    edx
  1770.     add    ecx,eax
  1771.     adc    edi,edx
  1772.  
  1773.     mov    eax,DWORD PTR fact9
  1774.     mov    edx,DWORD PTR es:[si].(VERTEX)z
  1775.     sub    edx,DWORD PTR iview_z
  1776.     imul    edx
  1777.     add    ecx,eax
  1778.     adc    edi,edx
  1779.  
  1780.     shrd    ecx,edi,27        /* 29 - PRESCALEZ */
  1781.     adc    ecx,0
  1782.  
  1783.     mov    DWORD PTR es:[si].(VERTEX)cz,ecx
  1784.     mov    BYTE PTR es:[si].(VERTEX)z_transformed,1
  1785.  
  1786.     xor    ax,ax
  1787.     cmp    ecx,DWORD PTR hither4
  1788.     jge    nonhither
  1789.     or    al,HITHER
  1790.      }
  1791. nonhither:
  1792.  asm {
  1793.     cmp     ecx,DWORD PTR yon4
  1794.     jle    nonyon
  1795.     or    al,YON
  1796.      }
  1797. nonyon:
  1798.  asm {
  1799.     mov     BYTE PTR es:[si].(VERTEX)z_outcode,al
  1800.      }
  1801. already_z:                              /* accumulate outcodes */
  1802.  asm {
  1803.     mov     al,BYTE PTR es:[si].(VERTEX)z_outcode
  1804.     or    BYTE PTR z_outcode_or,al
  1805.     and    BYTE PTR z_outcode_and,al
  1806.  
  1807.     add    WORD PTR pv,4            /* next vertex */
  1808.     dec    WORD PTR j
  1809.     jz      loopze
  1810.     jmp    loopz
  1811.      }
  1812. loopze:
  1813.  asm {
  1814.     pop     di
  1815.     pop    si
  1816.      }
  1817.  
  1818.  if (z_outcode_and == HITHER ||
  1819.      z_outcode_and == YON)  return;       /* all hither/yon? Reject poly */
  1820.  
  1821.             /* otherwise, begin Z clip and XY transforms */
  1822.  xy_outcode_or  = 0;
  1823.  xy_outcode_and = 15;   /* Z-clip pass setup */
  1824.  nvcount = 0;                        /* Pass 2: */
  1825.                      /* Z-clip and XY conv. vertices   */
  1826.                      /* also make copies to temp array */
  1827. {
  1828.  char first_z_out;        /* first vertex Z outcode     */
  1829.  VERTEX *first_z_vtx;     /* orig. (world) first vertex */
  1830.  char last_z_out;         /* previous vertex Z outcode  */
  1831.  VERTEX *last_z_vtx;      /* orig. (world) prev. vertex */
  1832.  char z_ocode;
  1833.  VERTEX *pv;
  1834.  
  1835.  asm {
  1836.     les    bx,p
  1837.     mov    eax,DWORD PTR es:[bx].(POLY)points
  1838.     mov    pv,eax
  1839.     mov    ax,WORD PTR es:[bx].(POLY)npoints
  1840.     mov    WORD PTR j,ax
  1841.  
  1842.     les    bx,DWORD PTR pv
  1843.     mov    eax,es:[bx]
  1844.     les    bx,es:[bx]
  1845.     mov    DWORD PTR first_z_vtx,eax
  1846.     mov    DWORD PTR last_z_vtx,eax
  1847.     mov    al,BYTE PTR es:[bx].(VERTEX)z_outcode
  1848.     and    al,HITHER
  1849.     mov    BYTE PTR first_z_out,al
  1850.     mov    BYTE PTR last_z_out,al
  1851.     jne    no_z_first
  1852.      }
  1853.   z_output(xy_transform(first_z_vtx));  /* output it if OK */
  1854. no_z_first:
  1855. zcloop:
  1856.  asm {
  1857.     dec    WORD PTR j
  1858.     jz    donezcl
  1859.     add    WORD PTR pv,4
  1860.     les    bx,DWORD PTR pv
  1861.     mov    edx,es:[bx]
  1862.     les    bx,es:[bx]
  1863.     mov    DWORD PTR v,edx
  1864.     mov    al,BYTE PTR es:[bx].(VERTEX)z_outcode
  1865.     and    al,HITHER
  1866.     mov    BYTE PTR z_ocode,al
  1867.     cmp    al,BYTE PTR last_z_out
  1868.     jz    no_z_mid
  1869.      }
  1870.   z_output( clip_z_int(last_z_vtx, v) );
  1871. no_z_mid:
  1872.  asm {
  1873.     les    bx,DWORD PTR pv
  1874.     mov    edx,es:[bx]
  1875.     mov    DWORD PTR last_z_vtx,edx
  1876.     mov    al,BYTE PTR z_ocode
  1877.     mov    BYTE PTR last_z_out,al
  1878.     or    al,al
  1879.     push    si
  1880.     jnz    no_z_m_out
  1881.      }
  1882.  z_output( xy_transform(last_z_vtx));
  1883. no_z_m_out:
  1884.  goto zcloop;
  1885.  
  1886. donezcl:
  1887.  
  1888.  if(first_z_out != last_z_out)     /* no flush needed? */
  1889.      z_output( clip_z_int(last_z_vtx, first_z_vtx) );
  1890.  
  1891.  if((nvcount<3 && p->npoints>2) || xy_outcode_and)
  1892.     {
  1893.      return;   /* reject poly if degenerate */
  1894.     }
  1895.                          /* or XY clip will delete it */
  1896. }
  1897.  
  1898. {
  1899.  NVERTEX **nvp = &nvert[0];
  1900.  np = newpoly();
  1901.  np->parent = p;
  1902.  vpoly = (NVERTEX **)npalloc;      /* copy space pointer for vertex ptr storage */
  1903.  np->npoints = nvcount;
  1904.                 /* vertex ptrs after poly */
  1905.  
  1906.  if(depth_type & AVERAGE)
  1907.   {
  1908.    long sumz;
  1909.    asm {
  1910.     push    si
  1911.     les    bx,np
  1912.     mov    cx,WORD PTR nvcount
  1913.     mov    si,WORD PTR nvp                 /* nvert[] in dseg */
  1914.     xor    eax,eax
  1915.        }
  1916. zfcaloop:
  1917.    asm {
  1918.     les    bx,ds:[si]
  1919.     add    eax,DWORD PTR es:[bx].(NVERTEX)z
  1920.     add    si,4
  1921.     loop    zfcaloop
  1922.  
  1923.     xor    edx,edx
  1924.     xor    esi,esi
  1925.     mov    si,WORD PTR nvcount
  1926.     idiv    esi
  1927.     mov    DWORD PTR nz,eax
  1928.     pop    si
  1929.        }
  1930.    }
  1931.   else         /* default: use deepest Z in polygon */
  1932.    {
  1933.      /* for (i = 0; i < nvcount; ++i)
  1934.             {
  1935.              if (np->points[i]->z > np->maxz) np->maxz = np->points[i]->z;
  1936.             }    */
  1937.    asm {
  1938.     push    si
  1939.     mov    cx,WORD PTR nvcount
  1940.     mov    si,WORD PTR nvp
  1941.     mov    eax,080000001h
  1942.        }
  1943.  zfcloop:
  1944.    asm {
  1945.     les    bx,ds:[si]
  1946.     cmp    eax,DWORD PTR es:[bx].(NVERTEX)z
  1947.     jge    notlow
  1948.     mov    eax,DWORD PTR es:[bx].(NVERTEX)z
  1949.        }
  1950.  notlow:
  1951.    asm {
  1952.     add    si,4
  1953.     loop    zfcloop
  1954.     pop    si
  1955.     mov    nz,eax
  1956.        }
  1957.    }
  1958.  
  1959.  if(depth_type & ATBACK)
  1960.    {
  1961.     nz |= 0x40000000;
  1962.    }
  1963.  
  1964.  
  1965.  np->maxz = nz;
  1966.  
  1967.  if((xy_outcode_or) == 0)    /* does poly need XY clipping? */
  1968.   {
  1969.  /*  for(i=0;i<nvcount;i++) *vpoly++ = *nvp++ ;  /* no: copy it */
  1970.   asm {
  1971.     push    si
  1972.     push    di
  1973.     push    ds
  1974.     les    di,DWORD PTR vpoly      /* ya, so it saves 2 mS/frame! */
  1975.     mov    cx,WORD PTR nvcount
  1976.     lds    si,DWORD PTR nvp
  1977.     rep    movsd
  1978.     pop    ds
  1979.     mov    WORD PTR vpoly,di
  1980.     mov    WORD PTR nvp,si
  1981.     pop    di
  1982.     pop    si
  1983.       }
  1984.   }
  1985.  else                           /* yes: XY clip it */
  1986.   {
  1987.    /* (do XY clip) */
  1988.  
  1989. r_polys_xyclipped++;
  1990.  
  1991.    last_top_vtx = last_bottom_vtx = NULL;  /* initialize clipper */
  1992.    last_left_vtx = last_right_vtx = NULL;
  1993.    nvcptr = 0;
  1994.                 /* clip all vertices */
  1995.    for(i=0;i<nvcount;i++)
  1996.        XY_clip(*nvp++, TOP);
  1997.  
  1998.    if(nvcount>2) XY_clip(NULL, TOP);   /* flush pending vertices (poly)  */
  1999.  
  2000.  
  2001.    if((nvcptr<3 && p->npoints>2) || nvcptr<2)
  2002.      {
  2003.        return;      /* discard degenerate poly */
  2004.      }
  2005.    np->npoints = nvcptr;
  2006.   }
  2007.  npalloc = (NPOLY *)vpoly;         /* update space pointer */
  2008. }
  2009.  
  2010.  np->color = user_poly_color(p,p->color,nz);    /* user poly color select */
  2011.  
  2012. {
  2013.             /* add to list of polys to render */
  2014.  if (npols < maxpolys)
  2015.   {
  2016.  
  2017. r_polys_drawn++;
  2018.  
  2019.    polist[npols].ptr = np;
  2020.    polist[npols++].depth = nz;
  2021.   }
  2022.  else OK = 0;
  2023. }
  2024.  
  2025. }
  2026.  
  2027.  
  2028. /************ OBJECT-CLIPPING STUFF **************/
  2029.  
  2030. /* Some background: we compute the coefficients of the left, right, top and
  2031.    bottom clipping planes, and use these to do bounding-sphere testing.
  2032.    The routine define_view_volume() computes the various _A, _B, and _C
  2033.    variables (e.g. left_B); note that these are in viewpoint coordinates
  2034.    (i.e. viewer at the origin, looking in the +ve Z direction).
  2035.    Since all the clipping planes pass through the origin, _D is always zero.
  2036.    We also compute an _M value for each clipping plane, which
  2037.    is the magnitude of the plane normal (which is just [_A, _B, _C].  Note
  2038.    that the sign of the magnitude is the same as the sign of _C (since _D
  2039.    is always zero).
  2040.    Optimization: we don't bother with coefficients that are zero, and we
  2041.    don't bother multiplying by coefficients that are one.
  2042.  */
  2043.  
  2044. static long center_z;
  2045.  
  2046. static int clip_by_volume(OBJECT *obj)
  2047. {
  2048.  long sx, sy, sz;
  2049.  
  2050.  long tx = obj->sphx;
  2051.  long ty = obj->sphy;
  2052.  long tz = obj->sphz;
  2053.  
  2054.  long r = obj->sphr;
  2055.  
  2056.  if (obj->oflags & OBJ_INVIS) return 7;  /* invisible object */
  2057.  if (obj->oflags & OBJ_HIGHLIGHTED) {
  2058.     if (current_view->flags & HIDE_HIGHLIGHTED) return 8;
  2059.     }
  2060.  else {
  2061.     if (current_view->flags & HIDE_UNHIGHLIGHTED) return 9;
  2062.     }
  2063.       /* transform Z coord of bounding sphere; keep for optional depth sort */
  2064. asm{
  2065.     .386
  2066.     push    si
  2067.     push    di
  2068.  
  2069.     mov    eax,DWORD PTR fac7
  2070.     mov    edx,DWORD PTR tx
  2071.     sub    edx,DWORD PTR iview_x
  2072.     imul    edx
  2073.     mov    esi,eax
  2074.     mov    edi,edx
  2075.  
  2076.     mov    eax,DWORD PTR fac8
  2077.     mov    edx,DWORD PTR ty
  2078.     sub    edx,DWORD PTR iview_y
  2079.     imul    edx
  2080.     add    esi,eax
  2081.     adc    edi,edx
  2082.  
  2083.     mov    eax,DWORD PTR fac9
  2084.     mov    edx,DWORD PTR tz
  2085.     sub    edx,DWORD PTR iview_z
  2086.     imul    edx
  2087.     add    esi,eax
  2088.     adc    edi,edx
  2089.  
  2090.     shrd    esi,edi,27    /* prescaled z */
  2091.     mov    DWORD PTR center_z,esi
  2092.     sar    esi,2
  2093.     mov    DWORD PTR sz,esi
  2094.  
  2095.     pop     di
  2096.     pop    si
  2097.    }
  2098.  
  2099.  if (sz + r < hither) return 1;  /* front clip */
  2100.  if (sz - r > yon) return 2;     /* back clip */
  2101.  
  2102.     /* transform X coordinate of bounding sphere */
  2103. asm{
  2104.     .386
  2105.     push    si
  2106.     push    di
  2107.  
  2108.     mov    eax,DWORD PTR fac1
  2109.     mov    edx,DWORD PTR tx
  2110.     sub    edx,DWORD PTR iview_x
  2111.     imul    edx
  2112.     mov    esi,eax
  2113.     mov    edi,edx
  2114.  
  2115.     mov    eax,DWORD PTR fac2
  2116.     mov    edx,DWORD PTR ty
  2117.     sub    edx,DWORD PTR iview_y
  2118.     imul    edx
  2119.     add    esi,eax
  2120.     adc    edi,edx
  2121.  
  2122.     mov    eax,DWORD PTR fac3
  2123.     mov    edx,DWORD PTR tz
  2124.     sub    edx,DWORD PTR iview_z
  2125.     imul    edx
  2126.     add    esi,eax
  2127.     adc    edi,edx
  2128.  
  2129.     shrd    esi,edi,29
  2130.     mov    DWORD PTR sx,esi
  2131.  
  2132.     pop     di
  2133.     pop    si
  2134.    }
  2135.  
  2136. /* if (-(left_C*sz + left_M*sx) > r) return 3;    /* left */
  2137.  asm {
  2138.     mov    eax,DWORD PTR left_C
  2139.     neg    eax
  2140.     imul    DWORD PTR sz
  2141.     shrd    eax,edx,29
  2142.     mov    ecx,eax            /* compute -Cz - r */
  2143.     sub    ecx,r
  2144.  
  2145.     mov    eax,DWORD PTR left_M    /* compute Mz */
  2146.     imul    DWORD PTR sx
  2147.     shrd    eax,edx,29
  2148.  
  2149.     cmp    ecx,eax
  2150.     jle    lvis
  2151.      }
  2152.  return 3;        /* left clipped */
  2153.  
  2154. lvis:
  2155.  
  2156. /* if (-(right_C*sz - right_M*sx) > r) return 4;    /* right */
  2157.  asm {
  2158.     mov    eax,DWORD PTR right_C
  2159.     neg    eax
  2160.     imul    DWORD PTR sz
  2161.     shrd    eax,edx,29
  2162.     mov    ecx,eax            /* compute -Cz - r */
  2163.     sub    ecx,r
  2164.  
  2165.     mov    eax,DWORD PTR right_M    /* compute Mz */
  2166.     imul    DWORD PTR sx
  2167.     shrd    eax,edx,29
  2168.  
  2169.     neg    eax
  2170.     cmp    ecx,eax
  2171.     jle    rvis
  2172.      }
  2173.  return 4;        /* right clipped */
  2174.  
  2175. rvis:
  2176.     /* transform Y coordinate of bounding sphere */
  2177. asm{
  2178.     push    si
  2179.     push    di
  2180.  
  2181.     mov    eax,DWORD PTR fac4
  2182.     mov    edx,DWORD PTR tx
  2183.     sub    edx,DWORD PTR iview_x
  2184.     imul    edx
  2185.     mov    esi,eax
  2186.     mov    edi,edx
  2187.  
  2188.     mov    eax,DWORD PTR fac5
  2189.     mov    edx,DWORD PTR ty
  2190.     sub    edx,DWORD PTR iview_y
  2191.     imul    edx
  2192.     add    esi,eax
  2193.     adc    edi,edx
  2194.  
  2195.     mov    eax,DWORD PTR fac6
  2196.     mov    edx,DWORD PTR tz
  2197.     sub    edx,DWORD PTR iview_z
  2198.     imul    edx
  2199.     add    esi,eax
  2200.     adc    edi,edx
  2201.  
  2202.     shrd    esi,edi,29        /* 25 for x and y, 29 for z */
  2203.     mov    DWORD PTR sy,esi
  2204.  
  2205.     pop     di
  2206.     pop    si
  2207.    }
  2208.  
  2209. /* if (-(bot_C*sz + bot_M*sy) > r) return 5;    /* below */
  2210.  asm {
  2211.     mov    eax,DWORD PTR bot_C
  2212.     neg    eax
  2213.     imul    DWORD PTR sz
  2214.     shrd    eax,edx,29
  2215.     mov    ecx,eax            /* compute -Cz - r */
  2216.     sub    ecx,r
  2217.  
  2218.     mov    eax,DWORD PTR bot_M    /* compute Mz */
  2219.     imul    DWORD PTR sy
  2220.     shrd    eax,edx,29
  2221.  
  2222.     cmp    ecx,eax
  2223.     jle    bvis
  2224.      }
  2225.  return 5;        /* bottom clipped */
  2226.  
  2227. bvis:
  2228.  
  2229. /* if (-(top_C*sz - top_M*sy) > r) return 6;    /* above */
  2230.  asm {
  2231.     mov    eax,DWORD PTR top_C
  2232.     neg    eax
  2233.     imul    DWORD PTR sz
  2234.     shrd    eax,edx,29
  2235.     mov    ecx,eax            /* compute -Cz - r */
  2236.     sub    ecx,r
  2237.  
  2238.     mov    eax,DWORD PTR top_M    /* compute Mz */
  2239.     imul    DWORD PTR sy
  2240.     shrd    eax,edx,29
  2241.  
  2242.     neg    eax
  2243.     cmp    ecx,eax
  2244.     jle    tvis
  2245.      }
  2246.  return 6;        /* top clipped */
  2247.  
  2248. tvis:
  2249.     /* otherwise, it's at least partially inside the viewing volume */
  2250.  return 0;
  2251. }
  2252.  
  2253.  
  2254.  
  2255. static long compute_z(long tx,long ty,long tz)
  2256. {
  2257.  long sz;    /* Z coord transform for use in object depth sort  */
  2258.  
  2259. asm{
  2260.     .386
  2261.     push    cx
  2262.     push    di
  2263.  
  2264.     mov    eax,DWORD PTR fact7
  2265.     mov    edx,DWORD PTR tx
  2266.     sub    edx,DWORD PTR iview_x
  2267.     imul    edx
  2268.     mov    ecx,eax
  2269.     mov    edi,edx
  2270.  
  2271.     mov    eax,DWORD PTR fact8
  2272.     mov    edx,DWORD PTR ty
  2273.     sub    edx,DWORD PTR iview_y
  2274.     imul    edx
  2275.     add    ecx,eax
  2276.     adc    edi,edx
  2277.  
  2278.     mov    eax,DWORD PTR fact9
  2279.     mov    edx,DWORD PTR tz
  2280.     sub    edx,DWORD PTR iview_z
  2281.     imul    edx
  2282.     add    ecx,eax
  2283.     adc    edi,edx
  2284.  
  2285.     shrd    ecx,edi,27        /* 29 - PRESCALEZ */
  2286.  
  2287.     mov    DWORD PTR sz,ecx
  2288.  
  2289.     pop     di
  2290.     pop    cx
  2291.    }
  2292.  return sz;
  2293. }
  2294.  
  2295. /*********** OBJECT-RENDERING CONTROL **********/
  2296.  
  2297. extern void move_rep(OBJECT *obj);
  2298.  
  2299. static int proc_obj(OBJECT *obj, long centz)
  2300. {
  2301.  int i;
  2302.  REP *repp;
  2303.  long r = obj->sphr;
  2304.  long oscreen;
  2305.  
  2306.  if(obj==NULL) return 1;                        /* fooled ya ! */
  2307.  if((repp = obj->replist)==NULL) return 1;     /* no representation */
  2308.  if(centz<hither) goto usethis;                 /* bad center */
  2309.  
  2310.  while(repp!=NULL)                /* choose representation to use */
  2311.     {
  2312.      if(repp->size==0) goto usethis;
  2313.    asm {
  2314.     mov    eax,r           /* size = scale*radius/distance */
  2315.     imul    DWORD PTR scx
  2316.     shrd    eax,edx,8        /* range-extended <16.16> -> <32.0> */
  2317.     sar    edx,8
  2318.     idiv    DWORD PTR centz
  2319.     sar    eax,6               /* 2x true size */
  2320.     mov    oscreen,eax
  2321.        }
  2322.    if(oscreen<0) goto usethis;
  2323.    if(oscreen>=(repp->size)) goto usethis;  /* 0 size always drawn */
  2324.      if(repp->next!=NULL) repp = repp->next;
  2325.      else return 1;
  2326.   }
  2327. usethis:
  2328.  obj->current_rep = repp;
  2329.  if(repp==NULL)
  2330.     return 1;        /* nothing if too far */
  2331.  
  2332.  if(obj->update_count != repp->update_count)  /* move if needed */
  2333.     move_rep(obj);
  2334.  
  2335. /* for (i = 0; i < obj->npoints; ++i)      /* at first, no transforms done */
  2336. /*  {
  2337.    repp->verts[i].new_copy = NULL;
  2338.    repp->verts[i].z_transformed = 0;
  2339.   }*/
  2340.  
  2341.  i = sizeof(VERTEX);
  2342.  
  2343.  asm {
  2344.     les    bx,repp
  2345.     mov    cx,es:[bx].(REP)nverts
  2346.     les    bx,es:[bx].(REP)verts
  2347.      }
  2348. cvloop:
  2349.  asm {
  2350.     mov    DWORD PTR es:[bx].(VERTEX)new_copy,0
  2351.     mov     BYTE PTR es:[bx].(VERTEX)z_transformed,0
  2352.     add    bx,WORD PTR i
  2353.     loop    cvloop
  2354.      }
  2355.  
  2356.  i = sizeof(POLY);
  2357.  
  2358.  asm {
  2359.     les    bx,repp
  2360.     mov    cx,es:[bx].(REP)npolys
  2361.     les    bx,es:[bx].(REP)polys
  2362.      }
  2363. cploop:
  2364.  asm {
  2365.     push    cx
  2366.     push    es
  2367.     push    bx
  2368.     push    cs
  2369.     call    near ptr proc_poly
  2370.     pop    bx
  2371.     pop    es
  2372.     pop    cx
  2373.     add    bx,WORD PTR i
  2374.     mov    ax,OK
  2375.     or    ax,ax
  2376.     jz    abort
  2377.     loop    cploop
  2378.      }
  2379.  abort:
  2380.  return 0;  /* return 0, object not clipped */
  2381. }
  2382.  
  2383.  
  2384.         /* quicksort DSORT array by depth */
  2385.  
  2386. static void iqsort(int m, int n)    /* m, n actually near ptrs into array */
  2387. {                                   /* es is seg. of array throughout */
  2388.  int i,j;                           /* keep array under 32K in size!  */
  2389.  
  2390.  asm {
  2391.     .386
  2392.     mov    si,m            /* i */
  2393.     cmp    si,n
  2394.     jl    keepon
  2395.      }
  2396.  return;
  2397.  
  2398. keepon:
  2399.  asm {
  2400.     mov    di,n            /* j */
  2401.     add     di,8
  2402.     mov    eax,DWORD PTR es:[si].(DSORT)depth  /* k */
  2403.      }
  2404.  
  2405. gloop:
  2406.  
  2407. fmax:
  2408.  asm {
  2409.     add    si,8
  2410.     cmp    DWORD PTR es:[si].(DSORT)depth,eax
  2411.     jg    fmax
  2412.      }
  2413.  
  2414. fmin:
  2415.  asm {
  2416.     sub    di,8
  2417.     cmp    DWORD PTR es:[di].(DSORT)depth,eax
  2418.     jl    fmin
  2419.  
  2420.     cmp    si,di
  2421.     jge    nonswap
  2422.  
  2423.     mov    ecx,DWORD PTR es:[si]
  2424.     mov    edx,DWORD PTR es:[di]
  2425.     mov    DWORD PTR es:[di],ecx
  2426.     mov    DWORD PTR es:[si],edx
  2427.     mov    ecx,DWORD PTR es:[si+4]
  2428.     mov    edx,DWORD PTR es:[di+4]
  2429.     mov    DWORD PTR es:[di+4],ecx
  2430.     mov    DWORD PTR es:[si+4],edx
  2431.     jmp    gloop
  2432.      }
  2433. nonswap:
  2434.  asm {
  2435.     mov    si,m
  2436.     mov    ecx,DWORD PTR es:[si]
  2437.     mov    edx,DWORD PTR es:[di]
  2438.     mov    DWORD PTR es:[di],ecx
  2439.     mov    DWORD PTR es:[si],edx
  2440.     mov    ecx,DWORD PTR es:[si+4]
  2441.     mov    edx,DWORD PTR es:[di+4]
  2442.     mov    DWORD PTR es:[di+4],ecx
  2443.     mov    DWORD PTR es:[si+4],edx
  2444.  
  2445.     mov    j,di
  2446.      }
  2447.  
  2448.  if(m < j-8) iqsort(m,j-8);
  2449.  if(j+8 < n) iqsort(j+8,n);
  2450.  }
  2451.  
  2452.  
  2453. static int test_poly_point = 0;
  2454. static int test_point_x;
  2455. static int test_point_y;
  2456. static int which_vertex;    /* npoly vertex # closest <UNTESTED YET> */
  2457. static POLY * in_poly;
  2458. static long poly_depth;
  2459.  
  2460. #pragma argsused
  2461. static test_poly(int n, int *p, long maxz, int polarity, NPOLY *np)
  2462. {
  2463.  int left = 0;                   /* test if point in poly on screen */
  2464.  int right = 0;
  2465.  int point = n;
  2466.  
  2467.  asm {
  2468.     push    si
  2469.     push    di
  2470.     push    cx
  2471.     mov    cx,n
  2472.     dec    cx
  2473.     les    bx,p
  2474.     mov    si,bx
  2475.     add    si,4
  2476.      }
  2477. tedge:
  2478.  asm {
  2479.     mov    ax,test_point_y   /* test point */
  2480.     mov    dx,test_point_x
  2481.  
  2482.     cmp    ax,[bx+2]      /*; check vertical */
  2483.     jle    above1
  2484.     cmp    ax,[si+2]
  2485.     jg    notine        /*; not in edge */
  2486.      }
  2487. above1:
  2488.  asm {
  2489.     cmp    ax,[bx+2]
  2490.     jge    vertok
  2491.     cmp    ax,[si+2]
  2492.     jl    notine        /*; not in edge */
  2493.          }
  2494. vertok:
  2495.  asm {
  2496.     cmp    dx,[bx]
  2497.     jg    rt1
  2498.     cmp    dx,[si]
  2499.     jle    left           /* ; to left of edge */
  2500.     jmp    allok
  2501.      }
  2502. rt1:
  2503.  asm {
  2504.     cmp    dx,[si]
  2505.     jg    right          /* ; to right of edge */
  2506.      }
  2507. allok:
  2508.  asm {
  2509.     sub    ax,[bx+2]       /* ; y - y1 */
  2510.     mov    dx,[si]
  2511.     sub    dx,[bx]         /* ; x2 - x1 */
  2512.     imul    dx
  2513.     mov    di,[si+2]
  2514.     sub    di,[bx+2]       /* ; y2 - y1 */
  2515.     je    pend        /* must be between... */
  2516.     idiv    di
  2517.     add    ax,[bx]        /* ; + x1 */
  2518.     cmp    ax,test_point_x
  2519.     jle    right        /* ; tested left */
  2520.      }
  2521. left:
  2522.  asm {
  2523.     inc    WORD PTR left
  2524.     test    WORD PTR right,-1
  2525.     jnz     inpoly
  2526.     jmp    pend
  2527.      }
  2528. right:
  2529.  asm {
  2530.     inc    WORD PTR right
  2531.     test    WORD PTR left,-1
  2532.     jnz     inpoly
  2533.      }
  2534. notine:
  2535. pend:
  2536.  asm {
  2537.     add    si,4
  2538.     add    bx,4
  2539.     sub    cx,1
  2540.     jg    tedge
  2541.     jl    notin
  2542.     mov    si,WORD PTR p
  2543.     jmp     tedge
  2544.      }
  2545. inpoly:
  2546.  asm {
  2547.     mov    eax,maxz
  2548.     cmp    eax,DWORD PTR poly_depth
  2549.     jg    notin
  2550.  
  2551.     mov    cx,n
  2552.     mov    bx,-1
  2553.      }
  2554. vdtest:
  2555.  asm {
  2556.     mov    ax,test_point_x
  2557.     sub    ax,[si]
  2558.     cwd
  2559.     xor    ax,dx
  2560.     sub    ax,dx
  2561.     mov    di,ax
  2562.     mov    ax,test_point_y
  2563.     sub    ax,[si+2]
  2564.     cwd
  2565.     xor    ax,dx
  2566.     sub    ax,dx
  2567.     add    di,ax
  2568.     cmp    bx,di
  2569.     jbe    nond
  2570.     mov     bx,di
  2571.     mov    point,cx
  2572.     add    si,4
  2573.      }
  2574. nond:
  2575.  asm {
  2576.     loop    vdtest
  2577.     pop    cx
  2578.     pop    di
  2579.     pop    si
  2580.      }
  2581.  which_vertex = n-point;
  2582.  if(polarity) which_vertex = n-1-which_vertex;
  2583.  return 1;
  2584.  
  2585. notin:
  2586.  asm {
  2587.     pop    cx
  2588.     pop    di
  2589.     pop    si
  2590.      }
  2591.  return 0;
  2592. }
  2593.  
  2594.  
  2595. #define INTASZE 30
  2596. static int pcoords[INTASZE*2];
  2597. extern void user_render_poly(int vertex_count, int *pcoords,
  2598.                  unsigned poly_color, long max_depth);
  2599.  
  2600.             /* copies poly data, submits to renderer   */
  2601.             /* copy in reverse order if flipped screen */
  2602. static void submit_poly(NPOLY *p, long maxz)
  2603. {
  2604.  int number;
  2605.  int polarity = 0;
  2606.  unsigned color = p->color;
  2607.  int a = FP_OFF(&pcoords[0]);
  2608.  
  2609.  if(orientation==NOFLIP || orientation==(XFLIP|YFLIP))
  2610.   {
  2611.      _AX = sizeof(NPOLY);
  2612.      asm {
  2613.     .386
  2614.     push    si
  2615.     les    bx,DWORD PTR p
  2616.     mov    cx,WORD PTR es:[bx].(NPOLY)npoints
  2617.     mov    WORD PTR number,cx
  2618.     mov    si,bx
  2619.     add    si,ax                        /* table of ptrs */
  2620.     mov    di,WORD PTR a
  2621.     push    es
  2622.              }
  2623.      coppl:
  2624.      asm {
  2625.     pop    es
  2626.     push    es
  2627.     les    bx,DWORD PTR es:[si]
  2628.     mov    ax,WORD PTR es:[bx].(NVERTEX)xs
  2629.     add    ax,2
  2630.     shr    ax,2
  2631.     mov    WORD PTR ds:[di],ax
  2632.     add    di,2
  2633.     mov    ax,WORD PTR es:[bx].(NVERTEX)ys
  2634.     add    ax,2
  2635.     shr    ax,2
  2636.     mov    WORD PTR ds:[di],ax
  2637.     add    di,2
  2638.     add    si,4
  2639.     loop    coppl
  2640.     pop    si
  2641.     pop    si
  2642.        }
  2643.   }
  2644.  else        /* copy vertices in reverse order */
  2645.   {
  2646.    _AX = sizeof(NPOLY);
  2647.    asm {
  2648.     .386
  2649.     push    si
  2650.     not    WORD PTR polarity
  2651.     les    bx,DWORD PTR p
  2652.     mov    si,bx
  2653.     add    si,ax                /* table of ptrs */
  2654.     mov    cx,WORD PTR es:[bx].(NPOLY)npoints
  2655.     mov    WORD PTR number,cx
  2656.     mov    di,WORD PTR a
  2657.     add    si,cx
  2658.     add    si,cx
  2659.     add    si,cx
  2660.     add    si,cx
  2661.     sub    si,4
  2662.     push    es
  2663.        }
  2664.    copplr:
  2665.      asm {
  2666.     pop    es
  2667.     push    es
  2668.     les    bx,DWORD PTR es:[si]
  2669.     mov    ax,WORD PTR es:[bx].(NVERTEX)xs
  2670.     add    ax,2
  2671.     shr    ax,2
  2672.     mov    WORD PTR ds:[di],ax
  2673.     add    di,2
  2674.     mov    ax,WORD PTR es:[bx].(NVERTEX)ys
  2675.     add    ax,2
  2676.     shr    ax,2
  2677.     mov    WORD PTR ds:[di],ax
  2678.     add    di,2
  2679.     sub    si,4
  2680.     loop    copplr
  2681.     pop    si
  2682.     pop    si
  2683.        }
  2684.   }
  2685.  
  2686.  user_render_poly(number, &pcoords[0], color, maxz);
  2687.  if(test_poly_point && number>2)
  2688.   if(test_poly(number, &pcoords[0], maxz, polarity, p))
  2689.    {
  2690.     poly_depth = maxz;
  2691.     in_poly = p->parent;
  2692.    }
  2693. }
  2694.  
  2695.  
  2696.  
  2697. extern void user_setup_blitter();
  2698. extern void user_reset_blitter();
  2699.  
  2700. static MATRIX dummy;
  2701.  
  2702. void subrender(OBJLIST *objlist)
  2703. {
  2704.  OBJECT *obj;
  2705.  int i;
  2706.  int lseg;
  2707.  int snpoly = 0;
  2708.  int nobs = 0;
  2709.  
  2710.  init_render();
  2711.  
  2712.  if(objlist==NULL ||
  2713.     objlist->nnext==NULL ||
  2714.     objlist->nnext==objlist->prev)  return;
  2715.  
  2716.  npols = 0;
  2717.  OK = 1;
  2718.                 /* step 1: sort objects and polys together */
  2719.  polist = visobjs;
  2720.  for (obj = objlist->nnext; obj; obj = obj->nnext)
  2721.   {
  2722.  
  2723. r_objects_tested++;
  2724.     if (clip_by_volume(obj) == 0)
  2725.      {
  2726. r_objects_passed++;
  2727.  
  2728.       if((depth_type = obj->oflags)&BYOBJECT)
  2729.     {
  2730.       obj->oflags |= IS_OBJECT;
  2731.       polist[npols].ptr = (NPOLY *) obj;             /* obj. depth only */
  2732.       polist[npols++].depth = center_z;
  2733.     }
  2734.      else
  2735.     {
  2736.      proc_obj(obj, center_z);                /* all polys in object */
  2737.      if(OK==0) break;
  2738.     }
  2739.      }
  2740.   }
  2741.  
  2742.  if(npols>1)
  2743.   {
  2744.    npols--;
  2745.    lseg = FP_SEG(polist);            /* sort all items by max Z */
  2746.    asm {
  2747.     push    si
  2748.     push    di
  2749.     mov    ax,lseg                  /* visobjs segment */
  2750.     mov    es,ax
  2751.        }
  2752.    iqsort( FP_OFF(&visobjs[0]), FP_OFF(&visobjs[npols]) );
  2753.    asm {
  2754.     pop    di
  2755.     pop    si
  2756.        }
  2757.    npols++;
  2758.   }
  2759.  nobs = npols;
  2760.  npols = 0;
  2761.  polist = vispolys;
  2762.  lseg = FP_SEG(polist);
  2763.  
  2764.  for (i=0;i<nobs;i++)                  /* now expand objects */
  2765.   {
  2766.    if(!(*((int *)visobjs[i].ptr) & IS_OBJECT))
  2767.     {
  2768.      memcpy(&vispolys[npols++], &visobjs[i], sizeof(DSORT));   /* just copy polys */
  2769.     }
  2770.    else
  2771.     {
  2772.      snpoly = npols;                   /* expand objects */
  2773.      proc_obj((OBJECT *) visobjs[i].ptr, visobjs[i].depth);
  2774.      if(OK==0) break;
  2775.      if(npols-snpoly>1)
  2776.       {
  2777.        npols--;                        /* resort within objects */
  2778.        asm {
  2779.         push    si
  2780.         push    di
  2781.         mov    ax,lseg                  /* vispolys segment */
  2782.         mov    es,ax
  2783.        }
  2784.        iqsort( FP_OFF(&vispolys[snpoly]), FP_OFF(&vispolys[npols]) );
  2785.        asm {
  2786.         pop    di
  2787.         pop    si
  2788.        }
  2789.        npols++;
  2790.       }
  2791.     }
  2792.    if(npols >= maxpolys) break;
  2793.   }
  2794.  
  2795.  user_setup_blitter();                /* draw the polys */
  2796.  for (i = 0; i < npols; ++i)
  2797.     submit_poly(vispolys[i].ptr,vispolys[i].depth);
  2798.  user_reset_blitter();
  2799. }
  2800.  
  2801.  
  2802. void set_screen_monitor(int x, int y)
  2803. {
  2804.  test_poly_point = 1;
  2805.  test_point_x = x;
  2806.  test_point_y = y;
  2807.  poly_depth = 0x7FFFFFFF;
  2808.  in_poly = NULL;
  2809. }
  2810.  
  2811. void render(OBJLIST *objlist, VIEW *view)
  2812. {
  2813.  render_set_view(view);
  2814.  subrender(objlist);
  2815. }
  2816.  
  2817. void clear_screen_monitor()
  2818. {
  2819.  test_poly_point = 0;
  2820. }
  2821.  
  2822. POLY *read_screen_monitor()
  2823. {
  2824.  return in_poly;
  2825. }
  2826.  
  2827.  
  2828.