- fixed the clipper.

* must do proper checks for merged ranges when inserting new ones. The checking code assumes that closed ranges are contiguous.
* when discarding parts of overlapping ranges this may not use merged clip values for its checks.
* ranges that have their clip values altered must be released and reinserted to ensure everything is correct.
This commit is contained in:
Christoph Oelckers 2021-12-20 15:34:50 +01:00
parent f152a4d9b5
commit c141c89cfd
3 changed files with 45 additions and 12 deletions

View file

@ -280,8 +280,8 @@ int BunchDrawer::ClipLine(int aline, bool portal)
if (!portal && !dontclip) if (!portal && !dontclip)
{ {
clipper->AddClipRange(startAngle, endAngle); clipper->AddClipRange(startAngle, endAngle);
Printf("\nWall %d from %2.3f - %2.3f (blocking)\n", line, bamang(startAngle).asdeg(), bamang(endAngle).asdeg()); //Printf("\nWall %d from %2.3f - %2.3f (blocking)\n", line, bamang(startAngle).asdeg(), bamang(endAngle).asdeg());
clipper->DumpClipper(); //clipper->DumpClipper();
} }
return CL_Draw; return CL_Draw;
} }
@ -293,8 +293,8 @@ int BunchDrawer::ClipLine(int aline, bool portal)
if (topclip < FLT_MAX || bottomclip > -FLT_MAX) if (topclip < FLT_MAX || bottomclip > -FLT_MAX)
{ {
clipper->AddWindowRange(startAngle, endAngle, topclip, bottomclip, viewz); clipper->AddWindowRange(startAngle, endAngle, topclip, bottomclip, viewz);
Printf("\nWall %d from %2.3f - %2.3f, (%2.3f, %2.3f) (passing)\n", line, bamang(startAngle).asdeg(), bamang(endAngle).asdeg(), topclip, bottomclip); //Printf("\nWall %d from %2.3f - %2.3f, (%2.3f, %2.3f) (passing)\n", line, bamang(startAngle).asdeg(), bamang(endAngle).asdeg(), topclip, bottomclip);
clipper->DumpClipper(); //clipper->DumpClipper();
} }
} }

View file

@ -47,7 +47,7 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Clipper::RemoveRange(ClipNode * range) void Clipper::RemoveRange(ClipNode * range, bool free)
{ {
if (range == cliphead) if (range == cliphead)
{ {
@ -60,7 +60,7 @@ void Clipper::RemoveRange(ClipNode * range)
if (range->next) range->next->prev = range->prev; if (range->next) range->next->prev = range->prev;
} }
Free(range); if (free) Free(range);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -79,6 +79,32 @@ bool Clipper::InsertRange(ClipNode* prev, ClipNode* node)
assert(node->start <= node->end); assert(node->start <= node->end);
assert(!prev || prev->end <= node->start); assert(!prev || prev->end <= node->start);
assert(!prev || !prev->next || prev->next->start >= node->end); assert(!prev || !prev->next || prev->next->start >= node->end);
if (node->topclip <= node->bottomclip)
{
if (prev)
{
if (prev->topclip <= prev->bottomclip && prev->end >= node->start)
{
prev->end = node->end;
Free(node);
if (prev->next && prev->end >= prev->next->start && prev->next->topclip <= prev->next->bottomclip)
{
prev->end = prev->next->end;
Free(prev->next);
return true;
}
return false;
}
else if (prev->next && node->end >= prev->next->start && prev->next->topclip <= prev->next->bottomclip)
{
prev->next->start = node->start;
Free(node);
return false;
}
}
}
if (prev) if (prev)
{ {
node->next = prev->next; node->next = prev->next;
@ -102,7 +128,7 @@ bool Clipper::InsertRange(ClipNode* prev, ClipNode* node)
} }
#endif #endif
return true; return false;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -130,8 +156,12 @@ void Clipper::SplitRange(ClipNode* node, int start, int end, float topclip, floa
} }
else else
{ {
// remove and reinsert to do proper checks of the clipping window.
auto prev = node->prev;
RemoveRange(node, false);
node->topclip = topclip; node->topclip = topclip;
node->bottomclip = bottomclip; node->bottomclip = bottomclip;
InsertRange(prev, node);
} }
} }
@ -444,8 +474,8 @@ void Clipper::AddWindowRange(int start, int end, float topclip, float bottomclip
if (start >= end) return; // may have been crushed to a single point. if (start >= end) return; // may have been crushed to a single point.
} }
// the new range is more narrow than the old one - just shorten the old one and go on. // the unaltered new range is more narrow than the old one - just shorten the old one and go on.
else if (mtopclip <= mbottomclip || (mtopclip < node->topclip && mbottomclip > node->bottomclip)) else if (topclip <= bottomclip || (topclip < node->topclip && bottomclip > node->bottomclip))
{ {
node->end = start; node->end = start;
assert(node->end > node->start); // ensured by initial condition. assert(node->end > node->start); // ensured by initial condition.
@ -458,6 +488,7 @@ void Clipper::AddWindowRange(int start, int end, float topclip, float bottomclip
SplitRange(node, start, nodeend, mtopclip, mbottomclip); SplitRange(node, start, nodeend, mtopclip, mbottomclip);
start = nodeend; start = nodeend;
if (start >= end) return; // may have been crushed to a single point. if (start >= end) return; // may have been crushed to a single point.
if (mtopclip <= mbottomclip) next = cliphead; // list may have become out of sync.
} }
} }
} }
@ -490,8 +521,8 @@ void Clipper::AddWindowRange(int start, int end, float topclip, float bottomclip
if (start >= end) return; // may have been crushed to a single point. if (start >= end) return; // may have been crushed to a single point.
} }
// the new range is more narrow than the old one - just shorten the old one and go on. // the unaltered new range is more narrow than the old one - just shorten the old one and go on.
else if (mtopclip <= mbottomclip || (mtopclip < node->topclip && mbottomclip > node->bottomclip)) else if (topclip <= bottomclip || (topclip < node->topclip && bottomclip > node->bottomclip))
{ {
node->start = end; node->start = end;
assert(node->end > node->start); assert(node->end > node->start);
@ -504,6 +535,7 @@ void Clipper::AddWindowRange(int start, int end, float topclip, float bottomclip
SplitRange(node, nodestart, end, mtopclip, mbottomclip); SplitRange(node, nodestart, end, mtopclip, mbottomclip);
end = node->start; end = node->start;
if (start >= end) return; // may have been crushed to a single point. if (start >= end) return; // may have been crushed to a single point.
if (mtopclip <= mbottomclip) next = cliphead; // list may have become out of sync.
} }
} }
} }

View file

@ -66,8 +66,9 @@ private:
return c; return c;
} }
void RemoveRange(ClipNode* cn); void RemoveRange(ClipNode* cn, bool free = true);
bool InsertRange(ClipNode* prev, ClipNode* node); bool InsertRange(ClipNode* prev, ClipNode* node);
bool InsertBlockingRange(ClipNode* prev, ClipNode* node, int start, int end);
void SplitRange(ClipNode* node, int start, int end, float topclip, float bottomclip); void SplitRange(ClipNode* node, int start, int end, float topclip, float bottomclip);
public: public: