- clipper rework

* let the clipper work on relative angles to simplify the math.
* properly initialize the initial visible range and preserve it for multiple invocations.
* track the maximum visible angular range per sector. While possibly not sufficient to handle every edge case imaginable it has low overhead and is still useful to eliminate obvious cases that do not need more complex checks. It is enough to fix the blue door in Duke E3L4.
* removed unused elements of the clipper.
This commit is contained in:
Christoph Oelckers 2021-04-24 12:08:38 +02:00
parent c05df44ad4
commit be08a2f800
6 changed files with 108 additions and 228 deletions

View file

@ -70,6 +70,11 @@ void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view, binangle a1, b
// Reverse the orientation so that startangle and endangle are properly ordered. // Reverse the orientation so that startangle and endangle are properly ordered.
wall[i].clipangle = clipper->PointToAngle(wall[i].pos); wall[i].clipangle = clipper->PointToAngle(wall[i].pos);
} }
for (int i = 0; i < numsectors; i++)
{
sectstartang[i] = -1;
sectendang[i] = -1;
}
} }
//========================================================================== //==========================================================================
@ -193,16 +198,37 @@ int BunchDrawer::ClipLine(int line, bool portal)
{ {
auto wal = &wall[line]; auto wal = &wall[line];
auto startAngle = wal->clipangle; auto startAngleBam = wal->clipangle;
auto endAngle = wall[wal->point2].clipangle; auto endAngleBam = wall[wal->point2].clipangle;
// Back side, i.e. backface culling - read: endAngle >= startAngle! // Back side, i.e. backface culling - read: endAngle <= startAngle!
if (startAngle.asbam() - endAngle.asbam() < ANGLE_180) if (startAngleBam.asbam() - endAngleBam.asbam() < ANGLE_180)
{ {
return CL_Skip; return CL_Skip;
} }
// convert to clipper coordinates and clamp to valid range.
int startAngle = startAngleBam.asbam() - ang1.asbam();
int endAngle = endAngleBam.asbam() - ang1.asbam();
if (startAngle < 0) startAngle = 0;
if (endAngle < 0) endAngle = INT_MAX;
if (!portal && !clipper->SafeCheckRange(startAngle, endAngle)) // since these values are derived from previous calls of this function they cannot be out of range.
int sect = wal->sector;
int sectStartAngle = sectstartang[sect];
auto sectEndAngle = sectendang[sect];
// check against the maximum possible viewing range of the sector.
// Todo: check if this is sufficient or if we really have to do a more costly check against the single visible segments.
if (sectStartAngle != -1)
{
if (sectStartAngle > endAngle || sectEndAngle < startAngle)
return CL_Skip; // completely outside the valid range for this sector.
if (sectStartAngle > startAngle) startAngle = sectStartAngle;
if (sectEndAngle < endAngle) endAngle = sectEndAngle;
if (endAngle <= startAngle) return CL_Skip; // can this even happen?
}
if (!portal && !clipper->IsRangeVisible(startAngle, endAngle))
{ {
return CL_Skip; return CL_Skip;
} }
@ -210,12 +236,26 @@ int BunchDrawer::ClipLine(int line, bool portal)
if (wal->nextwall == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal)) if (wal->nextwall == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal))
{ {
// one-sided // one-sided
if (!portal) clipper->SafeAddClipRange(startAngle, endAngle); if (!portal) clipper->AddClipRange(startAngle, endAngle);
return CL_Draw; return CL_Draw;
} }
else else
{ {
if (portal) clipper->SafeRemoveClipRange(startAngle, endAngle); if (portal) clipper->RemoveClipRange(startAngle, endAngle);
// set potentially visible viewing range for this line's back sector.
int nsect = wal->nextsector;
if (sectstartang[nsect] == -1)
{
sectstartang[nsect] = startAngle;
sectendang[nsect] = endAngle;
}
else
{
if (startAngle < sectstartang[nsect]) sectstartang[nsect] = startAngle;
if (endAngle > sectendang[nsect]) sectendang[nsect] = endAngle;
}
return CL_Draw | CL_Pass; return CL_Draw | CL_Pass;
} }
} }
@ -529,6 +569,14 @@ void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool p
//Printf("----------------------------------------- \nstart at sector %d\n", viewsectors[0]); //Printf("----------------------------------------- \nstart at sector %d\n", viewsectors[0]);
auto process = [&]() auto process = [&]()
{ {
clipper->Clear(ang1);
for (unsigned i = 0; i < sectcount; i++)
{
sectstartang[viewsectors[i]] = 0;
sectendang[viewsectors[i]] = int (ang2.asbam() - ang1.asbam());
}
for (unsigned i = 0; i < sectcount; i++) for (unsigned i = 0; i < sectcount; i++)
ProcessSector(viewsectors[i], portal); ProcessSector(viewsectors[i], portal);
while (Bunches.Size() > 0) while (Bunches.Size() > 0)
@ -550,12 +598,11 @@ void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount, bool p
// The BunchInFront check can fail with angles that may wrap around. // The BunchInFront check can fail with angles that may wrap around.
auto rotang = di->Viewpoint.RotAngle; auto rotang = di->Viewpoint.RotAngle;
ang1 = bamang(rotang - ANGLE_90); ang1 = bamang(rotang - ANGLE_90);
ang2 = bamang(rotang + ANGLE_90); ang2 = bamang(rotang + ANGLE_90 - 1);
process(); process();
clipper->Clear();
gotsector2.Zero(); gotsector2.Zero();
ang1 = bamang(rotang + ANGLE_90); ang1 = bamang(rotang + ANGLE_90);
ang2 = bamang(rotang - ANGLE_90); ang2 = bamang(rotang - ANGLE_90 - 1);
process(); process();
} }
Bsp.Unclock(); Bsp.Unclock();

View file

@ -32,6 +32,8 @@ class BunchDrawer
FixedBitArray<MAXWALLS> gotwall; FixedBitArray<MAXWALLS> gotwall;
binangle ang1, ang2; binangle ang1, ang2;
int sectstartang[MAXSECTORS], sectendang[MAXSECTORS];
private: private:
enum enum

View file

@ -40,12 +40,6 @@
#include "build.h" #include "build.h"
#include "printf.h" #include "printf.h"
unsigned Clipper::starttime;
Clipper::Clipper()
{
starttime++;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -74,20 +68,11 @@ void Clipper::RemoveRange(ClipNode * range)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Clipper::Clear() void Clipper::Clear(binangle rangestart)
{ {
ClipNode *node = cliphead; ClipNode *node = cliphead;
ClipNode *temp; ClipNode *temp;
blocked = false;
while (node != nullptr)
{
temp = node;
node = node->next;
Free(temp);
}
node = silhouette;
while (node != nullptr) while (node != nullptr)
{ {
temp = node; temp = node;
@ -96,30 +81,17 @@ void Clipper::Clear()
} }
cliphead = nullptr; cliphead = nullptr;
silhouette = nullptr;
starttime++;
}
//----------------------------------------------------------------------------- if (visibleStart.asbam() != 0 || visibleEnd.asbam() != 0)
//
// SetSilhouette
//
//-----------------------------------------------------------------------------
void Clipper::SetSilhouette()
{
ClipNode *node = cliphead;
ClipNode *last = nullptr;
while (node != nullptr)
{ {
ClipNode *snode = NewRange(node->start, node->end); int vstart = int(visibleStart.asbam() - rangestart.asbam());
if (silhouette == nullptr) silhouette = snode; if (vstart > 1) AddClipRange(0, vstart - 1);
snode->prev = last;
if (last != nullptr) last->next = snode; int vend = int(visibleEnd.asbam() - rangestart.asbam());
last = snode; if (vend > 0 && vend < INT_MAX - 1) AddClipRange(vend + 1, INT_MAX);
node = node->next;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -128,16 +100,16 @@ void Clipper::SetSilhouette()
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool Clipper::IsRangeVisible(binangle startAngle, binangle endAngle) bool Clipper::IsRangeVisible(int startAngle, int endAngle)
{ {
ClipNode *ci; ClipNode *ci;
ci = cliphead; ci = cliphead;
if (endAngle.asbam()==0 && ci && ci->start==0) return false; if (endAngle == 0 && ci && ci->start==0) return false;
while (ci != nullptr && ci->start < endAngle.asbam()) while (ci != nullptr && ci->start < endAngle)
{ {
if (startAngle.asbam() >= ci->start && endAngle.asbam() <= ci->end) if (startAngle >= ci->start && endAngle <= ci->end)
{ {
return false; return false;
} }
@ -153,9 +125,8 @@ bool Clipper::IsRangeVisible(binangle startAngle, binangle endAngle)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Clipper::AddClipRange(binangle start_, binangle end_) void Clipper::AddClipRange(int start, int end)
{ {
auto start = start_.asbam(), end = end_.asbam();
ClipNode *node, *temp, *prevNode; ClipNode *node, *temp, *prevNode;
if (cliphead) if (cliphead)
@ -259,42 +230,7 @@ void Clipper::AddClipRange(binangle start_, binangle end_)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Clipper::RemoveClipRange(binangle start_, binangle end_) void Clipper::RemoveClipRange(int start, int end)
{
auto start = start_.asbam(), end = end_.asbam();
ClipNode *node;
if (silhouette)
{
node = silhouette;
while (node != nullptr && node->end <= start)
{
node = node->next;
}
if (node != nullptr && node->start <= start)
{
if (node->end >= end) return;
start = node->end;
node = node->next;
}
while (node != nullptr && node->start < end)
{
DoRemoveClipRange(start, node->start);
start = node->end;
node = node->next;
}
if (start >= end) return;
}
DoRemoveClipRange(start, end);
}
//-----------------------------------------------------------------------------
//
// RemoveClipRange worker function
//
//-----------------------------------------------------------------------------
void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
{ {
ClipNode *node, *temp; ClipNode *node, *temp;
@ -347,15 +283,6 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the
// line from p1 to p2. The pseudoangle has the property that the ordering of
// points by true angle around p1 and ordering of points by pseudoangle are the
// same.
//
// For clipping exact angles are not needed. Only the ordering matters.
// This is about as fast as the fixed point R_PointToAngle2 but without
// the precision issues associated with that function.
//
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Clipper::DumpClipper() void Clipper::DumpClipper()

View file

@ -13,7 +13,7 @@ class ClipNode
friend class Clipper; friend class Clipper;
ClipNode *prev, *next; ClipNode *prev, *next;
angle_t start, end; int start, end;
bool operator== (const ClipNode &other) bool operator== (const ClipNode &other)
{ {
@ -24,27 +24,23 @@ class ClipNode
class Clipper class Clipper
{ {
static unsigned starttime;
FMemArena nodearena; FMemArena nodearena;
ClipNode * freelist = nullptr; ClipNode * freelist = nullptr;
ClipNode * clipnodes = nullptr; ClipNode * clipnodes = nullptr;
ClipNode * cliphead = nullptr; ClipNode * cliphead = nullptr;
ClipNode * silhouette = nullptr; // will be preserved even when RemoveClipRange is called
vec2_t viewpoint; vec2_t viewpoint;
bool blocked = false; void RemoveRange(ClipNode* cn);
binangle visibleStart, visibleEnd;
bool IsRangeVisible(binangle startangle, binangle endangle); public:
void RemoveRange(ClipNode * cn); bool IsRangeVisible(int startangle, int endangle);
void AddClipRange(binangle startangle, binangle endangle); void AddClipRange(int startangle, int endangle);
void RemoveClipRange(binangle startangle, binangle endangle); void RemoveClipRange(int startangle, int endangle);
public: public:
Clipper(); void Clear(binangle rangestart);
void Clear();
static binangle AngleToPseudo(binangle ang);
void Free(ClipNode *node) void Free(ClipNode *node)
{ {
@ -64,7 +60,7 @@ private:
else return (ClipNode*)nodearena.Alloc(sizeof(ClipNode)); else return (ClipNode*)nodearena.Alloc(sizeof(ClipNode));
} }
ClipNode * NewRange(angle_t start, angle_t end) ClipNode * NewRange(int start, int end)
{ {
ClipNode * c = GetNew(); ClipNode * c = GetNew();
@ -74,8 +70,6 @@ private:
return c; return c;
} }
void DoRemoveClipRange(angle_t start, angle_t end);
public: public:
void SetViewpoint(const vec2_t &vp) void SetViewpoint(const vec2_t &vp)
@ -83,88 +77,36 @@ public:
viewpoint = vp; viewpoint = vp;
} }
void SetSilhouette(); void SetVisibleRange(angle_t a1, angle_t a2)
bool SafeCheckRange(binangle startAngle, binangle endAngle)
{ {
if(startAngle.asbam() > endAngle.asbam()) if (a2 != 0xffffffff)
{ {
return (IsRangeVisible(startAngle, bamang(ANGLE_MAX)) || IsRangeVisible(bamang(0), endAngle)); visibleStart = bamang(a1 - a2);
visibleEnd = bamang(a1 + a2);
}
else visibleStart = visibleEnd = bamang(0);
} }
return IsRangeVisible(startAngle, endAngle); void RestrictVisibleRange(binangle a1, binangle a2)
}
void SafeAddClipRange(binangle startangle, binangle endangle)
{ {
if(startangle.asbam() > endangle.asbam()) if (visibleStart == visibleEnd)
{ {
// The range has to added in two parts. visibleStart = a1;
AddClipRange(startangle, bamang(ANGLE_MAX)); visibleEnd = a2;
AddClipRange(bamang(0), endangle);
} }
else else
{ {
// Add the range as usual. if (a1.asbam() - visibleStart.asbam() < visibleEnd.asbam() - visibleStart.asbam()) visibleStart = a1;
AddClipRange(startangle, endangle); if (a2.asbam() - visibleStart.asbam() < visibleEnd.asbam() - visibleStart.asbam()) visibleStart = a2;
} }
} }
void SafeAddClipRange(const vec2_t& v1, const vec2_t& v2)
{
binangle a2 = PointToAngle(v1);
binangle a1 = PointToAngle(v2);
SafeAddClipRange(a1,a2);
}
void SafeRemoveClipRange(binangle startangle, binangle endangle)
{
if(startangle.asbam() > endangle.asbam())
{
// The range has to added in two parts.
RemoveClipRange(startangle, bamang(ANGLE_MAX));
RemoveClipRange(bamang(0), endangle);
}
else
{
// Add the range as usual.
RemoveClipRange(startangle, endangle);
}
}
void SetBlocked(bool on)
{
blocked = on;
}
bool IsBlocked() const
{
return blocked;
}
void DumpClipper(); void DumpClipper();
binangle PointToAngle(const vec2_t& pos) binangle PointToAngle(const vec2_t& pos)
{ {
vec2_t vec = pos - viewpoint; vec2_t vec = pos - viewpoint;
#if 0
if (vec.x == 0 && vec.y == 0)
{
return bamang(0);
}
else
{
double result = vec.y / double(abs(vec.x) + fabs(vec.y));
if (vec.x < 0)
{
result = 2. - result;
}
return bamang(xs_Fix<30>::ToFix(result));
}
#else
return bvectangbam(vec.x, vec.y); return bvectangbam(vec.x, vec.y);
#endif
} }

View file

@ -121,7 +121,6 @@ static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfo
void HWDrawInfo::StartScene(FRenderViewpoint& parentvp, HWViewpointUniforms* uniforms) void HWDrawInfo::StartScene(FRenderViewpoint& parentvp, HWViewpointUniforms* uniforms)
{ {
staticClipper.Clear();
mClipper = &staticClipper; mClipper = &staticClipper;
Viewpoint = parentvp; Viewpoint = parentvp;
@ -369,7 +368,6 @@ void HWDrawInfo::CreateScene(bool portal)
const auto& vp = Viewpoint; const auto& vp = Viewpoint;
angle_t a1 = FrustumAngle(); angle_t a1 = FrustumAngle();
if (a1 != 0xffffffff) mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
// reset the portal manager // reset the portal manager
portalState.StartFrame(); portalState.StartFrame();
@ -385,6 +383,9 @@ void HWDrawInfo::CreateScene(bool portal)
geoofs = { 0,0 }; geoofs = { 0,0 };
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) }; vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
if(!portal) mClipper->SetVisibleRange(vp.RotAngle, a1);
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
if (vp.SectNums) if (vp.SectNums)
@ -420,10 +421,9 @@ void HWDrawInfo::CreateScene(bool portal)
if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp[i]; if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp[i];
} }
mClipper->Clear();
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
mDrawer.RenderScene(&drawsect, 1, false); mDrawer.RenderScene(&drawsect, 1, false);
for (int i = 0; i < eff.geocnt; i++) for (int i = 0; i < eff.geocnt; i++)
@ -452,8 +452,6 @@ void HWDrawInfo::CreateScene(bool portal)
if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp2[i]; if (eff.geosector[i] == effsect) drawsect = eff.geosectorwarp2[i];
} }
mClipper->Clear();
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1)); if (a1 != 0xffffffff) mDrawer.Init(this, mClipper, view, bamang(vp.RotAngle - a1), bamang(vp.RotAngle + a1));
else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0)); else mDrawer.Init(this, mClipper, view, bamang(0), bamang(0));
mDrawer.RenderScene(&drawsect, 1, false); mDrawer.RenderScene(&drawsect, 1, false);

View file

@ -417,36 +417,7 @@ void HWScenePortalBase::DrawContents(HWDrawInfo* di, FRenderState& state)
void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper) void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
{ {
auto outer_di = di->outer; clipper->SetVisibleRange(di->Viewpoint.RotAngle, di->FrustumAngle());
#if 0 // todo: fixme or remove - Unlike for Doom this won't be of great benefit with Build's rendering approach.
// This requires maximum precision, so convert everything to double.
DAngle angleOffset = deltaangle(DAngle(outer_di->Viewpoint.HWAngles.Yaw.Degrees), DAngle(di->Viewpoint.HWAngles.Yaw.Degrees));
clipper->Clear();
auto& vp = di->Viewpoint;
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
// Set the clipper to the minimal visible area
clipper->SafeAddClipRange(bamang(0), bamang(0xffffffff));
for (unsigned int i = 0; i < lines.Size(); i++)
{
binangle startang = bvectangbam(lines[i].seg->x - view.x, lines[i].seg->y - view.y);
binangle endang = bvectangbam(wall[lines[i].seg->point2].x - view.x, wall[lines[i].seg->point2].y - view.y);
if (endang.asbam() - startang.asbam() >= ANGLE_180)
{
clipper->SafeRemoveClipRange(startang, endang);
}
}
#endif
// and finally clip it to the visible area
angle_t a1 = di->FrustumAngle();
if (a1 < ANGLE_180) clipper->SafeAddClipRange(bamang(di->Viewpoint.RotAngle + a1), bamang(di->Viewpoint.RotAngle - a1));
// lock the parts that have just been clipped out.
//clipper->SetSilhouette();
} }
@ -596,14 +567,11 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
di->SetClipLine(line); di->SetClipLine(line);
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
clipper->Clear(); ClearClipper(di, clipper);
angle_t af = di->FrustumAngle();
if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af));
auto startan = bvectangbam(line->x - newx, line->y - newy); auto startan = bvectangbam(line->x - newx, line->y - newy);
auto endan = bvectangbam(wall[line->point2].x - newx, wall[line->point2].y - newy); auto endan = bvectangbam(wall[line->point2].x - newx, wall[line->point2].y - newy);
clipper->SafeAddClipRange(startan, endan); // we check the line from the backside so angles are reversed. clipper->RestrictVisibleRange(endan, startan); // we check the line from the backside so angles are reversed.
return true; return true;
} }
@ -668,14 +636,12 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
di->SetClipLine(line); di->SetClipLine(line);
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
clipper->Clear();
angle_t af = di->FrustumAngle(); ClearClipper(di, clipper);
if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af));
auto startan = bvectangbam(origin->x - origx, origin->y - origy); auto startan = bvectangbam(origin->x - origx, origin->y - origy);
auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy);
clipper->SafeAddClipRange(endan, startan); clipper->RestrictVisibleRange(startan, endan);
return true; return true;
} }
@ -722,14 +688,12 @@ bool HWLineToSpritePortal::Setup(HWDrawInfo* di, FRenderState& rstate, Clipper*
di->SetClipLine(line); di->SetClipLine(line);
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1)); di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
clipper->Clear();
angle_t af = di->FrustumAngle(); ClearClipper(di, clipper);
if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af));
auto startan = bvectangbam(origin->x - origx, origin->y - origy); auto startan = bvectangbam(origin->x - origx, origin->y - origy);
auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy); auto endan = bvectangbam(wall[origin->point2].x - origx, wall[origin->point2].y - origy);
clipper->SafeAddClipRange(endan, startan); clipper->RestrictVisibleRange(startan, endan);
return true; return true;
} }