📄 r_edge.c
字号:
void R_GenerateSpans (void)
{
edge_t *edge;
surf_t *surf;
// clear active surfaces to just the background surface
surfaces[1].next = surfaces[1].prev = &surfaces[1];
surfaces[1].last_u = edge_head_u_shift20;
// generate spans
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
{
if (edge->surfs[0])
{
// it has a left surface, so a surface is going away for this span
surf = &surfaces[edge->surfs[0]];
R_TrailingEdge (surf, edge);
if (!edge->surfs[1])
continue;
}
R_LeadingEdge (edge);
}
R_CleanupSpan ();
}
#endif // !id386
/*
==============
R_GenerateSpansBackward
==============
*/
void R_GenerateSpansBackward (void)
{
edge_t *edge;
// clear active surfaces to just the background surface
surfaces[1].next = surfaces[1].prev = &surfaces[1];
surfaces[1].last_u = edge_head_u_shift20;
// generate spans
for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
{
if (edge->surfs[0])
R_TrailingEdge (&surfaces[edge->surfs[0]], edge);
if (edge->surfs[1])
R_LeadingEdgeBackwards (edge);
}
R_CleanupSpan ();
}
/*
==============
R_ScanEdges
Input:
newedges[] array
this has links to edges, which have links to surfaces
Output:
Each surface has a linked list of its visible spans
==============
*/
void R_ScanEdges (void)
{
int iv, bottom;
byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
espan_t *basespan_p;
surf_t *s;
basespan_p = (espan_t *)
((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
span_p = basespan_p;
// clear active edges to just the background edges around the whole screen
// FIXME: most of this only needs to be set up once
edge_head.u = r_refdef.vrect.x << 20;
edge_head_u_shift20 = edge_head.u >> 20;
edge_head.u_step = 0;
edge_head.prev = NULL;
edge_head.next = &edge_tail;
edge_head.surfs[0] = 0;
edge_head.surfs[1] = 1;
edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
edge_tail_u_shift20 = edge_tail.u >> 20;
edge_tail.u_step = 0;
edge_tail.prev = &edge_head;
edge_tail.next = &edge_aftertail;
edge_tail.surfs[0] = 1;
edge_tail.surfs[1] = 0;
edge_aftertail.u = -1; // force a move
edge_aftertail.u_step = 0;
edge_aftertail.next = &edge_sentinel;
edge_aftertail.prev = &edge_tail;
// FIXME: do we need this now that we clamp x in r_draw.c?
edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this
edge_sentinel.prev = &edge_aftertail;
//
// process all scan lines
//
bottom = r_refdef.vrectbottom - 1;
for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
{
current_iv = iv;
fv = (float)iv;
// mark that the head (background start) span is pre-included
surfaces[1].spanstate = 1;
if (newedges[iv])
{
R_InsertNewEdges (newedges[iv], edge_head.next);
}
(*pdrawfunc) ();
// flush the span list if we can't be sure we have enough spans left for
// the next scan
if (span_p > max_span_p)
{
D_DrawSurfaces ();
// clear the surface span pointers
for (s = &surfaces[1] ; s<surface_p ; s++)
s->spans = NULL;
span_p = basespan_p;
}
if (removeedges[iv])
R_RemoveEdges (removeedges[iv]);
if (edge_head.next != &edge_tail)
R_StepActiveU (edge_head.next);
}
// do the last scan (no need to step or sort or remove on the last scan)
current_iv = iv;
fv = (float)iv;
// mark that the head (background start) span is pre-included
surfaces[1].spanstate = 1;
if (newedges[iv])
R_InsertNewEdges (newedges[iv], edge_head.next);
(*pdrawfunc) ();
// draw whatever's left in the span list
D_DrawSurfaces ();
}
/*
=========================================================================
SURFACE FILLING
=========================================================================
*/
msurface_t *pface;
surfcache_t *pcurrentcache;
vec3_t transformed_modelorg;
vec3_t world_transformed_modelorg;
vec3_t local_modelorg;
/*
=============
D_MipLevelForScale
=============
*/
int D_MipLevelForScale (float scale)
{
int lmiplevel;
if (scale >= d_scalemip[0] )
lmiplevel = 0;
else if (scale >= d_scalemip[1] )
lmiplevel = 1;
else if (scale >= d_scalemip[2] )
lmiplevel = 2;
else
lmiplevel = 3;
if (lmiplevel < d_minmip)
lmiplevel = d_minmip;
return lmiplevel;
}
/*
==============
D_FlatFillSurface
Simple single color fill with no texture mapping
==============
*/
void D_FlatFillSurface (surf_t *surf, int color)
{
espan_t *span;
byte *pdest;
int u, u2;
for (span=surf->spans ; span ; span=span->pnext)
{
pdest = (byte *)d_viewbuffer + r_screenwidth*span->v;
u = span->u;
u2 = span->u + span->count - 1;
for ( ; u <= u2 ; u++)
pdest[u] = color;
}
}
/*
==============
D_CalcGradients
==============
*/
void D_CalcGradients (msurface_t *pface)
{
mplane_t *pplane;
float mipscale;
vec3_t p_temp1;
vec3_t p_saxis, p_taxis;
float t;
pplane = pface->plane;
mipscale = 1.0 / (float)(1 << miplevel);
TransformVector (pface->texinfo->vecs[0], p_saxis);
TransformVector (pface->texinfo->vecs[1], p_taxis);
t = xscaleinv * mipscale;
d_sdivzstepu = p_saxis[0] * t;
d_tdivzstepu = p_taxis[0] * t;
t = yscaleinv * mipscale;
d_sdivzstepv = -p_saxis[1] * t;
d_tdivzstepv = -p_taxis[1] * t;
d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
ycenter * d_sdivzstepv;
d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
ycenter * d_tdivzstepv;
VectorScale (transformed_modelorg, mipscale, p_temp1);
t = 0x10000*mipscale;
sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
((pface->texturemins[0] << 16) >> miplevel)
+ pface->texinfo->vecs[0][3]*t;
tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
((pface->texturemins[1] << 16) >> miplevel)
+ pface->texinfo->vecs[1][3]*t;
// PGM - changing flow speed for non-warping textures.
if (pface->texinfo->flags & SURF_FLOWING)
{
if(pface->texinfo->flags & SURF_WARP)
sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) ));
else
sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) ));
}
// PGM
//
// -1 (-epsilon) so we never wander off the edge of the texture
//
bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}
/*
==============
D_BackgroundSurf
The grey background filler seen when there is a hole in the map
==============
*/
void D_BackgroundSurf (surf_t *s)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
D_DrawZSpans (s->spans);
}
/*
=================
D_TurbulentSurf
=================
*/
void D_TurbulentSurf (surf_t *s)
{
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
pface = s->msurf;
miplevel = 0;
cacheblock = pface->texinfo->image->pixels[0];
cachewidth = 64;
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin,
local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
D_CalcGradients (pface);
//============
//PGM
// textures that aren't warping are just flowing. Use NonTurbulent8 instead
if(!(pface->texinfo->flags & SURF_WARP))
NonTurbulent8 (s->spans);
else
Turbulent8 (s->spans);
//PGM
//============
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
currententity = NULL; // &r_worldentity;
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
R_TransformFrustum ();
}
}
/*
==============
D_SkySurf
==============
*/
void D_SkySurf (surf_t *s)
{
pface = s->msurf;
miplevel = 0;
if (!pface->texinfo->image)
return;
cacheblock = pface->texinfo->image->pixels[0];
cachewidth = 256;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
D_CalcGradients (pface);
D_DrawSpans16 (s->spans);
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
d_zistepu = 0;
d_zistepv = 0;
d_ziorigin = -0.9;
D_DrawZSpans (s->spans);
}
/*
==============
D_SolidSurf
Normal surface cached, texture mapped surface
==============
*/
void D_SolidSurf (surf_t *s)
{
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
if (s->insubmodel)
{
// FIXME: we don't want to do all this for every polygon!
// TODO: store once at start of frame
currententity = s->entity; //FIXME: make this passed in to
// R_RotateBmodel ()
VectorSubtract (r_origin, currententity->origin, local_modelorg);
TransformVector (local_modelorg, transformed_modelorg);
R_RotateBmodel (); // FIXME: don't mess with the frustum,
// make entity passed in
}
else
currententity = &r_worldentity;
pface = s->msurf;
#if 1
miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
#else
{
float dot;
float normal[3];
if ( s->insubmodel )
{
VectorCopy( pface->plane->normal, normal );
// TransformVector( pface->plane->normal, normal);
dot = DotProduct( normal, vpn );
}
else
{
VectorCopy( pface->plane->normal, normal );
dot = DotProduct( normal, vpn );
}
if ( pface->flags & SURF_PLANEBACK )
dot = -dot;
if ( dot > 0 )
printf( "blah" );
miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
}
#endif
// FIXME: make this passed in to D_CacheSurface
pcurrentcache = D_CacheSurface (pface, miplevel);
cacheblock = (pixel_t *)pcurrentcache->data;
cachewidth = pcurrentcache->width;
D_CalcGradients (pface);
D_DrawSpans16 (s->spans);
D_DrawZSpans (s->spans);
if (s->insubmodel)
{
//
// restore the old drawing state
// FIXME: we don't want to do this every time!
// TODO: speed up
//
VectorCopy (world_transformed_modelorg,
transformed_modelorg);
VectorCopy (base_vpn, vpn);
VectorCopy (base_vup, vup);
VectorCopy (base_vright, vright);
R_TransformFrustum ();
currententity = NULL; //&r_worldentity;
}
}
/*
=============
D_DrawflatSurfaces
To allow developers to see the polygon carving of the world
=============
*/
void D_DrawflatSurfaces (void)
{
surf_t *s;
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
d_zistepu = s->d_zistepu;
d_zistepv = s->d_zistepv;
d_ziorigin = s->d_ziorigin;
// make a stable color for each surface by taking the low
// bits of the msurface pointer
D_FlatFillSurface (s, (int)s->msurf & 0xFF);
D_DrawZSpans (s->spans);
}
}
/*
==============
D_DrawSurfaces
Rasterize all the span lists. Guaranteed zero overdraw.
May be called more than once a frame if the surf list overflows (higher res)
==============
*/
void D_DrawSurfaces (void)
{
surf_t *s;
// currententity = NULL; //&r_worldentity;
VectorSubtract (r_origin, vec3_origin, modelorg);
TransformVector (modelorg, transformed_modelorg);
VectorCopy (transformed_modelorg, world_transformed_modelorg);
if (!sw_drawflat->value)
{
for (s = &surfaces[1] ; s<surface_p ; s++)
{
if (!s->spans)
continue;
r_drawnpolycount++;
if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) )
D_SolidSurf (s);
else if (s->flags & SURF_DRAWSKYBOX)
D_SkySurf (s);
else if (s->flags & SURF_DRAWBACKGROUND)
D_BackgroundSurf (s);
else if (s->flags & SURF_DRAWTURB)
D_TurbulentSurf (s);
}
}
else
D_DrawflatSurfaces ();
currententity = NULL; //&r_worldentity;
VectorSubtract (r_origin, vec3_origin, modelorg);
R_TransformFrustum ();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -