📄 r_poly.c
字号:
*/
void R_DrawSpanlet66Stipple( void )
{
unsigned btemp;
byte *pdest = s_spanletvars.pdest;
short *pz = s_spanletvars.pz;
int izi = s_spanletvars.izi;
s_spanletvars.pdest += s_spanletvars.spancount;
s_spanletvars.pz += s_spanletvars.spancount;
if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE )
s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS;
else
s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep;
if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) )
{
if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) )
{
izi += s_spanletvars.izistep;
s_spanletvars.s += s_spanletvars.sstep;
s_spanletvars.t += s_spanletvars.tstep;
pdest++;
pz++;
s_spanletvars.spancount--;
}
s_spanletvars.sstep *= 2;
s_spanletvars.tstep *= 2;
while ( s_spanletvars.spancount > 0 )
{
unsigned s = s_spanletvars.s >> 16;
unsigned t = s_spanletvars.t >> 16;
btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
if ( btemp != 255 )
{
if ( *pz <= ( izi >> 16 ) )
*pdest = btemp;
}
izi += s_spanletvars.izistep_times_2;
s_spanletvars.s += s_spanletvars.sstep;
s_spanletvars.t += s_spanletvars.tstep;
pdest += 2;
pz += 2;
s_spanletvars.spancount -= 2;
}
}
else
{
while ( s_spanletvars.spancount > 0 )
{
unsigned s = s_spanletvars.s >> 16;
unsigned t = s_spanletvars.t >> 16;
btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) );
if ( btemp != 255 )
{
if ( *pz <= ( izi >> 16 ) )
*pdest = btemp;
}
izi += s_spanletvars.izistep;
s_spanletvars.s += s_spanletvars.sstep;
s_spanletvars.t += s_spanletvars.tstep;
pdest++;
pz++;
s_spanletvars.spancount--;
}
}
}
/*
** R_ClipPolyFace
**
** Clips the winding at clip_verts[clip_current] and changes clip_current
** Throws out the back side
*/
int R_ClipPolyFace (int nump, clipplane_t *pclipplane)
{
int i, outcount;
float dists[MAXWORKINGVERTS+3];
float frac, clipdist, *pclipnormal;
float *in, *instep, *outstep, *vert2;
clipdist = pclipplane->dist;
pclipnormal = pclipplane->normal;
// calc dists
if (clip_current)
{
in = r_clip_verts[1][0];
outstep = r_clip_verts[0][0];
clip_current = 0;
}
else
{
in = r_clip_verts[0][0];
outstep = r_clip_verts[1][0];
clip_current = 1;
}
instep = in;
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
{
dists[i] = DotProduct (instep, pclipnormal) - clipdist;
}
// handle wraparound case
dists[nump] = dists[0];
memcpy (instep, in, sizeof (vec5_t));
// clip the winding
instep = in;
outcount = 0;
for (i=0 ; i<nump ; i++, instep += sizeof (vec5_t) / sizeof (float))
{
if (dists[i] >= 0)
{
memcpy (outstep, instep, sizeof (vec5_t));
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
if (dists[i] == 0 || dists[i+1] == 0)
continue;
if ( (dists[i] > 0) == (dists[i+1] > 0) )
continue;
// split it into a new vertex
frac = dists[i] / (dists[i] - dists[i+1]);
vert2 = instep + sizeof (vec5_t) / sizeof (float);
outstep[0] = instep[0] + frac*(vert2[0] - instep[0]);
outstep[1] = instep[1] + frac*(vert2[1] - instep[1]);
outstep[2] = instep[2] + frac*(vert2[2] - instep[2]);
outstep[3] = instep[3] + frac*(vert2[3] - instep[3]);
outstep[4] = instep[4] + frac*(vert2[4] - instep[4]);
outstep += sizeof (vec5_t) / sizeof (float);
outcount++;
}
return outcount;
}
/*
** R_PolygonDrawSpans
*/
// PGM - iswater was qboolean. changed to allow passing more flags
void R_PolygonDrawSpans(espan_t *pspan, int iswater )
{
int count;
fixed16_t snext, tnext;
float sdivz, tdivz, zi, z, du, dv, spancountminus1;
float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu;
s_spanletvars.pbase = cacheblock;
//PGM
if ( iswater & SURF_WARP)
r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
else if (iswater & SURF_FLOWING)
r_turb_turb = blanktable;
//PGM
sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE;
tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE;
zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE;
// we count on FP exceptions being turned off to avoid range problems
s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000);
s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2;
s_spanletvars.pz = 0;
do
{
s_spanletvars.pdest = (byte *)d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u;
s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
s_spanletvars.u = pspan->u;
s_spanletvars.v = pspan->v;
count = pspan->count;
if (count <= 0)
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du = (float)pspan->u;
dv = (float)pspan->v;
sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000);
s_spanletvars.s = (int)(sdivz * z) + sadjust;
s_spanletvars.t = (int)(tdivz * z) + tadjust;
if ( !iswater )
{
if (s_spanletvars.s > bbextents)
s_spanletvars.s = bbextents;
else if (s_spanletvars.s < 0)
s_spanletvars.s = 0;
if (s_spanletvars.t > bbextentt)
s_spanletvars.t = bbextentt;
else if (s_spanletvars.t < 0)
s_spanletvars.t = 0;
}
do
{
// calculate s and t at the far end of the span
if (count >= AFFINE_SPANLET_SIZE )
s_spanletvars.spancount = AFFINE_SPANLET_SIZE;
else
s_spanletvars.spancount = count;
count -= s_spanletvars.spancount;
if (count)
{
// calculate s/z, t/z, zi->fixed s and t at far end of span,
// calculate s and t steps across span by shifting
sdivz += sdivzspanletstepu;
tdivz += tdivzspanletstepu;
zi += zispanletstepu;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
tnext = (int)(tdivz * z) + tadjust;
if ( !iswater )
{
if (snext > bbextents)
snext = bbextents;
else if (snext < AFFINE_SPANLET_SIZE)
snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < AFFINE_SPANLET_SIZE)
tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
}
s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS;
s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS;
}
else
{
// calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
// can't step off polygon), clamp, calculate s and t steps across
// span by division, biasing steps low so we don't run off the
// texture
spancountminus1 = (float)(s_spanletvars.spancount - 1);
sdivz += d_sdivzstepu * spancountminus1;
tdivz += d_tdivzstepu * spancountminus1;
zi += d_zistepu * spancountminus1;
z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
snext = (int)(sdivz * z) + sadjust;
tnext = (int)(tdivz * z) + tadjust;
if ( !iswater )
{
if (snext > bbextents)
snext = bbextents;
else if (snext < AFFINE_SPANLET_SIZE)
snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
if (tnext > bbextentt)
tnext = bbextentt;
else if (tnext < AFFINE_SPANLET_SIZE)
tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
}
if (s_spanletvars.spancount > 1)
{
s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1);
s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1);
}
}
if ( iswater )
{
s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1);
s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1);
}
r_polydesc.drawspanlet();
s_spanletvars.s = snext;
s_spanletvars.t = tnext;
} while (count > 0);
NextSpan:
pspan++;
} while (pspan->count != DS_SPAN_LIST_END);
}
/*
**
** R_PolygonScanLeftEdge
**
** Goes through the polygon and scans the left edge, filling in
** screen coordinate data for the spans
*/
void R_PolygonScanLeftEdge (void)
{
int i, v, itop, ibottom, lmaxindex;
emitpoint_t *pvert, *pnext;
espan_t *pspan;
float du, dv, vtop, vbottom, slope;
fixed16_t u, u_step;
pspan = s_polygon_spans;
i = s_minindex;
if (i == 0)
i = r_polydesc.nump;
lmaxindex = s_maxindex;
if (lmaxindex == 0)
lmaxindex = r_polydesc.nump;
vtop = ceil (r_polydesc.pverts[i].v);
do
{
pvert = &r_polydesc.pverts[i];
pnext = pvert - 1;
vbottom = ceil (pnext->v);
if (vtop < vbottom)
{
du = pnext->u - pvert->u;
dv = pnext->v - pvert->v;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->u = u >> 16;
pspan->v = v;
u += u_step;
pspan++;
}
}
vtop = vbottom;
i--;
if (i == 0)
i = r_polydesc.nump;
} while (i != lmaxindex);
}
/*
** R_PolygonScanRightEdge
**
** Goes through the polygon and scans the right edge, filling in
** count values.
*/
void R_PolygonScanRightEdge (void)
{
int i, v, itop, ibottom;
emitpoint_t *pvert, *pnext;
espan_t *pspan;
float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext;
fixed16_t u, u_step;
pspan = s_polygon_spans;
i = s_minindex;
vvert = r_polydesc.pverts[i].v;
if (vvert < r_refdef.fvrecty_adj)
vvert = r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj)
vvert = r_refdef.fvrectbottom_adj;
vtop = ceil (vvert);
do
{
pvert = &r_polydesc.pverts[i];
pnext = pvert + 1;
vnext = pnext->v;
if (vnext < r_refdef.fvrecty_adj)
vnext = r_refdef.fvrecty_adj;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -