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