mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-21 20:11:12 +00:00
Undo clipsegs optimization
This commit is contained in:
parent
e22ea1f2e9
commit
5f5fff7e58
4 changed files with 162 additions and 99 deletions
225
src/r_bsp.c
225
src/r_bsp.c
|
@ -52,66 +52,164 @@ void R_ClearDrawSegs(void)
|
||||||
ds_p = drawsegs;
|
ds_p = drawsegs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CPhipps -
|
// Fix from boom.
|
||||||
// Instead of clipsegs, let's try using an array with one entry for each column,
|
#define MAXSEGS (MAXVIDWIDTH/2+1)
|
||||||
// indicating whether it's blocked by a solid wall yet or not.
|
|
||||||
UINT8 solidcol[MAXVIDWIDTH];
|
// 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
|
// R_ClipSolidWallSegment
|
||||||
// columns which aren't solid, and updates the solidcol[] array appropriately
|
// Does handle solid walls,
|
||||||
static void R_ClipWallSegment(INT32 first, INT32 last, boolean solid)
|
// e.g. single sided LineDefs (middle texture)
|
||||||
|
// that entirely block the view.
|
||||||
|
//
|
||||||
|
static void R_ClipSolidWallSegment(INT32 first, INT32 last)
|
||||||
{
|
{
|
||||||
while (first < last)
|
cliprange_t *next;
|
||||||
{
|
cliprange_t *start;
|
||||||
UINT8 *p;
|
|
||||||
|
|
||||||
if (solidcol[first])
|
// Find the first range that touches the range (adjacent pixels are touching).
|
||||||
{
|
start = solidsegs;
|
||||||
p = memchr(solidcol+first, 0, last-first);
|
while (start->last < first - 1)
|
||||||
if (!p)
|
start++;
|
||||||
return; // All solid
|
|
||||||
|
|
||||||
first = p - solidcol;
|
if (first < start->first)
|
||||||
}
|
{
|
||||||
else
|
if (last < start->first - 1)
|
||||||
{
|
{
|
||||||
p = memchr(solidcol+first, 1, last-first);
|
// Post is entirely visible (above start), so insert a new clippost.
|
||||||
|
R_StoreWallRange(first, last);
|
||||||
int to;
|
next = newend;
|
||||||
if (!p)
|
newend++;
|
||||||
to = last;
|
// NO MORE CRASHING!
|
||||||
else
|
if (newend - solidsegs > MAXSEGS)
|
||||||
to = p - solidcol;
|
I_Error("R_ClipSolidWallSegment: Solid Segs overflow!\n");
|
||||||
|
|
||||||
R_StoreWallRange(first, to-1);
|
while (next != start)
|
||||||
|
{
|
||||||
if (solid)
|
*next = *(next-1);
|
||||||
memset(solidcol+first, 1, to-first);
|
next--;
|
||||||
|
|
||||||
first = to;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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)
|
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)
|
void R_PortalClearClipSegs(INT32 start, INT32 end)
|
||||||
{
|
{
|
||||||
R_ClearClipSegs();
|
solidsegs[0].first = -0x7fffffff;
|
||||||
|
solidsegs[0].last = start-1;
|
||||||
for (INT32 x = 0; x < start; x++)
|
solidsegs[1].first = end;
|
||||||
solidcol[x] = 1;
|
solidsegs[1].last = 0x7fffffff;
|
||||||
|
newend = solidsegs + 2;
|
||||||
for (INT32 x = end; x < viewwidth; x++)
|
|
||||||
solidcol[x] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// R_DoorClosed
|
// R_DoorClosed
|
||||||
//
|
//
|
||||||
// This function is used to fix the automap bug which
|
// This function is used to fix the automap bug which
|
||||||
|
@ -517,11 +615,11 @@ static void R_AddLine(seg_t *line)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clippass:
|
clippass:
|
||||||
R_ClipWallSegment(x1, x2, false);
|
R_ClipPassWallSegment(x1, x2 - 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clipsolid:
|
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;
|
angle_t angle1, angle2;
|
||||||
INT32 sx1, sx2, boxpos;
|
INT32 sx1, sx2, boxpos;
|
||||||
const INT32* check;
|
const INT32* check;
|
||||||
|
cliprange_t *start;
|
||||||
|
|
||||||
// Find the corners of the box that define the edges from current viewpoint.
|
// Find the corners of the box that define the edges from current viewpoint.
|
||||||
if (viewx <= bspcoord[BOXLEFT])
|
if ((boxpos = (viewx <= bspcoord[BOXLEFT] ? 0 : viewx < bspcoord[BOXRIGHT] ? 1 : 2) + (viewy >= bspcoord[BOXTOP] ? 0 : viewy > bspcoord[BOXBOTTOM] ? 4 : 8)) == 5)
|
||||||
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)
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
check = checkcoord[boxpos];
|
check = checkcoord[boxpos];
|
||||||
|
@ -599,14 +684,14 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
|
||||||
sx2 = viewangletox[angle2];
|
sx2 = viewangletox[angle2];
|
||||||
|
|
||||||
// Does not cross a pixel.
|
// Does not cross a pixel.
|
||||||
if (sx1 >= sx2)
|
if (sx1 >= sx2) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!memchr(solidcol+sx1, 0, sx2-sx1))
|
start = solidsegs;
|
||||||
{
|
while (start->last < sx2)
|
||||||
// All columns it covers are already solidly covered
|
start++;
|
||||||
return false;
|
|
||||||
}
|
if (sx1 >= start->first && sx2 <= start->last)
|
||||||
|
return false; // The clippost contains the new span.
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1313,7 +1398,7 @@ void R_RenderPortalHorizonLine(sector_t *sector)
|
||||||
firstseg = NULL;
|
firstseg = NULL;
|
||||||
curline = &segs[0];
|
curline = &segs[0];
|
||||||
|
|
||||||
R_ClipWallSegment(portalclipstart, portalclipend, true);
|
R_ClipSolidWallSegment(portalclipstart, portalclipend);
|
||||||
|
|
||||||
curline = NULL;
|
curline = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,6 @@ extern boolean horizonline;
|
||||||
|
|
||||||
extern INT32 doorclosed;
|
extern INT32 doorclosed;
|
||||||
|
|
||||||
extern UINT8 solidcol[MAXVIDWIDTH];
|
|
||||||
|
|
||||||
// BSP?
|
// BSP?
|
||||||
void R_ClearClipSegs(void);
|
void R_ClearClipSegs(void);
|
||||||
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
void R_PortalClearClipSegs(INT32 start, INT32 end);
|
||||||
|
|
11
src/r_defs.h
11
src/r_defs.h
|
@ -31,6 +31,17 @@
|
||||||
|
|
||||||
#include "taglist.h"
|
#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.
|
// Silhouette, needed for clipping segs (mainly) and sprites representing things.
|
||||||
#define SIL_NONE 0
|
#define SIL_NONE 0
|
||||||
#define SIL_BOTTOM 1
|
#define SIL_BOTTOM 1
|
||||||
|
|
31
src/r_segs.c
31
src/r_segs.c
|
@ -994,8 +994,6 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor)
|
||||||
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
|
return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean didsolidcol; // True if at least one column was marked solid
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// R_RenderSegLoop
|
// R_RenderSegLoop
|
||||||
// Draws zero, one, or two textures (and possibly a masked
|
// Draws zero, one, or two textures (and possibly a masked
|
||||||
|
@ -1437,12 +1435,6 @@ static void R_RenderSegLoop (void)
|
||||||
floorclip[rw_x] = bottomclip;
|
floorclip[rw_x] = bottomclip;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((markceiling || markfloor) && (floorclip[rw_x] <= ceilingclip[rw_x] + 1))
|
|
||||||
{
|
|
||||||
solidcol[rw_x] = 1;
|
|
||||||
didsolidcol = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maskedtexturecol)
|
if (maskedtexturecol)
|
||||||
maskedtexturecol[rw_x] = texturecolumn + rw_offsetx;
|
maskedtexturecol[rw_x] = texturecolumn + rw_offsetx;
|
||||||
|
|
||||||
|
@ -1565,12 +1557,6 @@ static void R_MarkSegBounds(void)
|
||||||
if (markfloor) // no bottom wall
|
if (markfloor) // no bottom wall
|
||||||
floorclip[rw_x] = bottomclip;
|
floorclip[rw_x] = bottomclip;
|
||||||
|
|
||||||
if (floorclip[rw_x] <= ceilingclip[rw_x] + 1)
|
|
||||||
{
|
|
||||||
solidcol[rw_x] = 1;
|
|
||||||
didsolidcol = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
rw_scale += rw_scalestep;
|
rw_scale += rw_scalestep;
|
||||||
topfrac += topstep;
|
topfrac += topstep;
|
||||||
bottomfrac += bottomstep;
|
bottomfrac += bottomstep;
|
||||||
|
@ -2954,8 +2940,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
didsolidcol = false;
|
|
||||||
|
|
||||||
if (!segtextured && !numffloors && !numbackffloors)
|
if (!segtextured && !numffloors && !numbackffloors)
|
||||||
{
|
{
|
||||||
if (markfloor || markceiling)
|
if (markfloor || markceiling)
|
||||||
|
@ -2985,21 +2969,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
||||||
else
|
else
|
||||||
ds_p->portalpass = 0;
|
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
|
// save sprite clipping info
|
||||||
if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM)))
|
if (maskedtexture || (ds_p->silhouette & (SIL_TOP | SIL_BOTTOM)))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue