Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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