home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / d_polyset.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  26.4 KB  |  1,117 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // d_polyset.c: routines for drawing sets of polygons sharing the same
  21. // texture (used for Alias models)
  22.  
  23. #include "quakedef.h"
  24. #include "r_local.h"
  25. #include "d_local.h"
  26.  
  27. // TODO: put in span spilling to shrink list size
  28. // !!! if this is changed, it must be changed in d_polysa.s too !!!
  29. #define DPS_MAXSPANS      MAXHEIGHT+1 
  30.                   // 1 extra for spanpackage that marks end
  31.  
  32. // !!! if this is changed, it must be changed in asm_draw.h too !!!
  33. typedef struct {
  34.   void      *pdest;
  35.   short     *pz;
  36.   int       count;
  37.   byte      *ptex;
  38.   int       sfrac, tfrac, light, zi;
  39. } spanpackage_t;
  40.  
  41. typedef struct {
  42.   int   isflattop;
  43.   int   numleftedges;
  44.   int   *pleftedgevert0;
  45.   int   *pleftedgevert1;
  46.   int   *pleftedgevert2;
  47.   int   numrightedges;
  48.   int   *prightedgevert0;
  49.   int   *prightedgevert1;
  50.   int   *prightedgevert2;
  51. } edgetable;
  52.  
  53. int r_p0[6], r_p1[6], r_p2[6];
  54.  
  55. byte    *d_pcolormap;
  56.  
  57. int     d_aflatcolor;
  58. int     d_xdenom;
  59.  
  60. edgetable *pedgetable;
  61.  
  62. edgetable edgetables[12] = {
  63.   {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
  64.   {0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, NULL},
  65.   {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
  66.   {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
  67.   {0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, NULL},
  68.   {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
  69.   {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
  70.   {0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, NULL},
  71.   {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
  72.   {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
  73.   {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
  74.   {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
  75. };
  76.  
  77. // FIXME: some of these can become statics
  78. int       a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
  79. int       r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
  80. int       r_zistepx, r_zistepy;
  81. int       d_aspancount, d_countextrastep;
  82.  
  83. spanpackage_t     *a_spans;
  84. spanpackage_t     *d_pedgespanpackage;
  85. static int        ystart;
  86. byte          *d_pdest, *d_ptex;
  87. short         *d_pz;
  88. int           d_sfrac, d_tfrac, d_light, d_zi;
  89. int           d_ptexextrastep, d_sfracextrastep;
  90. int           d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
  91. int           d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
  92. int           d_sfracbasestep, d_tfracbasestep;
  93. int           d_ziextrastep, d_zibasestep;
  94. int           d_pzextrastep, d_pzbasestep;
  95.  
  96. typedef struct {
  97.   int   quotient;
  98.   int   remainder;
  99. } adivtab_t;
  100.  
  101. #if !defined(M68KASM) && !defined(PPCASM)
  102. static adivtab_t  adivtab[32*32] = {
  103. #include "adivtab.h"
  104. };
  105. #endif
  106.  
  107. byte  *skintable[MAX_LBM_HEIGHT];
  108. int   skinwidth;
  109. byte  *skinstart;
  110.  
  111. void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage);
  112. void D_PolysetCalcGradients (int skinwidth);
  113. void D_DrawSubdiv (void);
  114. void D_DrawNonSubdiv (void);
  115. void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
  116. void D_PolysetSetEdgeTable (void);
  117. void D_RasterizeAliasPolySmooth (void);
  118. void D_PolysetScanLeftEdge (int height);
  119.  
  120. #if !id386
  121.  
  122. /*
  123. ================
  124. D_PolysetDraw
  125. ================
  126. */
  127. void D_PolysetDraw (void)
  128. {
  129.   spanpackage_t spans[DPS_MAXSPANS + 1 +
  130.       ((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
  131.             // one extra because of cache line pretouching
  132.  
  133.   a_spans = (spanpackage_t *)
  134.       (((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
  135.  
  136.   if (r_affinetridesc.drawtype)
  137.   {
  138.     D_DrawSubdiv ();
  139.   }
  140.   else
  141.   {
  142.     D_DrawNonSubdiv ();
  143.   }
  144. }
  145.  
  146.  
  147. /*
  148. ================
  149. D_PolysetDrawFinalVerts
  150. ================
  151. */
  152. void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
  153. {
  154.   int   i, z;
  155.   short *zbuf;
  156.  
  157.   for (i=0 ; i<numverts ; i++, fv++)
  158.   {
  159.   // valid triangle coordinates for filling can include the bottom and
  160.   // right clip edges, due to the fill rule; these shouldn't be drawn
  161.     if ((fv->v[0] < r_refdef.vrectright) &&
  162.       (fv->v[1] < r_refdef.vrectbottom))
  163.     {
  164.       z = fv->v[5]>>16;
  165.       zbuf = zspantable[fv->v[1]] + fv->v[0];
  166.       if (z >= *zbuf)
  167.       {
  168.         int   pix;
  169.         
  170.         *zbuf = z;
  171.         pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
  172.         pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
  173.         d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
  174.       }
  175.     }
  176.   }
  177. }
  178.  
  179.  
  180. #ifndef PPCASM
  181. /*
  182. ================
  183. D_DrawSubdiv
  184. ================
  185. */
  186. void D_DrawSubdiv (void)
  187. {
  188.   mtriangle_t   *ptri;
  189.   finalvert_t   *pfv, *index0, *index1, *index2;
  190.   int       i;
  191.   int       lnumtriangles;
  192.  
  193.   pfv = r_affinetridesc.pfinalverts;
  194.   ptri = r_affinetridesc.ptriangles;
  195.   lnumtriangles = r_affinetridesc.numtriangles;
  196.  
  197.   for (i=0 ; i<lnumtriangles ; i++)
  198.   {
  199.     index0 = pfv + ptri[i].vertindex[0];
  200.     index1 = pfv + ptri[i].vertindex[1];
  201.     index2 = pfv + ptri[i].vertindex[2];
  202.  
  203.     if (((index0->v[1]-index1->v[1]) *
  204.        (index0->v[0]-index2->v[0]) -
  205.        (index0->v[0]-index1->v[0]) * 
  206.        (index0->v[1]-index2->v[1])) >= 0)
  207.     {
  208.       continue;
  209.     }
  210.  
  211.     d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
  212.  
  213.     if (ptri[i].facesfront)
  214.     {
  215.       D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
  216.     }
  217.     else
  218.     {
  219.       int   s0, s1, s2;
  220.  
  221.       s0 = index0->v[2];
  222.       s1 = index1->v[2];
  223.       s2 = index2->v[2];
  224.  
  225.       if (index0->flags & ALIAS_ONSEAM)
  226.         index0->v[2] += r_affinetridesc.seamfixupX16;
  227.       if (index1->flags & ALIAS_ONSEAM)
  228.         index1->v[2] += r_affinetridesc.seamfixupX16;
  229.       if (index2->flags & ALIAS_ONSEAM)
  230.         index2->v[2] += r_affinetridesc.seamfixupX16;
  231.  
  232.       D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
  233.  
  234.       index0->v[2] = s0;
  235.       index1->v[2] = s1;
  236.       index2->v[2] = s2;
  237.     }
  238.   }
  239. }
  240. #endif
  241.  
  242.  
  243. #if !defined(M68KASM) && !defined(PPCASM)
  244. /*
  245. ================
  246. D_DrawNonSubdiv
  247. ================
  248. */
  249. void D_DrawNonSubdiv (void)
  250. {
  251.   mtriangle_t   *ptri;
  252.   finalvert_t   *pfv, *index0, *index1, *index2;
  253.   int       i;
  254.   int       lnumtriangles;
  255.  
  256.   pfv = r_affinetridesc.pfinalverts;
  257.   ptri = r_affinetridesc.ptriangles;
  258.   lnumtriangles = r_affinetridesc.numtriangles;
  259.  
  260.   for (i=0 ; i<lnumtriangles ; i++, ptri++)
  261.   {
  262.     index0 = pfv + ptri->vertindex[0];
  263.     index1 = pfv + ptri->vertindex[1];
  264.     index2 = pfv + ptri->vertindex[2];
  265.  
  266.     d_xdenom = (index0->v[1]-index1->v[1]) *
  267.         (index0->v[0]-index2->v[0]) -
  268.         (index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
  269.  
  270.     if (d_xdenom >= 0)
  271.     {
  272.       continue;
  273.     }
  274.  
  275.     r_p0[0] = index0->v[0];   // u
  276.     r_p0[1] = index0->v[1];   // v
  277.     r_p0[2] = index0->v[2];   // s
  278.     r_p0[3] = index0->v[3];   // t
  279.     r_p0[4] = index0->v[4];   // light
  280.     r_p0[5] = index0->v[5];   // iz
  281.  
  282.     r_p1[0] = index1->v[0];
  283.     r_p1[1] = index1->v[1];
  284.     r_p1[2] = index1->v[2];
  285.     r_p1[3] = index1->v[3];
  286.     r_p1[4] = index1->v[4];
  287.     r_p1[5] = index1->v[5];
  288.  
  289.     r_p2[0] = index2->v[0];
  290.     r_p2[1] = index2->v[1];
  291.     r_p2[2] = index2->v[2];
  292.     r_p2[3] = index2->v[3];
  293.     r_p2[4] = index2->v[4];
  294.     r_p2[5] = index2->v[5];
  295.  
  296.     if (!ptri->facesfront)
  297.     {
  298.       if (index0->flags & ALIAS_ONSEAM)
  299.         r_p0[2] += r_affinetridesc.seamfixupX16;
  300.       if (index1->flags & ALIAS_ONSEAM)
  301.         r_p1[2] += r_affinetridesc.seamfixupX16;
  302.       if (index2->flags & ALIAS_ONSEAM)
  303.         r_p2[2] += r_affinetridesc.seamfixupX16;
  304.     }
  305.  
  306.     D_PolysetSetEdgeTable ();
  307.     D_RasterizeAliasPolySmooth ();
  308.   }
  309. }
  310.  
  311.  
  312. /*
  313. ================
  314. D_PolysetRecursiveTriangle
  315. ================
  316. */
  317. void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
  318. {
  319.   int   *temp;
  320.   int   d;
  321.   int   new[6];
  322.   int   z;
  323.   short *zbuf;
  324.  
  325.   d = lp2[0] - lp1[0];
  326.   if (d < -1 || d > 1)
  327.     goto split;
  328.   d = lp2[1] - lp1[1];
  329.   if (d < -1 || d > 1)
  330.     goto split;
  331.  
  332.   d = lp3[0] - lp2[0];
  333.   if (d < -1 || d > 1)
  334.     goto split2;
  335.   d = lp3[1] - lp2[1];
  336.   if (d < -1 || d > 1)
  337.     goto split2;
  338.  
  339.   d = lp1[0] - lp3[0];
  340.   if (d < -1 || d > 1)
  341.     goto split3;
  342.   d = lp1[1] - lp3[1];
  343.   if (d < -1 || d > 1)
  344.   {
  345. split3:
  346.     temp = lp1;
  347.     lp1 = lp3;
  348.     lp3 = lp2;
  349.     lp2 = temp;
  350.  
  351.     goto split;
  352.   }
  353.  
  354.   return;     // entire tri is filled
  355.  
  356. split2:
  357.   temp = lp1;
  358.   lp1 = lp2;
  359.   lp2 = lp3;
  360.   lp3 = temp;
  361.  
  362. split:
  363. // split this edge
  364.   new[0] = (lp1[0] + lp2[0]) >> 1;
  365.   new[1] = (lp1[1] + lp2[1]) >> 1;
  366.   new[2] = (lp1[2] + lp2[2]) >> 1;
  367.   new[3] = (lp1[3] + lp2[3]) >> 1;
  368.   new[5] = (lp1[5] + lp2[5]) >> 1;
  369.  
  370. // draw the point if splitting a leading edge
  371.   if (lp2[1] > lp1[1])
  372.     goto nodraw;
  373.   if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
  374.     goto nodraw;
  375.  
  376.  
  377.   z = new[5]>>16;
  378.   zbuf = zspantable[new[1]] + new[0];
  379.   if (z >= *zbuf)
  380.   {
  381.     int   pix;
  382.     
  383.     *zbuf = z;
  384.     pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
  385.     d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
  386.   }
  387.  
  388. nodraw:
  389. // recursively continue
  390.   D_PolysetRecursiveTriangle (lp3, lp1, new);
  391.   D_PolysetRecursiveTriangle (lp3, new, lp2);
  392. }
  393. #endif
  394. #endif  // !id386
  395.  
  396.  
  397. /*
  398. ================
  399. D_PolysetUpdateTables
  400. ================
  401. */
  402. void D_PolysetUpdateTables (void)
  403. {
  404.   int   i;
  405.   byte  *s;
  406.   
  407.   if (r_affinetridesc.skinwidth != skinwidth ||
  408.     r_affinetridesc.pskin != skinstart)
  409.   {
  410.     skinwidth = r_affinetridesc.skinwidth;
  411.     skinstart = r_affinetridesc.pskin;
  412.     s = skinstart;
  413.     for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
  414.       skintable[i] = s;
  415.   }
  416. }
  417.  
  418.  
  419. #if !id386 && !defined(M68KASM) && !defined(PPCASM)
  420. /*
  421. ===================
  422. D_PolysetScanLeftEdge
  423. ====================
  424. */
  425. void D_PolysetScanLeftEdge (int height)
  426. {
  427.  
  428.   do
  429.   {
  430.     d_pedgespanpackage->pdest = d_pdest;
  431.     d_pedgespanpackage->pz = d_pz;
  432.     d_pedgespanpackage->count = d_aspancount;
  433.     d_pedgespanpackage->ptex = d_ptex;
  434.  
  435.     d_pedgespanpackage->sfrac = d_sfrac;
  436.     d_pedgespanpackage->tfrac = d_tfrac;
  437.  
  438.   // FIXME: need to clamp l, s, t, at both ends?
  439.     d_pedgespanpackage->light = d_light;
  440.     d_pedgespanpackage->zi = d_zi;
  441.  
  442.     d_pedgespanpackage++;
  443.  
  444.     errorterm += erroradjustup;
  445.     if (errorterm >= 0)
  446.     {
  447.       d_pdest += d_pdestextrastep;
  448.       d_pz += d_pzextrastep;
  449.       d_aspancount += d_countextrastep;
  450.       d_ptex += d_ptexextrastep;
  451.       d_sfrac += d_sfracextrastep;
  452.       d_ptex += d_sfrac >> 16;
  453.  
  454.       d_sfrac &= 0xFFFF;
  455.       d_tfrac += d_tfracextrastep;
  456.       if (d_tfrac & 0x10000)
  457.       {
  458.         d_ptex += r_affinetridesc.skinwidth;
  459.         d_tfrac &= 0xFFFF;
  460.       }
  461.       d_light += d_lightextrastep;
  462.       d_zi += d_ziextrastep;
  463.       errorterm -= erroradjustdown;
  464.     }
  465.     else
  466.     {
  467.       d_pdest += d_pdestbasestep;
  468.       d_pz += d_pzbasestep;
  469.       d_aspancount += ubasestep;
  470.       d_ptex += d_ptexbasestep;
  471.       d_sfrac += d_sfracbasestep;
  472.       d_ptex += d_sfrac >> 16;
  473.       d_sfrac &= 0xFFFF;
  474.       d_tfrac += d_tfracbasestep;
  475.       if (d_tfrac & 0x10000)
  476.       {
  477.         d_ptex += r_affinetridesc.skinwidth;
  478.         d_tfrac &= 0xFFFF;
  479.       }
  480.       d_light += d_lightbasestep;
  481.       d_zi += d_zibasestep;
  482.     }
  483.   } while (--height);
  484. }
  485. #endif  // !id386/!PPCASM/!M68KASM
  486.  
  487.  
  488. #if !defined(M68KASM) && !defined(PPCASM)
  489. /*
  490. ===================
  491. D_PolysetSetUpForLineScan
  492. ====================
  493. */
  494. void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
  495.     fixed8_t endvertu, fixed8_t endvertv)
  496. {
  497.   double    dm, dn;
  498.   int     tm, tn;
  499.   adivtab_t *ptemp;
  500.  
  501. // TODO: implement x86 version
  502.  
  503.   errorterm = -1;
  504.  
  505.   tm = endvertu - startvertu;
  506.   tn = endvertv - startvertv;
  507.  
  508.   if (((tm <= 16) && (tm >= -15)) &&
  509.     ((tn <= 16) && (tn >= -15)))
  510.   {
  511.     ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
  512.     ubasestep = ptemp->quotient;
  513.     erroradjustup = ptemp->remainder;
  514.     erroradjustdown = tn;
  515.   }
  516.   else
  517.   {
  518.     dm = (double)tm;
  519.     dn = (double)tn;
  520.  
  521.     FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
  522.  
  523.     erroradjustdown = dn;
  524.   }
  525. }
  526. #endif
  527.  
  528.  
  529. #if !id386 && !defined(M68KASM) && !defined(PPCASM)
  530. /*
  531. ================
  532. D_PolysetCalcGradients
  533. ================
  534. */
  535. void D_PolysetCalcGradients (int skinwidth)
  536. {
  537.   float xstepdenominv, ystepdenominv, t0, t1;
  538.   float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
  539.  
  540.   p00_minus_p20 = r_p0[0] - r_p2[0];
  541.   p01_minus_p21 = r_p0[1] - r_p2[1];
  542.   p10_minus_p20 = r_p1[0] - r_p2[0];
  543.   p11_minus_p21 = r_p1[1] - r_p2[1];
  544.  
  545.   xstepdenominv = 1.0 / (float)d_xdenom;
  546.  
  547.   ystepdenominv = -xstepdenominv;
  548.  
  549. // ceil () for light so positive steps are exaggerated, negative steps
  550. // diminished,  pushing us away from underflow toward overflow. Underflow is
  551. // very visible, overflow is very unlikely, because of ambient lighting
  552.   t0 = r_p0[4] - r_p2[4];
  553.   t1 = r_p1[4] - r_p2[4];
  554.   r_lstepx = (int)
  555.       ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
  556.   r_lstepy = (int)
  557.       ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
  558.  
  559.   t0 = r_p0[2] - r_p2[2];
  560.   t1 = r_p1[2] - r_p2[2];
  561.   r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
  562.       xstepdenominv);
  563.   r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
  564.       ystepdenominv);
  565.  
  566.   t0 = r_p0[3] - r_p2[3];
  567.   t1 = r_p1[3] - r_p2[3];
  568.   r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
  569.       xstepdenominv);
  570.   r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
  571.       ystepdenominv);
  572.  
  573.   t0 = r_p0[5] - r_p2[5];
  574.   t1 = r_p1[5] - r_p2[5];
  575.   r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
  576.       xstepdenominv);
  577.   r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
  578.       ystepdenominv);
  579.  
  580. #if id386
  581.   a_sstepxfrac = r_sstepx << 16;
  582.   a_tstepxfrac = r_tstepx << 16;
  583. #else
  584.   a_sstepxfrac = r_sstepx & 0xFFFF;
  585.   a_tstepxfrac = r_tstepx & 0xFFFF;
  586. #endif
  587.  
  588.   a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
  589. }
  590. #endif  // !id386/!M68KASM/!PPCASM
  591.  
  592.  
  593. #if 0
  594. byte gelmap[256];
  595. void InitGel (byte *palette)
  596. {
  597.   int   i;
  598.   int   r;
  599.  
  600.   for (i=0 ; i<256 ; i++)
  601.   {
  602. //    r = (palette[i*3]>>4);
  603.     r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
  604.     gelmap[i] = /* 64 */ 0 + r;
  605.   }
  606. }
  607. #endif
  608.  
  609.  
  610. #if !id386 && !defined(M68KASM) && !defined(PPCASM)
  611. /*
  612. ================
  613. D_PolysetDrawSpans8
  614. ================
  615. */
  616. void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
  617. {
  618.   int   lcount;
  619.   byte  *lpdest;
  620.   byte  *lptex;
  621.   int   lsfrac, ltfrac;
  622.   int   llight;
  623.   int   lzi;
  624.   short *lpz;
  625.  
  626.   do
  627.   {
  628.     lcount = d_aspancount - pspanpackage->count;
  629.  
  630.     errorterm += erroradjustup;
  631.     if (errorterm >= 0)
  632.     {
  633.       d_aspancount += d_countextrastep;
  634.       errorterm -= erroradjustdown;
  635.     }
  636.     else
  637.     {
  638.       d_aspancount += ubasestep;
  639.     }
  640.  
  641.     if (lcount)
  642.     {
  643.       lpdest = pspanpackage->pdest;
  644.       lptex = pspanpackage->ptex;
  645.       lpz = pspanpackage->pz;
  646.       lsfrac = pspanpackage->sfrac;
  647.       ltfrac = pspanpackage->tfrac;
  648.       llight = pspanpackage->light;
  649.       lzi = pspanpackage->zi;
  650.  
  651.       do
  652.       {
  653.         if ((lzi >> 16) >= *lpz)
  654.         {
  655.           *lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
  656. // gel mapping          *lpdest = gelmap[*lpdest];
  657.           *lpz = lzi >> 16;
  658.         }
  659.         lpdest++;
  660.         lzi += r_zistepx;
  661.         lpz++;
  662.         llight += r_lstepx;
  663.         lptex += a_ststepxwhole;
  664.         lsfrac += a_sstepxfrac;
  665.         lptex += lsfrac >> 16;
  666.         lsfrac &= 0xFFFF;
  667.         ltfrac += a_tstepxfrac;
  668.         if (ltfrac & 0x10000)
  669.         {
  670.           lptex += r_affinetridesc.skinwidth;
  671.           ltfrac &= 0xFFFF;
  672.         }
  673.       } while (--lcount);
  674.     }
  675.  
  676.     pspanpackage++;
  677.   } while (pspanpackage->count != -999999);
  678. }
  679. #endif  // !id386/!M68KASM/!PPCASM
  680.  
  681.  
  682. /*
  683. ================
  684. D_PolysetFillSpans8
  685. ================
  686. */
  687. void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
  688. {
  689.   int       color;
  690.  
  691. // FIXME: do z buffering
  692.  
  693.   color = d_aflatcolor++;
  694.  
  695.   while (1)
  696.   {
  697.     int   lcount;
  698.     byte  *lpdest;
  699.  
  700.     lcount = pspanpackage->count;
  701.  
  702.     if (lcount == -1)
  703.       return;
  704.  
  705.     if (lcount)
  706.     {
  707.       lpdest = pspanpackage->pdest;
  708.  
  709.       do
  710.       {
  711.         *lpdest++ = color;
  712.       } while (--lcount);
  713.     }
  714.  
  715.     pspanpackage++;
  716.   }
  717. }
  718.  
  719.  
  720. #ifndef M68KASM
  721. /*
  722. ================
  723. D_RasterizeAliasPolySmooth
  724. ================
  725. */
  726. void D_RasterizeAliasPolySmooth (void)
  727. {
  728.   int       initialleftheight, initialrightheight;
  729.   int       *plefttop, *prighttop, *pleftbottom, *prightbottom;
  730.   int       working_lstepx, originalcount;
  731.  
  732.   plefttop = pedgetable->pleftedgevert0;
  733.   prighttop = pedgetable->prightedgevert0;
  734.  
  735.   pleftbottom = pedgetable->pleftedgevert1;
  736.   prightbottom = pedgetable->prightedgevert1;
  737.  
  738.   initialleftheight = pleftbottom[1] - plefttop[1];
  739.   initialrightheight = prightbottom[1] - prighttop[1];
  740.  
  741. //
  742. // set the s, t, and light gradients, which are consistent across the triangle
  743. // because being a triangle, things are affine
  744. //
  745.   D_PolysetCalcGradients (r_affinetridesc.skinwidth);
  746.  
  747. //
  748. // rasterize the polygon
  749. //
  750.  
  751. //
  752. // scan out the top (and possibly only) part of the left edge
  753. //
  754.   d_pedgespanpackage = a_spans;
  755.  
  756.   ystart = plefttop[1];
  757.   d_aspancount = plefttop[0] - prighttop[0];
  758.  
  759.   d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
  760.       (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
  761. #if id386
  762.   d_sfrac = (plefttop[2] & 0xFFFF) << 16;
  763.   d_tfrac = (plefttop[3] & 0xFFFF) << 16;
  764. #else
  765.   d_sfrac = plefttop[2] & 0xFFFF;
  766.   d_tfrac = plefttop[3] & 0xFFFF;
  767. #endif
  768.   d_light = plefttop[4];
  769.   d_zi = plefttop[5];
  770.  
  771.   d_pdest = (byte *)d_viewbuffer +
  772.       ystart * screenwidth + plefttop[0];
  773.   d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
  774.  
  775.   if (initialleftheight == 1)
  776.   {
  777.     d_pedgespanpackage->pdest = d_pdest;
  778.     d_pedgespanpackage->pz = d_pz;
  779.     d_pedgespanpackage->count = d_aspancount;
  780.     d_pedgespanpackage->ptex = d_ptex;
  781.  
  782.     d_pedgespanpackage->sfrac = d_sfrac;
  783.     d_pedgespanpackage->tfrac = d_tfrac;
  784.  
  785.   // FIXME: need to clamp l, s, t, at both ends?
  786.     d_pedgespanpackage->light = d_light;
  787.     d_pedgespanpackage->zi = d_zi;
  788.  
  789.     d_pedgespanpackage++;
  790.   }
  791.   else
  792.   {
  793.     D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
  794.                 pleftbottom[0], pleftbottom[1]);
  795.  
  796.   #if id386
  797.     d_pzbasestep = (d_zwidth + ubasestep) << 1;
  798.     d_pzextrastep = d_pzbasestep + 2;
  799.   #else
  800.     d_pzbasestep = d_zwidth + ubasestep;
  801.     d_pzextrastep = d_pzbasestep + 1;
  802.   #endif
  803.  
  804.     d_pdestbasestep = screenwidth + ubasestep;
  805.     d_pdestextrastep = d_pdestbasestep + 1;
  806.  
  807.   // TODO: can reuse partial expressions here
  808.  
  809.   // for negative steps in x along left edge, bias toward overflow rather than
  810.   // underflow (sort of turning the floor () we did in the gradient calcs into
  811.   // ceil (), but plus a little bit)
  812.     if (ubasestep < 0)
  813.       working_lstepx = r_lstepx - 1;
  814.     else
  815.       working_lstepx = r_lstepx;
  816.  
  817.     d_countextrastep = ubasestep + 1;
  818.     d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
  819.         ((r_tstepy + r_tstepx * ubasestep) >> 16) *
  820.         r_affinetridesc.skinwidth;
  821.   #if id386
  822.     d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
  823.     d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
  824.   #else
  825.     d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
  826.     d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
  827.   #endif
  828.     d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
  829.     d_zibasestep = r_zistepy + r_zistepx * ubasestep;
  830.  
  831.     d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
  832.         ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
  833.         r_affinetridesc.skinwidth;
  834.   #if id386
  835.     d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
  836.     d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
  837.   #else
  838.     d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
  839.     d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
  840.   #endif
  841.     d_lightextrastep = d_lightbasestep + working_lstepx;
  842.     d_ziextrastep = d_zibasestep + r_zistepx;
  843.  
  844.     D_PolysetScanLeftEdge (initialleftheight);
  845.   }
  846.  
  847. //
  848. // scan out the bottom part of the left edge, if it exists
  849. //
  850.   if (pedgetable->numleftedges == 2)
  851.   {
  852.     int   height;
  853.  
  854.     plefttop = pleftbottom;
  855.     pleftbottom = pedgetable->pleftedgevert2;
  856.  
  857.     height = pleftbottom[1] - plefttop[1];
  858.  
  859. // TODO: make this a function; modularize this function in general
  860.  
  861.     ystart = plefttop[1];
  862.     d_aspancount = plefttop[0] - prighttop[0];
  863.     d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
  864.         (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
  865.     d_sfrac = 0;
  866.     d_tfrac = 0;
  867.     d_light = plefttop[4];
  868.     d_zi = plefttop[5];
  869.  
  870.     d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
  871.     d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
  872.  
  873.     if (height == 1)
  874.     {
  875.       d_pedgespanpackage->pdest = d_pdest;
  876.       d_pedgespanpackage->pz = d_pz;
  877.       d_pedgespanpackage->count = d_aspancount;
  878.       d_pedgespanpackage->ptex = d_ptex;
  879.  
  880.       d_pedgespanpackage->sfrac = d_sfrac;
  881.       d_pedgespanpackage->tfrac = d_tfrac;
  882.  
  883.     // FIXME: need to clamp l, s, t, at both ends?
  884.       d_pedgespanpackage->light = d_light;
  885.       d_pedgespanpackage->zi = d_zi;
  886.  
  887.       d_pedgespanpackage++;
  888.     }
  889.     else
  890.     {
  891.       D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
  892.                   pleftbottom[0], pleftbottom[1]);
  893.  
  894.       d_pdestbasestep = screenwidth + ubasestep;
  895.       d_pdestextrastep = d_pdestbasestep + 1;
  896.  
  897.   #if id386
  898.       d_pzbasestep = (d_zwidth + ubasestep) << 1;
  899.       d_pzextrastep = d_pzbasestep + 2;
  900.   #else
  901.       d_pzbasestep = d_zwidth + ubasestep;
  902.       d_pzextrastep = d_pzbasestep + 1;
  903.   #endif
  904.  
  905.       if (ubasestep < 0)
  906.         working_lstepx = r_lstepx - 1;
  907.       else
  908.         working_lstepx = r_lstepx;
  909.  
  910.       d_countextrastep = ubasestep + 1;
  911.       d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
  912.           ((r_tstepy + r_tstepx * ubasestep) >> 16) *
  913.           r_affinetridesc.skinwidth;
  914.   #if id386
  915.       d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
  916.       d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
  917.   #else
  918.       d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
  919.       d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
  920.   #endif
  921.       d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
  922.       d_zibasestep = r_zistepy + r_zistepx * ubasestep;
  923.  
  924.       d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
  925.           ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
  926.           r_affinetridesc.skinwidth;
  927.   #if id386
  928.       d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
  929.       d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
  930.   #else
  931.       d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
  932.       d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
  933.   #endif
  934.       d_lightextrastep = d_lightbasestep + working_lstepx;
  935.       d_ziextrastep = d_zibasestep + r_zistepx;
  936.  
  937.       D_PolysetScanLeftEdge (height);
  938.     }
  939.   }
  940.  
  941. // scan out the top (and possibly only) part of the right edge, updating the
  942. // count field
  943.   d_pedgespanpackage = a_spans;
  944.  
  945.   D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
  946.               prightbottom[0], prightbottom[1]);
  947.   d_aspancount = 0;
  948.   d_countextrastep = ubasestep + 1;
  949.   originalcount = a_spans[initialrightheight].count;
  950.   a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
  951.   D_PolysetDrawSpans8 (a_spans);
  952.  
  953. // scan out the bottom part of the right edge, if it exists
  954.   if (pedgetable->numrightedges == 2)
  955.   {
  956.     int       height;
  957.     spanpackage_t *pstart;
  958.  
  959.     pstart = a_spans + initialrightheight;
  960.     pstart->count = originalcount;
  961.  
  962.     d_aspancount = prightbottom[0] - prighttop[0];
  963.  
  964.     prighttop = prightbottom;
  965.     prightbottom = pedgetable->prightedgevert2;
  966.  
  967.     height = prightbottom[1] - prighttop[1];
  968.  
  969.     D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
  970.                 prightbottom[0], prightbottom[1]);
  971.  
  972.     d_countextrastep = ubasestep + 1;
  973.     a_spans[initialrightheight + height].count = -999999;
  974.                       // mark end of the spanpackages
  975.     D_PolysetDrawSpans8 (pstart);
  976.   }
  977. }
  978.  
  979.  
  980. /*
  981. ================
  982. D_PolysetSetEdgeTable
  983. ================
  984. */
  985. void D_PolysetSetEdgeTable (void)
  986. {
  987.   int     edgetableindex;
  988.  
  989.   edgetableindex = 0; // assume the vertices are already in
  990.             //  top to bottom order
  991.  
  992. //
  993. // determine which edges are right & left, and the order in which
  994. // to rasterize them
  995. //
  996.   if (r_p0[1] >= r_p1[1])
  997.   {
  998.     if (r_p0[1] == r_p1[1])
  999.     {
  1000.       if (r_p0[1] < r_p2[1])
  1001.         pedgetable = &edgetables[2];
  1002.       else
  1003.         pedgetable = &edgetables[5];
  1004.  
  1005.       return;
  1006.     }
  1007.     else
  1008.     {
  1009.       edgetableindex = 1;
  1010.     }
  1011.   }
  1012.  
  1013.   if (r_p0[1] == r_p2[1])
  1014.   {
  1015.     if (edgetableindex)
  1016.       pedgetable = &edgetables[8];
  1017.     else
  1018.       pedgetable = &edgetables[9];
  1019.  
  1020.     return;
  1021.   }
  1022.   else if (r_p1[1] == r_p2[1])
  1023.   {
  1024.     if (edgetableindex)
  1025.       pedgetable = &edgetables[10];
  1026.     else
  1027.       pedgetable = &edgetables[11];
  1028.  
  1029.     return;
  1030.   }
  1031.  
  1032.   if (r_p0[1] > r_p2[1])
  1033.     edgetableindex += 2;
  1034.  
  1035.   if (r_p1[1] > r_p2[1])
  1036.     edgetableindex += 4;
  1037.  
  1038.   pedgetable = &edgetables[edgetableindex];
  1039. }
  1040. #endif // M68KASM
  1041.  
  1042.  
  1043. #if 0
  1044.  
  1045. void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
  1046. {
  1047.   int   d;
  1048.   int   new[6];
  1049.   int   ofs;
  1050.   
  1051.   d = lp2[0] - lp1[0];
  1052.   if (d < -1 || d > 1)
  1053.     goto split;
  1054.   d = lp2[1] - lp1[1];
  1055.   if (d < -1 || d > 1)
  1056.     goto split;
  1057.  
  1058.   return; // line is completed
  1059.  
  1060. split:
  1061. // split this edge
  1062.   new[0] = (lp1[0] + lp2[0]) >> 1;
  1063.   new[1] = (lp1[1] + lp2[1]) >> 1;
  1064.   new[5] = (lp1[5] + lp2[5]) >> 1;
  1065.   new[2] = (lp1[2] + lp2[2]) >> 1;
  1066.   new[3] = (lp1[3] + lp2[3]) >> 1;
  1067.   new[4] = (lp1[4] + lp2[4]) >> 1;
  1068.  
  1069. // draw the point
  1070.   ofs = d_scantable[new[1]] + new[0];
  1071.   if (new[5] > d_pzbuffer[ofs])
  1072.   {
  1073.     int   pix;
  1074.     
  1075.     d_pzbuffer[ofs] = new[5];
  1076.     pix = skintable[new[3]>>16][new[2]>>16];
  1077. //    pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
  1078.     d_viewbuffer[ofs] = pix;
  1079.   }
  1080.  
  1081. // recursively continue
  1082.   D_PolysetRecursiveDrawLine (lp1, new);
  1083.   D_PolysetRecursiveDrawLine (new, lp2);
  1084. }
  1085.  
  1086. void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
  1087. {
  1088.   int   d;
  1089.   int   new[4];
  1090.   
  1091.   d = lp2[0] - lp1[0];
  1092.   if (d < -1 || d > 1)
  1093.     goto split;
  1094.   d = lp2[1] - lp1[1];
  1095.   if (d < -1 || d > 1)
  1096.     goto split;
  1097.   return;
  1098.  
  1099. split:
  1100. // split this edge
  1101.   new[0] = (lp1[0] + lp2[0]) >> 1;
  1102.   new[1] = (lp1[1] + lp2[1]) >> 1;
  1103.   new[5] = (lp1[5] + lp2[5]) >> 1;
  1104.   new[2] = (lp1[2] + lp2[2]) >> 1;
  1105.   new[3] = (lp1[3] + lp2[3]) >> 1;
  1106.   new[4] = (lp1[4] + lp2[4]) >> 1;
  1107.  
  1108.   D_PolysetRecursiveDrawLine (new, lp3);
  1109.  
  1110. // recursively continue
  1111.   D_PolysetRecursiveTriangle (lp1, new, lp3);
  1112.   D_PolysetRecursiveTriangle (new, lp2, lp3);
  1113. }
  1114.  
  1115. #endif
  1116.  
  1117.