Move all clip segment handling to r_clip_segment and make its working data private

This commit is contained in:
Magnus Norddahl 2016-12-28 12:07:55 +01:00
parent 1b284ecf3b
commit 18a551f936
5 changed files with 164 additions and 173 deletions

View File

@ -96,148 +96,6 @@ WORD MirrorFlags;
subsector_t *InSubsector; subsector_t *InSubsector;
void R_StoreWallRange (int start, int stop);
//==========================================================================
//
// R_ClipWallSegment
//
// Clips the given range of columns, possibly including it in the clip list.
// Handles both windows (e.g. LineDefs with upper and lower textures) and
// solid walls (e.g. single sided LineDefs [middle texture]) that entirely
// block the view.
//
//==========================================================================
bool R_ClipWallSegment (int first, int last, bool solid)
{
cliprange_t *next, *start;
int i, j;
bool res = false;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first)
start++;
if (first < start->first)
{
res = true;
if (last <= start->first)
{
// Post is entirely visible (above start).
R_StoreWallRange (first, last);
if (fake3D & FAKE3D_FAKEMASK)
{
return true;
}
// Insert a new clippost for solid walls.
if (solid)
{
if (last == start->first)
{
start->first = first;
}
else
{
next = newend;
newend++;
while (next != start)
{
*next = *(next-1);
next--;
}
next->first = first;
next->last = last;
}
}
return true;
}
// There is a fragment above *start.
R_StoreWallRange (first, start->first);
// Adjust the clip size for solid walls
if (solid && !(fake3D & FAKE3D_FAKEMASK))
{
start->first = first;
}
}
// Bottom contained in start?
if (last <= start->last)
return res;
next = start;
while (last >= (next+1)->first)
{
// There is a fragment between two posts.
R_StoreWallRange (next->last, (next+1)->first);
next++;
if (last <= next->last)
{
// Bottom is contained in next.
last = next->last;
goto crunch;
}
}
// There is a fragment after *next.
R_StoreWallRange (next->last, last);
crunch:
if (fake3D & FAKE3D_FAKEMASK)
{
return true;
}
if (solid)
{
// Adjust the clip size.
start->last = last;
if (next != start)
{
// Remove start+1 to next from the clip list,
// because start now covers their area.
for (i = 1, j = (int)(newend - next); j > 0; i++, j--)
{
start[i] = next[i];
}
newend = start+i;
}
}
return true;
}
bool R_CheckClipWallSegment (int first, int last)
{
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first)
start++;
if (first < start->first)
{
return true;
}
// Bottom contained in start?
if (last > start->last)
{
return true;
}
return false;
}
// //
// killough 3/7/98: Hack floor/ceiling heights for deep water etc. // killough 3/7/98: Hack floor/ceiling heights for deep water etc.
// //
@ -703,7 +561,7 @@ void R_AddLine (seg_t *line)
#endif #endif
} }
if (R_ClipWallSegment (WallC.sx1, WallC.sx2, solid)) if (R_ClipWallSegment(WallC.sx1, WallC.sx2, solid, R_StoreWallRange))
{ {
InSubsector->flags |= SSECF_DRAWN; InSubsector->flags |= SSECF_DRAWN;
} }
@ -836,8 +694,6 @@ static bool R_CheckBBox (float *bspcoord) // killough 1/28/98: static
double rx1, ry1, rx2, ry2; double rx1, ry1, rx2, ry2;
int sx1, sx2; int sx1, sx2;
cliprange_t* start;
// Find the corners of the box // Find the corners of the box
// that define the edges from current viewpoint. // that define the edges from current viewpoint.
if (ViewPos.X <= bspcoord[BOXLEFT]) if (ViewPos.X <= bspcoord[BOXLEFT])
@ -911,21 +767,7 @@ static bool R_CheckBBox (float *bspcoord) // killough 1/28/98: static
// Find the first clippost that touches the source post // Find the first clippost that touches the source post
// (adjacent pixels are touching). // (adjacent pixels are touching).
// Does not cross a pixel. return R_IsWallSegmentVisible(sx1, sx2);
if (sx2 <= sx1)
return false;
start = solidsegs;
while (start->last < sx2)
start++;
if (sx1 >= start->first && sx2 <= start->last)
{
// The clippost contains the new span.
return false;
}
return true;
} }

View File

@ -26,8 +26,16 @@
namespace swrenderer namespace swrenderer
{ {
cliprange_t *newend; namespace
{
struct cliprange_t
{
short first, last;
};
cliprange_t *newend; // newend is one past the last valid seg
cliprange_t solidsegs[MAXWIDTH / 2 + 2]; cliprange_t solidsegs[MAXWIDTH / 2 + 2];
}
void R_ClearClipSegs(short left, short right) void R_ClearClipSegs(short left, short right)
{ {
@ -37,4 +45,145 @@ namespace swrenderer
solidsegs[1].last = 0x7fff; solidsegs[1].last = 0x7fff;
newend = solidsegs+2; newend = solidsegs+2;
} }
bool R_CheckClipWallSegment(int first, int last)
{
cliprange_t *start;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first)
start++;
if (first < start->first)
{
return true;
}
// Bottom contained in start?
if (last > start->last)
{
return true;
}
return false;
}
bool R_IsWallSegmentVisible(int sx1, int sx2)
{
// Does not cross a pixel.
if (sx2 <= sx1)
return false;
cliprange_t *start = solidsegs;
while (start->last < sx2)
start++;
if (sx1 >= start->first && sx2 <= start->last)
{
// The clippost contains the new span.
return false;
}
return true;
}
bool R_ClipWallSegment(int first, int last, bool solid, VisibleSegmentCallback callback)
{
cliprange_t *next, *start;
int i, j;
bool res = false;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = solidsegs;
while (start->last < first)
start++;
if (first < start->first)
{
res = true;
if (last <= start->first)
{
// Post is entirely visible (above start).
if (!callback(first, last))
return true;
// Insert a new clippost for solid walls.
if (solid)
{
if (last == start->first)
{
start->first = first;
}
else
{
next = newend;
newend++;
while (next != start)
{
*next = *(next - 1);
next--;
}
next->first = first;
next->last = last;
}
}
return true;
}
// There is a fragment above *start.
if (!callback(first, start->first) && solid)
{
start->first = first;
}
}
// Bottom contained in start?
if (last <= start->last)
return res;
bool clipsegment;
next = start;
while (last >= (next + 1)->first)
{
// There is a fragment between two posts.
clipsegment = callback(next->last, (next + 1)->first);
next++;
if (last <= next->last)
{
// Bottom is contained in next.
last = next->last;
goto crunch;
}
}
// There is a fragment after *next.
clipsegment = callback(next->last, last);
crunch:
if (!clipsegment)
{
return true;
}
if (solid)
{
// Adjust the clip size.
start->last = last;
if (next != start)
{
// Remove start+1 to next from the clip list,
// because start now covers their area.
for (i = 1, j = (int)(newend - next); j > 0; i++, j--)
{
start[i] = next[i];
}
newend = start + i;
}
}
return true;
}
} }

View File

@ -3,14 +3,10 @@
namespace swrenderer namespace swrenderer
{ {
struct cliprange_t typedef bool(*VisibleSegmentCallback)(int x1, int x2);
{
short first, last;
};
// newend is one past the last valid seg
extern cliprange_t *newend;
extern cliprange_t solidsegs[MAXWIDTH/2+2];
void R_ClearClipSegs(short left, short right); void R_ClearClipSegs(short left, short right);
bool R_ClipWallSegment(int x1, int x2, bool solid, VisibleSegmentCallback callback);
bool R_CheckClipWallSegment(int first, int last);
bool R_IsWallSegmentVisible(int x1, int x2);
} }

View File

@ -1587,7 +1587,7 @@ ptrdiff_t R_NewOpening (ptrdiff_t len)
// A wall segment will be drawn between start and stop pixels (inclusive). // A wall segment will be drawn between start and stop pixels (inclusive).
// //
void R_StoreWallRange (int start, int stop) bool R_StoreWallRange (int start, int stop)
{ {
int i; int i;
bool maskedtexture = false; bool maskedtexture = false;
@ -1827,7 +1827,8 @@ void R_StoreWallRange (int start, int stop)
if(fake3D & 7) { if(fake3D & 7) {
ds_p++; ds_p++;
return;
return !(fake3D & FAKE3D_FAKEMASK);
} }
// save sprite clipping info // save sprite clipping info
@ -1888,6 +1889,8 @@ void R_StoreWallRange (int start, int stop)
} }
ds_p++; ds_p++;
return !(fake3D & FAKE3D_FAKEMASK);
} }
int R_CreateWallSegmentY(short *outbuf, double z1, double z2, const FWallCoords *wallc) int R_CreateWallSegmentY(short *outbuf, double z1, double z2, const FWallCoords *wallc)

View File

@ -28,6 +28,7 @@ namespace swrenderer
struct drawseg_t; struct drawseg_t;
bool R_StoreWallRange(int start, int stop);
void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2); void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2);
extern short *openings; extern short *openings;