r_bsp.cpp: merge R_ClipSolidWallSegment and R_ClipPassWallSegment into one templated function

Prep for creating a third variant. Control flow is largely
the same between these two leveraging if constexpr seems
appropriate.

Also splits the crunch goto label away into a new function
called R_CrunchWallSegment.
This commit is contained in:
James R 2023-04-05 00:05:00 -07:00
parent ccd5f3bfc4
commit d55b1b194a

View file

@ -90,13 +90,40 @@ void R_ClearDrawSegs(void)
static cliprange_t *newend; static cliprange_t *newend;
static cliprange_t solidsegs[MAXSEGS]; static cliprange_t solidsegs[MAXSEGS];
// namespace
// R_ClipSolidWallSegment {
// Does handle solid walls,
// e.g. single sided LineDefs (middle texture) enum class ClipType
// that entirely block the view. {
// // Does handle solid walls,
static void R_ClipSolidWallSegment(INT32 first, INT32 last) // e.g. single sided LineDefs (middle texture)
// that entirely block the view.
kSolid,
// 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.
kPass,
};
void R_CrunchWallSegment(cliprange_t *start, cliprange_t *next)
{
// Remove start+1 to next from the clip list, because start now covers their area.
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");
}
template <ClipType Type>
void R_ClipWallSegment(INT32 first, INT32 last)
{ {
cliprange_t *next; cliprange_t *next;
cliprange_t *start; cliprange_t *start;
@ -112,26 +139,35 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
{ {
// Post is entirely visible (above start), so insert a new clippost. // Post is entirely visible (above start), so insert a new clippost.
R_StoreWallRange(first, last); 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) if constexpr (Type != ClipType::kPass)
{ {
*next = *(next-1); next = newend;
next--; 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;
} }
next->first = first;
next->last = last;
return; return;
} }
// There is a fragment above *start. // There is a fragment above *start.
R_StoreWallRange(first, start->first - 1); R_StoreWallRange(first, start->first - 1);
// Now adjust the clip size.
start->first = first; if constexpr (Type != ClipType::kPass)
{
// Now adjust the clip size.
start->first = first;
}
} }
// Bottom contained in start? // Bottom contained in start?
@ -142,84 +178,36 @@ static void R_ClipSolidWallSegment(INT32 first, INT32 last)
while (last >= (next+1)->first - 1) while (last >= (next+1)->first - 1)
{ {
// There is a fragment between two posts. // There is a fragment between two posts.
R_StoreWallRange(next->last + 1, (next+1)->first - 1); R_StoreWallRange(start->last + 1, (start+1)->first - 1);
next++; next++;
if (last <= next->last) if (last <= next->last)
{ {
// Bottom is contained in next. if constexpr (Type != ClipType::kPass)
// Adjust the clip size. {
start->last = next->last; // Bottom is contained in next.
goto crunch; // Adjust the clip size.
} start->last = next->last;
} R_CrunchWallSegment(start, next);
}
// 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; 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. // There is a fragment after *next.
R_StoreWallRange(start->last + 1, last); R_StoreWallRange(start->last + 1, last);
if constexpr (Type != ClipType::kPass)
{
// Adjust the clip size.
start->last = last;
R_CrunchWallSegment(start, next);
}
} }
}; // namespace
// //
// R_ClearClipSegs // R_ClearClipSegs
// //
@ -641,11 +629,11 @@ static void R_AddLine(seg_t *line)
return; return;
clippass: clippass:
R_ClipPassWallSegment(x1, x2 - 1); R_ClipWallSegment<ClipType::kPass>(x1, x2 - 1);
return; return;
clipsolid: clipsolid:
R_ClipSolidWallSegment(x1, x2 - 1); R_ClipWallSegment<ClipType::kSolid>(x1, x2 - 1);
} }
// //