diff --git a/src/swrenderer/scene/r_bsp.cpp b/src/swrenderer/scene/r_bsp.cpp index 24937c7a9..2b3054e4f 100644 --- a/src/swrenderer/scene/r_bsp.cpp +++ b/src/swrenderer/scene/r_bsp.cpp @@ -96,148 +96,6 @@ WORD MirrorFlags; 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. // @@ -703,7 +561,7 @@ void R_AddLine (seg_t *line) #endif } - if (R_ClipWallSegment (WallC.sx1, WallC.sx2, solid)) + if (R_ClipWallSegment(WallC.sx1, WallC.sx2, solid, R_StoreWallRange)) { InSubsector->flags |= SSECF_DRAWN; } @@ -836,8 +694,6 @@ static bool R_CheckBBox (float *bspcoord) // killough 1/28/98: static double rx1, ry1, rx2, ry2; int sx1, sx2; - cliprange_t* start; - // Find the corners of the box // that define the edges from current viewpoint. 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 // (adjacent pixels are touching). - // Does not cross a pixel. - 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; + return R_IsWallSegmentVisible(sx1, sx2); } diff --git a/src/swrenderer/scene/r_clip_segment.cpp b/src/swrenderer/scene/r_clip_segment.cpp index 1c4da9214..4db069a49 100644 --- a/src/swrenderer/scene/r_clip_segment.cpp +++ b/src/swrenderer/scene/r_clip_segment.cpp @@ -26,8 +26,16 @@ namespace swrenderer { - cliprange_t *newend; - cliprange_t solidsegs[MAXWIDTH/2+2]; + namespace + { + struct cliprange_t + { + short first, last; + }; + + cliprange_t *newend; // newend is one past the last valid seg + cliprange_t solidsegs[MAXWIDTH / 2 + 2]; + } void R_ClearClipSegs(short left, short right) { @@ -37,4 +45,145 @@ namespace swrenderer solidsegs[1].last = 0x7fff; 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; + } } diff --git a/src/swrenderer/scene/r_clip_segment.h b/src/swrenderer/scene/r_clip_segment.h index ce6fffe07..3ebe464d8 100644 --- a/src/swrenderer/scene/r_clip_segment.h +++ b/src/swrenderer/scene/r_clip_segment.h @@ -3,14 +3,10 @@ namespace swrenderer { - struct cliprange_t - { - short first, last; - }; - - // newend is one past the last valid seg - extern cliprange_t *newend; - extern cliprange_t solidsegs[MAXWIDTH/2+2]; - + typedef bool(*VisibleSegmentCallback)(int x1, int x2); + 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); } diff --git a/src/swrenderer/scene/r_segs.cpp b/src/swrenderer/scene/r_segs.cpp index 5be89ecb0..f23a9326b 100644 --- a/src/swrenderer/scene/r_segs.cpp +++ b/src/swrenderer/scene/r_segs.cpp @@ -1587,7 +1587,7 @@ ptrdiff_t R_NewOpening (ptrdiff_t len) // 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; bool maskedtexture = false; @@ -1827,7 +1827,8 @@ void R_StoreWallRange (int start, int stop) if(fake3D & 7) { ds_p++; - return; + + return !(fake3D & FAKE3D_FAKEMASK); } // save sprite clipping info @@ -1888,6 +1889,8 @@ void R_StoreWallRange (int start, int stop) } ds_p++; + + return !(fake3D & FAKE3D_FAKEMASK); } int R_CreateWallSegmentY(short *outbuf, double z1, double z2, const FWallCoords *wallc) diff --git a/src/swrenderer/scene/r_segs.h b/src/swrenderer/scene/r_segs.h index 20cba123b..f9b235872 100644 --- a/src/swrenderer/scene/r_segs.h +++ b/src/swrenderer/scene/r_segs.h @@ -28,6 +28,7 @@ namespace swrenderer struct drawseg_t; +bool R_StoreWallRange(int start, int stop); void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2); extern short *openings;