Undo clipsegs optimization

This commit is contained in:
Lactozilla 2024-05-20 21:06:31 -03:00
parent e22ea1f2e9
commit 5f5fff7e58
4 changed files with 162 additions and 99 deletions

View file

@ -52,66 +52,164 @@ void R_ClearDrawSegs(void)
ds_p = drawsegs;
}
// CPhipps -
// Instead of clipsegs, let's try using an array with one entry for each column,
// indicating whether it's blocked by a solid wall yet or not.
UINT8 solidcol[MAXVIDWIDTH];
// Fix from boom.
#define MAXSEGS (MAXVIDWIDTH/2+1)
// newend is one past the last valid seg
static cliprange_t *newend;
static cliprange_t solidsegs[MAXSEGS];
// CPhipps -
// R_ClipWallSegment
//
// Replaces the old R_Clip*WallSegment functions. It draws bits of walls in those
// columns which aren't solid, and updates the solidcol[] array appropriately
static void R_ClipWallSegment(INT32 first, INT32 last, boolean solid)
// R_ClipSolidWallSegment
// Does handle solid walls,
// e.g. single sided LineDefs (middle texture)
// that entirely block the view.
//
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
{
while (first < last)
{
UINT8 *p;
cliprange_t *next;
cliprange_t *start;
if (solidcol[first])
{
p = memchr(solidcol+first, 0, last-first);
if (!p)
return; // All solid
// Find the first range that touches the range (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
first = p - solidcol;
}
else
{
p = memchr(solidcol+first, 1, last-first);
int to;
if (!p)
to = last;
else
to = p - solidcol;
R_StoreWallRange(first, to-1);
if (solid)
memset(solidcol+first, 1, to-first);
first = to;
}
if (first < start->first)
{
if (last < start->first - 1)
{
// Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange(first, last);
next = newend;
newend++;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
while (next != start)
{
*next = *(next-1);
next--;
}
next->first = first;
next->last = last;
return;
}
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
// Now adjust the clip size.
start->first = first;
}
// Bottom contained in start?
if (last <= start->last)
return;
next = start;
while (last >= (next+1)->first - 1)
{
// There is a fragment between two posts.
R_StoreWallRange(next->last + 1, (next+1)->first - 1);
next++;
if (last <= next->last)
{
// Bottom is contained in next.
// Adjust the clip size.
start->last = next->last;
goto crunch;
}
}
// There is a fragment after *next.
R_StoreWallRange(next->last + 1, last);
// Adjust the clip size.
start->last = last;
// Remove start+1 to next from the clip list, because start now covers their area.
crunch:
if (next == start)
return; // Post just extended past the bottom of one post.
while (next++ != newend)
*++start = *next; // Remove a post.
newend = start + 1;
// NO MORE CRASHING!
if (newend - solidsegs > MAXSEGS)
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
}
//
// R_ClipPassWallSegment
// Clips the given range of columns, but does not include it in the clip list.
// Does handle windows, e.g. LineDefs with upper and lower texture.
//
static inline void R_ClipPassWallSegment(INT32 first, INT32 last)
{
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first - 1)
start++;
if (first < start->first)
{
if (last < start->first - 1)
{
// Post is entirely visible (above start).
R_StoreWallRange(first, last);
return;
}
// There is a fragment above *start.
R_StoreWallRange(first, start->first - 1);
}
// Bottom contained in start?
if (last <= start->last)
return;
while (last >= (start+1)->first - 1)
{
// There is a fragment between two posts.
R_StoreWallRange(start->last + 1, (start+1)->first - 1);
start++;
if (last <= start->last)
return;
}
// There is a fragment after *next.
R_StoreWallRange(start->last + 1, last);
}
//
// R_ClearClipSegs
//
void R_ClearClipSegs(void)
{
memset(solidcol, 0, viewwidth);
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = -1;
solidsegs[1].first = viewwidth;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
}
void R_PortalClearClipSegs(INT32 start, INT32 end)
{
R_ClearClipSegs();
for (INT32 x = 0; x < start; x++)
solidcol[x] = 1;
for (INT32 x = end; x < viewwidth; x++)
solidcol[x] = 1;
solidsegs[0].first = -0x7fffffff;
solidsegs[0].last = start-1;
solidsegs[1].first = end;
solidsegs[1].last = 0x7fffffff;
newend = solidsegs + 2;
}
// R_DoorClosed
//
// This function is used to fix the automap bug which
@ -517,11 +615,11 @@ static void R_AddLine(seg_t *line)
return;
clippass:
R_ClipWallSegment(x1, x2, false);
R_ClipPassWallSegment(x1, x2 - 1);
return;
clipsolid:
R_ClipWallSegment(x1, x2, true);
R_ClipSolidWallSegment(x1, x2 - 1);
}
//
@ -554,23 +652,10 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
angle_t angle1, angle2;
INT32 sx1, sx2, boxpos;
const INT32* check;
cliprange_t *start;
// Find the corners of the box that define the edges from current viewpoint.
if (viewx <= bspcoord[BOXLEFT])
boxpos = 0;
else if (viewx < bspcoord[BOXRIGHT])
boxpos = 1;
else
boxpos = 2;
if (viewy >= bspcoord[BOXTOP])
boxpos |= 0;
else if (viewy > bspcoord[BOXBOTTOM])
boxpos |= 1<<2;
else
boxpos |= 2<<2;
if (boxpos == 5)
if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
return true;
check = checkcoord[boxpos];
@ -599,14 +684,14 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
sx2 = viewangletox[angle2];
// Does not cross a pixel.
if (sx1 >= sx2)
return false;
if (sx1 >= sx2) return false;
if (!memchr(solidcol+sx1, 0, sx2-sx1))
{
// All columns it covers are already solidly covered
return false;
}
start = solidsegs;
while (start->last < sx2)
start++;
if (sx1 >= start->first && sx2 <= start->last)
return false; // The clippost contains the new span.
return true;
}
@ -1313,7 +1398,7 @@ void R_RenderPortalHorizonLine(sector_t *sector)
firstseg = NULL;
curline = &segs[0];
R_ClipWallSegment(portalclipstart, portalclipend, true);
R_ClipSolidWallSegment(portalclipstart, portalclipend);
curline = NULL;
}

View file

@ -38,8 +38,6 @@ extern boolean horizonline;
extern INT32 doorclosed;
extern UINT8 solidcol[MAXVIDWIDTH];
// BSP?
void R_ClearClipSegs(void);
void R_PortalClearClipSegs(INT32 start, INT32 end);

View file

@ -31,6 +31,17 @@
#include "taglist.h"
//
// ClipWallSegment
// Clips the given range of columns
// and includes it in the new clip list.
//
typedef struct
{
INT32 first;
INT32 last;
} cliprange_t;
// Silhouette, needed for clipping segs (mainly) and sprites representing things.
#define SIL_NONE 0
#define SIL_BOTTOM 1

View file

@ -994,8 +994,6 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor)
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
}
static boolean didsolidcol; // True if at least one column was marked solid
//
// R_RenderSegLoop
// Draws zero, one, or two textures (and possibly a masked
@ -1437,12 +1435,6 @@ static void R_RenderSegLoop (void)
floorclip[rw_x] = bottomclip;
}
if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1))
{
solidcol[rw_x] = 1;
didsolidcol = true;
}
if (maskedtexturecol)
maskedtexturecol[rw_x] = texturecolumn + rw_offsetx;
@ -1565,12 +1557,6 @@ static void R_MarkSegBounds(void)
if (markfloor) // no bottom wall
floorclip[rw_x] = bottomclip;
if (floorclip[rw_x] <= ceilingclip[rw_x] + 1)
{
solidcol[rw_x] = 1;
didsolidcol = true;
}
rw_scale += rw_scalestep;
topfrac += topstep;
bottomfrac += bottomstep;
@ -2954,8 +2940,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
}
}
didsolidcol = false;
if (!segtextured && !numffloors && !numbackffloors)
{
if (markfloor || markceiling)
@ -2985,21 +2969,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
else
ds_p->portalpass = 0;
// cph - if a column was made solid by this wall, we _must_ save full clipping info
if (backsector && didsolidcol)
{
if (!(ds_p->silhouette & SIL_BOTTOM))
{
ds_p->silhouette |= SIL_BOTTOM;
ds_p->bsilheight = backsector->f_slope ? INT32_MAX : backsector->floorheight;
}
if (!(ds_p->silhouette & SIL_TOP))
{
ds_p->silhouette |= SIL_TOP;
ds_p->tsilheight = backsector->c_slope ? INT32_MIN : backsector->ceilingheight;
}
}
// save sprite clipping info
if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM)))
{