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