ref: eb498d4e7706fa6f99d364ee96f8da2533d99a21
dir: /d_polyse.c/
#include "quakedef.h"
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct {
pixel_t *pdest, *ptex;
uzint *pz;
int count, sfrac, tfrac, zi, light[3];
} spanpackage_t;
typedef struct {
finalvert_t *pleftedgevert0;
finalvert_t *pleftedgevert1;
finalvert_t *pleftedgevert2;
finalvert_t *prightedgevert0;
finalvert_t *prightedgevert1;
finalvert_t *prightedgevert2;
int isflattop;
int numleftedges;
int numrightedges;
} edgetable;
// TODO: put in span spilling to shrink list size
// !!! if this is changed, it must be changed in d_polysa.s too !!!
static spanpackage_t a_spans[MAXHEIGHT+1];
// 1 extra for spanpackage that marks end
static finalvert_t r_p0, r_p1, r_p2;
static pixel_t *d_pcolormap;
static int d_xdenom;
static edgetable *pedgetable;
static edgetable edgetables[12] = {
{&r_p0, &r_p2, nil, &r_p0, &r_p1, &r_p2, 0, 1, 2},
{&r_p1, &r_p0, &r_p2, &r_p1, &r_p2, nil, 0, 2, 1},
{&r_p0, &r_p2, nil, &r_p1, &r_p2, nil, 1, 1, 1},
{&r_p1, &r_p0, nil, &r_p1, &r_p2, &r_p0, 0, 1, 2},
{&r_p0, &r_p2, &r_p1, &r_p0, &r_p1, nil, 0, 2, 1},
{&r_p2, &r_p1, nil, &r_p2, &r_p0, nil, 0, 1, 1},
{&r_p2, &r_p1, nil, &r_p2, &r_p0, &r_p1, 0, 1, 2},
{&r_p2, &r_p1, &r_p0, &r_p2, &r_p0, nil, 0, 2, 1},
{&r_p1, &r_p0, nil, &r_p1, &r_p2, nil, 0, 1, 1},
{&r_p2, &r_p1, nil, &r_p0, &r_p1, nil, 1, 1, 1},
{&r_p1, &r_p0, nil, &r_p2, &r_p0, nil, 1, 1, 1},
{&r_p0, &r_p2, nil, &r_p0, &r_p1, nil, 0, 1, 1},
};
// FIXME: some of these can become statics
static int a_sstepxfrac, a_tstepxfrac, r_lstepx[3], a_ststepxwhole;
static int r_sstepx, r_tstepx, r_lstepy[3], r_sstepy, r_tstepy;
static int r_zistepx, r_zistepy;
static int d_aspancount, d_countextrastep;
static spanpackage_t *d_pedgespanpackage;
static int ystart;
static pixel_t *d_pdest, *d_ptex;
static uzint *d_pz;
static int d_sfrac, d_tfrac, d_light[3], d_zi;
static int d_ptexextrastep, d_sfracextrastep;
static int d_lightextrastep[3], d_pdestextrastep, d_tfracextrastep;
static int d_lightbasestep[3], d_pdestbasestep, d_ptexbasestep;
static int d_sfracbasestep, d_tfracbasestep;
static int d_ziextrastep, d_zibasestep;
static int d_pzextrastep, d_pzbasestep;
static int ubasestep, errorterm, erroradjustup, erroradjustdown;
typedef struct {
int quotient;
int remainder;
} adivtab_t;
static const adivtab_t adivtab[32*32] = {
#include "adivtab.h"
};
static pixel_t *skintable[MAX_LBM_HEIGHT];
static pixel_t *skinstart;
int skinwidth;
void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage, pixel_t *colormap, byte alpha);
void D_PolysetCalcGradients (int skinwidth);
void D_DrawSubdiv (pixel_t *colormap);
void D_DrawNonSubdiv (void);
void D_PolysetRecursiveTriangle (finalvert_t *p1, finalvert_t *p2, finalvert_t *p3, byte alpha, int l[3]);
void D_PolysetSetEdgeTable (void);
void D_RasterizeAliasPolySmooth (void);
void D_PolysetScanLeftEdge (int height);
/*
================
D_PolysetDraw
================
*/
void D_PolysetDraw (pixel_t *colormap)
{
if (r_affinetridesc.drawtype)
{
D_DrawSubdiv (colormap);
}
else
{
D_DrawNonSubdiv ();
}
}
/*
================
D_PolysetDrawFinalVerts
================
*/
void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts, pixel_t *colormap, byte alpha)
{
int i, z;
uzint *zbuf;
for(i = 0 ; i < numverts; i++, fv++){
// valid triangle coordinates for filling can include the bottom and
// right clip edges, due to the fill rule; these shouldn't be drawn
if (fv->u < r_refdef.vrectright && fv->v < r_refdef.vrectbottom){
z = fv->zi;
zbuf = zspantable[fv->v] + fv->u;
if(z >= *zbuf){
pixel_t p = addlight(skintable[fv->t >> 16][fv->s >> 16], fv->l[0], fv->l[1], fv->l[2]);
int n = d_scantable[fv->v] + fv->u;
if(r_drawflags & DRAW_BLEND){
d_viewbuffer[n] = blendalpha(p, d_viewbuffer[n], alpha, z);
}else{
d_viewbuffer[n] = p;
*zbuf = z;
}
}
}
}
}
/*
================
D_DrawSubdiv
================
*/
void D_DrawSubdiv (pixel_t *colormap)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
for (i=0 ; i<lnumtriangles ; i++)
{
index0 = pfv + ptri[i].vertindex[0];
index1 = pfv + ptri[i].vertindex[1];
index2 = pfv + ptri[i].vertindex[2];
if (((index0->v - index1->v) *
(index0->u - index2->u) -
(index0->u - index1->u) *
(index0->v - index2->v)) >= 0)
{
continue;
}
d_pcolormap = colormap + (index0->l[0] & 0xFF00);
if (ptri[i].facesfront)
{
D_PolysetRecursiveTriangle(index0, index1, index2, currententity->alpha, index0->l);
}
else
{
int s0, s1, s2;
s0 = index0->s;
s1 = index1->s;
s2 = index2->s;
if (index0->flags & ALIAS_ONSEAM)
index0->s += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
index1->s += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
index2->s += r_affinetridesc.seamfixupX16;
D_PolysetRecursiveTriangle(index0, index1, index2, currententity->alpha, index0->l);
index0->s = s0;
index1->s = s1;
index2->s = s2;
}
}
}
/*
================
D_DrawNonSubdiv
================
*/
void D_DrawNonSubdiv (void)
{
mtriangle_t *ptri;
finalvert_t *pfv, *index0, *index1, *index2;
int i;
int lnumtriangles;
pfv = r_affinetridesc.pfinalverts;
ptri = r_affinetridesc.ptriangles;
lnumtriangles = r_affinetridesc.numtriangles;
for (i=0 ; i<lnumtriangles ; i++, ptri++)
{
index0 = pfv + ptri->vertindex[0];
index1 = pfv + ptri->vertindex[1];
index2 = pfv + ptri->vertindex[2];
d_xdenom = (index0->v - index1->v) * (index0->u - index2->u) -
(index0->u - index1->u) * (index0->v - index2->v);
if(d_xdenom >= 0)
continue;
memmove(r_p0.x, index0->x, sizeof(r_p0.x));
memmove(r_p1.x, index1->x, sizeof(r_p1.x));
memmove(r_p2.x, index2->x, sizeof(r_p2.x));
if (!ptri->facesfront)
{
if (index0->flags & ALIAS_ONSEAM)
r_p0.s += r_affinetridesc.seamfixupX16;
if (index1->flags & ALIAS_ONSEAM)
r_p1.s += r_affinetridesc.seamfixupX16;
if (index2->flags & ALIAS_ONSEAM)
r_p2.s += r_affinetridesc.seamfixupX16;
}
D_PolysetSetEdgeTable();
D_RasterizeAliasPolySmooth();
}
}
/*
================
D_PolysetRecursiveTriangle
================
*/
void D_PolysetRecursiveTriangle (finalvert_t *lp1, finalvert_t *lp2, finalvert_t *lp3, byte alpha, int l[3])
{
finalvert_t new, *temp;
uzint *zbuf;
int d, z;
d = lp2->u - lp1->u;
if (d < -1 || d > 1)
goto split;
d = lp2->v - lp1->v;
if (d < -1 || d > 1)
goto split;
d = lp3->u - lp2->u;
if (d < -1 || d > 1)
goto split2;
d = lp3->v - lp2->v;
if (d < -1 || d > 1)
goto split2;
d = lp1->u - lp3->u;
if (d < -1 || d > 1)
goto split3;
d = lp1->v - lp3->v;
if (d < -1 || d > 1)
{
split3:
temp = lp1;
lp1 = lp3;
lp3 = lp2;
lp2 = temp;
goto split;
}
return; // entire tri is filled
split2:
temp = lp1;
lp1 = lp2;
lp2 = lp3;
lp3 = temp;
split:
// split this edge
new.u = (lp1->u + lp2->u) >> 1;
new.v = (lp1->v + lp2->v) >> 1;
new.s = (lp1->s + lp2->s) >> 1;
new.t = (lp1->t + lp2->t) >> 1;
new.zi = (lp1->zi + lp2->zi) >> 1;
// draw the point if splitting a leading edge
if (lp2->v > lp1->v)
goto nodraw;
if ((lp2->v == lp1->v) && (lp2->u < lp1->u))
goto nodraw;
z = new.zi;
zbuf = zspantable[new.v] + new.u;
if (z >= *zbuf){
pixel_t p = addlight(skintable[new.t >> 16][new.s >> 16], l[0], l[1], l[2]);
int n = d_scantable[new.v] + new.u;
if(r_drawflags & DRAW_BLEND){
d_viewbuffer[n] = blendalpha(p, d_viewbuffer[n], alpha, z);
}else{
d_viewbuffer[n] = p;
*zbuf = z;
}
}
nodraw:
// recursively continue
D_PolysetRecursiveTriangle(lp3, lp1, &new, alpha, l);
D_PolysetRecursiveTriangle(lp3, &new, lp2, alpha, l);
}
/*
================
D_PolysetUpdateTables
================
*/
void D_PolysetUpdateTables (void)
{
int i;
pixel_t *s;
if (r_affinetridesc.skinwidth != skinwidth ||
r_affinetridesc.pskin != skinstart)
{
skinwidth = r_affinetridesc.skinwidth;
skinstart = r_affinetridesc.pskin;
s = skinstart;
for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
skintable[i] = s;
}
}
/*
===================
D_PolysetScanLeftEdge
====================
*/
void D_PolysetScanLeftEdge (int height)
{
do
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light[0] = d_light[0];
d_pedgespanpackage->light[1] = d_light[1];
d_pedgespanpackage->light[2] = d_light[2];
d_pedgespanpackage->zi = d_zi;
d_pedgespanpackage++;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_pdest += d_pdestextrastep;
d_pz += d_pzextrastep;
d_aspancount += d_countextrastep;
d_ptex += d_ptexextrastep;
d_sfrac += d_sfracextrastep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracextrastep;
if (d_tfrac & 0x10000)
{
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light[0] += d_lightextrastep[0];
d_light[1] += d_lightextrastep[1];
d_light[2] += d_lightextrastep[2];
d_zi += d_ziextrastep;
errorterm -= erroradjustdown;
}
else
{
d_pdest += d_pdestbasestep;
d_pz += d_pzbasestep;
d_aspancount += ubasestep;
d_ptex += d_ptexbasestep;
d_sfrac += d_sfracbasestep;
d_ptex += d_sfrac >> 16;
d_sfrac &= 0xFFFF;
d_tfrac += d_tfracbasestep;
if (d_tfrac & 0x10000)
{
d_ptex += r_affinetridesc.skinwidth;
d_tfrac &= 0xFFFF;
}
d_light[0] += d_lightbasestep[0];
d_light[1] += d_lightbasestep[1];
d_light[2] += d_lightbasestep[2];
d_zi += d_zibasestep;
}
} while (--height);
}
/*
===================
D_PolysetSetUpForLineScan
====================
*/
void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
fixed8_t endvertu, fixed8_t endvertv)
{
double dm, dn;
int tm, tn, n;
// TODO: implement x86 version
errorterm = -1;
tm = endvertu - startvertu;
tn = endvertv - startvertv;
if (((tm <= 16) && (tm >= -15)) &&
((tn <= 16) && (tn >= -15)))
{
n = ((tm+15) << 5) + (tn+15);
ubasestep = adivtab[n].quotient;
erroradjustup = adivtab[n].remainder;
erroradjustdown = tn;
}
else
{
dm = (double)tm;
dn = (double)tn;
FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
erroradjustdown = dn;
}
}
/*
================
D_PolysetCalcGradients
================
*/
void D_PolysetCalcGradients (int skinwidth)
{
float xstepdenominv, ystepdenominv, t0, t1;
float p0v_minus_p2v, p1v_minus_p2v, p0u_minus_p2u, p1u_minus_p2u;
int i;
p0u_minus_p2u = r_p0.u - r_p2.u;
p0v_minus_p2v = r_p0.v - r_p2.v;
p1u_minus_p2u = r_p1.u - r_p2.u;
p1v_minus_p2v = r_p1.v - r_p2.v;
xstepdenominv = 1.0 / (float)d_xdenom;
ystepdenominv = -xstepdenominv;
// ceil () for light so positive steps are exaggerated, negative steps
// diminished, pushing us away from underflow toward overflow. Underflow is
// very visible, overflow is very unlikely, because of ambient lighting
for(i = 0; i < 3; i++){
t0 = r_p0.l[i] - r_p2.l[i];
t1 = r_p1.l[i] - r_p2.l[i];
r_lstepx[i] = (int)ceil((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
r_lstepy[i] = (int)ceil((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
}
t0 = r_p0.s - r_p2.s;
t1 = r_p1.s - r_p2.s;
r_sstepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
r_sstepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
t0 = r_p0.t - r_p2.t;
t1 = r_p1.t - r_p2.t;
r_tstepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
r_tstepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
t0 = r_p0.zi - r_p2.zi;
t1 = r_p1.zi - r_p2.zi;
r_zistepx = (int)((t1 * p0v_minus_p2v - t0 * p1v_minus_p2v) * xstepdenominv);
r_zistepy = (int)((t1 * p0u_minus_p2u - t0 * p1u_minus_p2u) * ystepdenominv);
a_sstepxfrac = r_sstepx & 0xFFFF;
a_tstepxfrac = r_tstepx & 0xFFFF;
a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
}
/*
================
D_PolysetDrawSpans8
================
*/
void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage, pixel_t *colormap, byte alpha)
{
int lcount;
pixel_t *lpdest, *lptex;
int lsfrac, ltfrac;
int llight[3];
int lzi;
uzint *lpz;
do
{
lcount = d_aspancount - pspanpackage->count;
errorterm += erroradjustup;
if (errorterm >= 0)
{
d_aspancount += d_countextrastep;
errorterm -= erroradjustdown;
}
else
{
d_aspancount += ubasestep;
}
if (lcount)
{
lpdest = pspanpackage->pdest;
lptex = pspanpackage->ptex;
lpz = pspanpackage->pz;
lsfrac = pspanpackage->sfrac;
ltfrac = pspanpackage->tfrac;
llight[0] = pspanpackage->light[0];
llight[1] = pspanpackage->light[1];
llight[2] = pspanpackage->light[2];
lzi = pspanpackage->zi;
do
{
if (lzi >= *lpz){
pixel_t p = addlight(*lptex, llight[0], llight[1], llight[2]);
if(r_drawflags & DRAW_BLEND){
*lpdest = blendalpha(
p,
*lpdest,
alpha,
lzi
);
}else{
*lpdest = p;
// gel mapping *lpdest = gelmap[*lpdest];
*lpz = lzi;
}
}
lpdest++;
lzi += r_zistepx;
lpz++;
llight[0] += r_lstepx[0];
llight[1] += r_lstepx[1];
llight[2] += r_lstepx[2];
lptex += a_ststepxwhole;
lsfrac += a_sstepxfrac;
lptex += lsfrac >> 16;
lsfrac &= 0xFFFF;
ltfrac += a_tstepxfrac;
if (ltfrac & 0x10000)
{
lptex += r_affinetridesc.skinwidth;
ltfrac &= 0xFFFF;
}
} while (--lcount);
}
pspanpackage++;
} while (pspanpackage->count != Q_MININT);
}
/*
================
D_RasterizeAliasPolySmooth
================
*/
void D_RasterizeAliasPolySmooth (void)
{
int initialleftheight, initialrightheight;
finalvert_t *plefttop, *prighttop, *pleftbottom, *prightbottom;
int working_lstepx[3], originalcount;
plefttop = pedgetable->pleftedgevert0;
prighttop = pedgetable->prightedgevert0;
pleftbottom = pedgetable->pleftedgevert1;
prightbottom = pedgetable->prightedgevert1;
initialleftheight = pleftbottom->v - plefttop->v;
initialrightheight = prightbottom->v - prighttop->v;
assert(initialleftheight <= MAXHEIGHT);
// set the s, t, and light gradients, which are consistent across the triangle
// because being a triangle, things are affine
D_PolysetCalcGradients (r_affinetridesc.skinwidth);
// rasterize the polygon
// scan out the top (and possibly only) part of the left edge
d_pedgespanpackage = a_spans;
ystart = plefttop->v;
d_aspancount = plefttop->u - prighttop->u;
d_ptex = r_affinetridesc.pskin + (plefttop->s >> 16) +
(plefttop->t >> 16) * r_affinetridesc.skinwidth;
d_sfrac = plefttop->s & 0xFFFF;
d_tfrac = plefttop->t & 0xFFFF;
d_zi = plefttop->zi;
d_light[0] = plefttop->l[0];
d_light[1] = plefttop->l[1];
d_light[2] = plefttop->l[2];
d_pdest = d_viewbuffer + ystart * screenwidth + plefttop->u;
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop->u;
if (initialleftheight == 1)
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light[0] = d_light[0];
d_pedgespanpackage->light[1] = d_light[1];
d_pedgespanpackage->light[2] = d_light[2];
d_pedgespanpackage->zi = d_zi;
d_pedgespanpackage++;
}
else
{
D_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
pleftbottom->u, pleftbottom->v);
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
// TODO: can reuse partial expressions here
// for negative steps in x along left edge, bias toward overflow rather than
// underflow (sort of turning the floor () we did in the gradient calcs into
// ceil (), but plus a little bit)
working_lstepx[0] = r_lstepx[0];
working_lstepx[1] = r_lstepx[1];
working_lstepx[2] = r_lstepx[2];
if(ubasestep < 0){
working_lstepx[0] -= 1;
working_lstepx[1] -= 1;
working_lstepx[2] -= 1;
}
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
d_lightbasestep[0] = r_lstepy[0] + working_lstepx[0] * ubasestep;
d_lightbasestep[1] = r_lstepy[1] + working_lstepx[1] * ubasestep;
d_lightbasestep[2] = r_lstepy[2] + working_lstepx[2] * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
d_lightextrastep[0] = d_lightbasestep[0] + working_lstepx[0];
d_lightextrastep[1] = d_lightbasestep[1] + working_lstepx[1];
d_lightextrastep[2] = d_lightbasestep[2] + working_lstepx[2];
d_ziextrastep = d_zibasestep + r_zistepx;
D_PolysetScanLeftEdge (initialleftheight);
}
// scan out the bottom part of the left edge, if it exists
if (pedgetable->numleftedges == 2)
{
int height;
plefttop = pleftbottom;
pleftbottom = pedgetable->pleftedgevert2;
height = pleftbottom->v - plefttop->v;
// TODO: make this a function; modularize this function in general
ystart = plefttop->v;
d_aspancount = plefttop->u - prighttop->u;
d_ptex = r_affinetridesc.pskin + (plefttop->s >> 16) +
(plefttop->t >> 16) * r_affinetridesc.skinwidth;
d_sfrac = 0;
d_tfrac = 0;
d_zi = plefttop->zi;
d_light[0] = plefttop->l[0];
d_light[1] = plefttop->l[1];
d_light[2] = plefttop->l[2];
d_pdest = d_viewbuffer + ystart * screenwidth + plefttop->u;
d_pz = d_pzbuffer + ystart * d_zwidth + plefttop->u;
if (height == 1)
{
d_pedgespanpackage->pdest = d_pdest;
d_pedgespanpackage->pz = d_pz;
d_pedgespanpackage->count = d_aspancount;
d_pedgespanpackage->ptex = d_ptex;
d_pedgespanpackage->sfrac = d_sfrac;
d_pedgespanpackage->tfrac = d_tfrac;
// FIXME: need to clamp l, s, t, at both ends?
d_pedgespanpackage->light[0] = d_light[0];
d_pedgespanpackage->light[1] = d_light[1];
d_pedgespanpackage->light[2] = d_light[2];
d_pedgespanpackage->zi = d_zi;
}
else
{
D_PolysetSetUpForLineScan(plefttop->u, plefttop->v,
pleftbottom->u, pleftbottom->v);
d_pdestbasestep = screenwidth + ubasestep;
d_pdestextrastep = d_pdestbasestep + 1;
d_pzbasestep = d_zwidth + ubasestep;
d_pzextrastep = d_pzbasestep + 1;
if (ubasestep < 0){
working_lstepx[0] = r_lstepx[0] - 1;
working_lstepx[1] = r_lstepx[1] - 1;
working_lstepx[2] = r_lstepx[2] - 1;
}else{
working_lstepx[0] = r_lstepx[0];
working_lstepx[1] = r_lstepx[1];
working_lstepx[2] = r_lstepx[2];
}
d_countextrastep = ubasestep + 1;
d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
((r_tstepy + r_tstepx * ubasestep) >> 16) *
r_affinetridesc.skinwidth;
d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
d_lightbasestep[0] = r_lstepy[0] + working_lstepx[0] * ubasestep;
d_lightbasestep[1] = r_lstepy[1] + working_lstepx[1] * ubasestep;
d_lightbasestep[2] = r_lstepy[2] + working_lstepx[2] * ubasestep;
d_zibasestep = r_zistepy + r_zistepx * ubasestep;
d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
r_affinetridesc.skinwidth;
d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
d_lightextrastep[0] = d_lightbasestep[0] + working_lstepx[0];
d_lightextrastep[1] = d_lightbasestep[1] + working_lstepx[1];
d_lightextrastep[2] = d_lightbasestep[2] + working_lstepx[2];
d_ziextrastep = d_zibasestep + r_zistepx;
D_PolysetScanLeftEdge (height);
}
}
// scan out the top (and possibly only) part of the right edge, updating the
// count field
d_pedgespanpackage = a_spans;
D_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
prightbottom->u, prightbottom->v);
d_aspancount = 0;
d_countextrastep = ubasestep + 1;
originalcount = a_spans[initialrightheight].count;
a_spans[initialrightheight].count = Q_MININT; // mark end of the spanpackages
D_PolysetDrawSpans8 (a_spans, currententity->colormap, currententity->alpha);
// scan out the bottom part of the right edge, if it exists
if (pedgetable->numrightedges == 2)
{
int height;
spanpackage_t *pstart;
pstart = a_spans + initialrightheight;
pstart->count = originalcount;
d_aspancount = prightbottom->u - prighttop->u;
prighttop = prightbottom;
prightbottom = pedgetable->prightedgevert2;
height = prightbottom->v - prighttop->v;
D_PolysetSetUpForLineScan(prighttop->u, prighttop->v,
prightbottom->u, prightbottom->v);
d_countextrastep = ubasestep + 1;
a_spans[initialrightheight + height].count = Q_MININT;
// mark end of the spanpackages
D_PolysetDrawSpans8 (pstart, currententity->colormap, currententity->alpha);
}
}
/*
================
D_PolysetSetEdgeTable
================
*/
void D_PolysetSetEdgeTable (void)
{
int edgetableindex;
edgetableindex = 0; // assume the vertices are already in
// top to bottom order
// determine which edges are right & left, and the order in which
// to rasterize them
if(r_p0.v >= r_p1.v){
if(r_p0.v == r_p1.v){
pedgetable = &edgetables[r_p0.v < r_p2.v ? 2 : 5];
return;
}
edgetableindex = 1;
}
if(r_p0.v == r_p2.v){
pedgetable = &edgetables[edgetableindex ? 8 : 9];
return;
}
if(r_p1.v == r_p2.v){
pedgetable = &edgetables[edgetableindex ? 10 : 11];
return;
}
if(r_p0.v > r_p2.v)
edgetableindex += 2;
if(r_p1.v > r_p2.v)
edgetableindex += 4;
pedgetable = &edgetables[edgetableindex];
}