📄 r_poly.c
字号:
if (vnext > r_refdef.fvrectbottom_adj)
vnext = r_refdef.fvrectbottom_adj;
vbottom = ceil (vnext);
if (vtop < vbottom)
{
uvert = pvert->u;
if (uvert < r_refdef.fvrectx_adj)
uvert = r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj)
uvert = r_refdef.fvrectright_adj;
unext = pnext->u;
if (unext < r_refdef.fvrectx_adj)
unext = r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj)
unext = r_refdef.fvrectright_adj;
du = unext - uvert;
dv = vnext - vvert;
slope = du / dv;
u_step = (int)(slope * 0x10000);
// adjust u to ceil the integer portion
u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) +
(0x10000 - 1);
itop = (int)vtop;
ibottom = (int)vbottom;
for (v=itop ; v<ibottom ; v++)
{
pspan->count = (u >> 16) - pspan->u;
u += u_step;
pspan++;
}
}
vtop = vbottom;
vvert = vnext;
i++;
if (i == r_polydesc.nump)
i = 0;
} while (i != s_maxindex);
pspan->count = DS_SPAN_LIST_END; // mark the end of the span list
}
/*
** R_ClipAndDrawPoly
*/
// PGM - isturbulent was qboolean. changed to int to allow passing more flags
void R_ClipAndDrawPoly ( float alpha, int isturbulent, qboolean textured )
{
emitpoint_t outverts[MAXWORKINGVERTS+3], *pout;
float *pv;
int i, nump;
float scale;
vec3_t transformed, local;
if ( !textured )
{
r_polydesc.drawspanlet = R_DrawSpanletConstant33;
}
else
{
/*
** choose the correct spanlet routine based on alpha
*/
if ( alpha == 1 )
{
// isturbulent is ignored because we know that turbulent surfaces
// can't be opaque
r_polydesc.drawspanlet = R_DrawSpanletOpaque;
}
else
{
if ( sw_stipplealpha->value )
{
if ( isturbulent )
{
if ( alpha > 0.33 )
r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66;
else
r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33;
}
else
{
if ( alpha > 0.33 )
r_polydesc.drawspanlet = R_DrawSpanlet66Stipple;
else
r_polydesc.drawspanlet = R_DrawSpanlet33Stipple;
}
}
else
{
if ( isturbulent )
{
if ( alpha > 0.33 )
r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66;
else
r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33;
}
else
{
if ( alpha > 0.33 )
r_polydesc.drawspanlet = R_DrawSpanlet66;
else
r_polydesc.drawspanlet = R_DrawSpanlet33;
}
}
}
}
// clip to the frustum in worldspace
nump = r_polydesc.nump;
clip_current = 0;
for (i=0 ; i<4 ; i++)
{
nump = R_ClipPolyFace (nump, &view_clipplanes[i]);
if (nump < 3)
return;
if (nump > MAXWORKINGVERTS)
ri.Sys_Error(ERR_DROP, "R_ClipAndDrawPoly: too many points: %d", nump );
}
// transform vertices into viewspace and project
pv = &r_clip_verts[clip_current][0][0];
for (i=0 ; i<nump ; i++)
{
VectorSubtract (pv, r_origin, local);
TransformVector (local, transformed);
if (transformed[2] < NEAR_CLIP)
transformed[2] = NEAR_CLIP;
pout = &outverts[i];
pout->zi = 1.0 / transformed[2];
pout->s = pv[3];
pout->t = pv[4];
scale = xscale * pout->zi;
pout->u = (xcenter + scale * transformed[0]);
scale = yscale * pout->zi;
pout->v = (ycenter - scale * transformed[1]);
pv += sizeof (vec5_t) / sizeof (pv);
}
// draw it
r_polydesc.nump = nump;
r_polydesc.pverts = outverts;
R_DrawPoly( isturbulent );
}
/*
** R_BuildPolygonFromSurface
*/
void R_BuildPolygonFromSurface(msurface_t *fa)
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
int vertpage;
float *vec;
vec5_t *pverts;
float tmins[2] = { 0, 0 };
r_polydesc.nump = 0;
// reconstruct the polygon
pedges = currentmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
pverts = r_clip_verts[0];
for (i=0 ; i<lnumverts ; i++)
{
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
VectorCopy (vec, pverts[i] );
}
VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright );
VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup );
VectorCopy( fa->plane->normal, r_polydesc.vpn );
VectorCopy( r_origin, r_polydesc.viewer_position );
if ( fa->flags & SURF_PLANEBACK )
{
VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn );
}
// PGM 09/16/98
if ( fa->texinfo->flags & (SURF_WARP|SURF_FLOWING) )
{
r_polydesc.pixels = fa->texinfo->image->pixels[0];
r_polydesc.pixel_width = fa->texinfo->image->width;
r_polydesc.pixel_height = fa->texinfo->image->height;
}
// PGM 09/16/98
else
{
surfcache_t *scache;
scache = D_CacheSurface( fa, 0 );
r_polydesc.pixels = scache->data;
r_polydesc.pixel_width = scache->width;
r_polydesc.pixel_height = scache->height;
tmins[0] = fa->texturemins[0];
tmins[1] = fa->texturemins[1];
}
r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] );
r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0];
r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1];
// scrolling texture addition
if (fa->texinfo->flags & SURF_FLOWING)
{
r_polydesc.s_offset += -128 * ( (r_newrefdef.time*0.25) - (int)(r_newrefdef.time*0.25) );
}
r_polydesc.nump = lnumverts;
}
/*
** R_PolygonCalculateGradients
*/
void R_PolygonCalculateGradients (void)
{
vec3_t p_normal, p_saxis, p_taxis;
float distinv;
TransformVector (r_polydesc.vpn, p_normal);
TransformVector (r_polydesc.vright, p_saxis);
TransformVector (r_polydesc.vup, p_taxis);
distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist );
d_sdivzstepu = p_saxis[0] * xscaleinv;
d_sdivzstepv = -p_saxis[1] * yscaleinv;
d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
d_tdivzstepu = p_taxis[0] * xscaleinv;
d_tdivzstepv = -p_taxis[1] * yscaleinv;
d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
d_zistepu = p_normal[0] * xscaleinv * distinv;
d_zistepv = -p_normal[1] * yscaleinv * distinv;
d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 );
tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 );
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents = (r_polydesc.pixel_width << 16) - 1;
bbextentt = (r_polydesc.pixel_height << 16) - 1;
}
/*
** R_DrawPoly
**
** Polygon drawing function. Uses the polygon described in r_polydesc
** to calculate edges and gradients, then renders the resultant spans.
**
** This should NOT be called externally since it doesn't do clipping!
*/
// PGM - iswater was qboolean. changed to support passing more flags
static void R_DrawPoly( int iswater )
{
int i, nump;
float ymin, ymax;
emitpoint_t *pverts;
espan_t spans[MAXHEIGHT+1];
s_polygon_spans = spans;
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin = 999999.9;
ymax = -999999.9;
pverts = r_polydesc.pverts;
for (i=0 ; i<r_polydesc.nump ; i++)
{
if (pverts->v < ymin)
{
ymin = pverts->v;
s_minindex = i;
}
if (pverts->v > ymax)
{
ymax = pverts->v;
s_maxindex = i;
}
pverts++;
}
ymin = ceil (ymin);
ymax = ceil (ymax);
if (ymin >= ymax)
return; // doesn't cross any scans at all
cachewidth = r_polydesc.pixel_width;
cacheblock = r_polydesc.pixels;
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump = r_polydesc.nump;
pverts = r_polydesc.pverts;
pverts[nump] = pverts[0];
R_PolygonCalculateGradients ();
R_PolygonScanLeftEdge ();
R_PolygonScanRightEdge ();
R_PolygonDrawSpans( s_polygon_spans, iswater );
}
/*
** R_DrawAlphaSurfaces
*/
void R_DrawAlphaSurfaces( void )
{
msurface_t *s = r_alpha_surfaces;
currentmodel = r_worldmodel;
modelorg[0] = -r_origin[0];
modelorg[1] = -r_origin[1];
modelorg[2] = -r_origin[2];
while ( s )
{
R_BuildPolygonFromSurface( s );
//=======
//PGM
// if (s->texinfo->flags & SURF_TRANS66)
// R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
// else
// R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
// PGM - pass down all the texinfo flags, not just SURF_WARP.
if (s->texinfo->flags & SURF_TRANS66)
R_ClipAndDrawPoly( 0.60f, (s->texinfo->flags & SURF_WARP|SURF_FLOWING), true );
else
R_ClipAndDrawPoly( 0.30f, (s->texinfo->flags & SURF_WARP|SURF_FLOWING), true );
//PGM
//=======
s = s->nextalphasurface;
}
r_alpha_surfaces = NULL;
}
/*
** R_IMFlatShadedQuad
*/
void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha )
{
vec3_t s0, s1;
r_polydesc.nump = 4;
VectorCopy( r_origin, r_polydesc.viewer_position );
VectorCopy( a, r_clip_verts[0][0] );
VectorCopy( b, r_clip_verts[0][1] );
VectorCopy( c, r_clip_verts[0][2] );
VectorCopy( d, r_clip_verts[0][3] );
r_clip_verts[0][0][3] = 0;
r_clip_verts[0][1][3] = 0;
r_clip_verts[0][2][3] = 0;
r_clip_verts[0][3][3] = 0;
r_clip_verts[0][0][4] = 0;
r_clip_verts[0][1][4] = 0;
r_clip_verts[0][2][4] = 0;
r_clip_verts[0][3][4] = 0;
VectorSubtract( d, c, s0 );
VectorSubtract( c, b, s1 );
CrossProduct( s0, s1, r_polydesc.vpn );
VectorNormalize( r_polydesc.vpn );
r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] );
r_polyblendcolor = color;
R_ClipAndDrawPoly( alpha, false, false );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -