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

View file

@ -47,7 +47,7 @@
//
//-----------------------------------------------------------------------------
void Clipper::RemoveRange(ClipNode * range)
void Clipper::RemoveRange(ClipNode * range, bool free)
{
if (range == cliphead)
{
@ -60,7 +60,7 @@ void Clipper::RemoveRange(ClipNode * range)
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(!prev || prev->end <= node->start);
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)
{
node->next = prev->next;
@ -102,7 +128,7 @@ bool Clipper::InsertRange(ClipNode* prev, ClipNode* node)
}
#endif
return true;
return false;
}
//-----------------------------------------------------------------------------
@ -130,8 +156,12 @@ void Clipper::SplitRange(ClipNode* node, int start, int end, float topclip, floa
}
else
{
// remove and reinsert to do proper checks of the clipping window.
auto prev = node->prev;
RemoveRange(node, false);
node->topclip = topclip;
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.
}
// the 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))
// the unaltered new range is more narrow than the old one - just shorten the old one and go on.
else if (topclip <= bottomclip || (topclip < node->topclip && bottomclip > node->bottomclip))
{
node->end = start;
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);
start = nodeend;
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.
}
// the 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))
// the unaltered new range is more narrow than the old one - just shorten the old one and go on.
else if (topclip <= bottomclip || (topclip < node->topclip && bottomclip > node->bottomclip))
{
node->start = end;
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);
end = node->start;
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;
}
void RemoveRange(ClipNode* cn);
void RemoveRange(ClipNode* cn, bool free = true);
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);
public: