From 7c5080f6545a472e88f775e1fa90a95b96503036 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 15 Dec 2021 16:12:42 +0100 Subject: [PATCH] - reimplemented sector splitting. With the new setup this is a lot easier than with the old one. --- source/core/rendering/hw_sections.h | 1 - source/core/rendering/hw_sections2.cpp | 97 +++++++++++++++++-- .../core/rendering/scene/hw_bunchdrawer.cpp | 11 ++- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/source/core/rendering/hw_sections.h b/source/core/rendering/hw_sections.h index 592312008..60549145f 100644 --- a/source/core/rendering/hw_sections.h +++ b/source/core/rendering/hw_sections.h @@ -18,7 +18,6 @@ struct SectionLine int endpoint; int wall; int partner; - int point2index; vec2_t v1() const { return ::wall[startpoint].pos; } vec2_t v2() const { return ::wall[endpoint].pos; } diff --git a/source/core/rendering/hw_sections2.cpp b/source/core/rendering/hw_sections2.cpp index 3bb888d09..da54ee6af 100644 --- a/source/core/rendering/hw_sections2.cpp +++ b/source/core/rendering/hw_sections2.cpp @@ -518,6 +518,61 @@ static void GroupData(TArray& collect, TArray& } } +//========================================================================== +// +// handle explicit sector splits while we still have simple index arrays. +// This operates on the generated sections +// +//========================================================================== + +static void TrySplitLoop(sectionbuildsector& builder, int firstwall, int lastwall) +{ + for (unsigned s = 0; s < builder.sections.Size(); s++) + { + auto& section = builder.sections[s]; + if (section.loops.Size() > 1) + { + // Must have one loop to split a section. Should this ever be needed for sections with holes the loops need to be joined before running this. + Printf("Unable to split sector %d between walls %d and %d\n", builder.sectnum, firstwall, lastwall); + return; + } + auto& loop = section.loops[0]; + unsigned i1 = loop.Find(firstwall); + unsigned i2 = loop.Find(lastwall); + if (i1 >= loop.Size() || i2 >= loop.Size()) continue; + if (i2 < i1) std::swap(i1, i2); + TArray newloop1; + TArray newloop2; + auto it = loop.begin(); + auto end = loop.end() - 1; + while (it != end && *it != firstwall) newloop1.Push(*it++); + newloop1.Push(-firstwall); + while (it != end && *it != lastwall) newloop2.Push(*it++); + newloop2.Push(-lastwall); + while (it != end) newloop1.Push(*it++); + section.wallcount = newloop1.Size(); + newloop1.Push(loop.Last()); + section.loops[0] = std::move(newloop1); + builder.sections.Reserve(1); + auto& newsect = builder.sections.Last(); + newsect.bugged = false; + newsect.wallcount = newloop2.Size(); + newloop2.Push(loop.Last()); + newsect.loops.Resize(1); + newsect.loops[0] = std::move(newloop2); + break; + } +} + +static void SplitLoops(TArray& builders) +{ + for (unsigned i = 0; i < splits.Size(); i += 3) + { + int sector = splits[0]; + TrySplitLoop(builders[sector], splits[i + 1], splits[i + 2]); + } +} + //========================================================================== // // @@ -527,10 +582,17 @@ static void GroupData(TArray& collect, TArray& static void ConstructSections(TArray& builders) { // count all sections and allocate the global buffers. + TArray splitwalls; // Allocate all Section walls. - sectionLines.Resize(numwalls); + sectionLines.Resize(numwalls + splits.Size() * 2 / 3); + for (unsigned i = 0; i < splits.Size(); i++) + { + if (i % 3) splitwalls.Push(splits[i]); + } + + int nextwall = numwalls; for (int i = 0; i < numwalls; i++) { sectionLines[i].startpoint = i; @@ -538,6 +600,14 @@ static void ConstructSections(TArray& builders) sectionLines[i].wall = i; sectionLines[i].partner = wall[i].nextwall; } + for (int i = numwalls; i < (int)sectionLines.Size(); i++) + { + int pair = (i - numwalls); + sectionLines[i].startpoint = splitwalls[pair]; + sectionLines[i].endpoint = splitwalls[pair ^ 1]; + sectionLines[i].wall = -1; + sectionLines[i].partner = numwalls + (pair ^ 1); + } unsigned count = 0; // allocate as much as possible from the arena here. @@ -584,15 +654,25 @@ static void ConstructSections(TArray& builders) { auto& srcloop = srcsect.loops[i]; auto& loop = section->loops[i]; - unsigned numwalls = srcloop.Size() - 1; - auto walls = (int*)sectionArena.Calloc(numwalls * sizeof(int)); - loop.walls.Set(walls, numwalls); - for (unsigned w = 0; w < numwalls; w++) + unsigned numsectionwalls = srcloop.Size() - 1; + auto walls = (int*)sectionArena.Calloc(numsectionwalls * sizeof(int)); + loop.walls.Set(walls, numsectionwalls); + for (unsigned w = 0; w < numsectionwalls; w++) { int wall_i = srcloop[w]; - auto wal = §ionLines[wall_i]; - section->lines[curwall++] = loop.walls[w] = wall_i; - wal->section = section->index; + if (wall_i >= 0) + { + auto wal = §ionLines[wall_i]; + section->lines[curwall++] = loop.walls[w] = wall_i; + wal->section = section->index; + } + else + { + wall_i = numwalls + splitwalls.Find(-wall_i); + auto wal = §ionLines[wall_i]; + section->lines[curwall++] = loop.walls[w] = wall_i; + wal->section = section->index; + } } } } @@ -623,6 +703,7 @@ void hw_CreateSections2() TArray builders(numsectors, true); GroupData(collect, builders); + SplitLoops(builders); ConstructSections(builders); } diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 8d5f34b2c..c116e732e 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -221,7 +221,6 @@ int BunchDrawer::ClipLine(int aline, bool portal) return CL_Skip; } if (line >= 0 && blockwall[line]) return CL_Draw; - auto wal = &wall[line]; // convert to clipper coordinates and clamp to valid range. int startAngle = startAngleBam.asbam(); @@ -256,7 +255,10 @@ int BunchDrawer::ClipLine(int aline, bool portal) return CL_Skip; } - if (cline->partner == -1 || (wal->cstat & CSTAT_WALL_1WAY) || CheckClip(wal)) + if (line < 0) + return CL_Pass; + + if (cline->partner == -1 || (wall[line].cstat & CSTAT_WALL_1WAY) || CheckClip(&wall[line])) { // one-sided if (!portal && !dontclip) clipper->AddClipRange(startAngle, endAngle); @@ -442,7 +444,7 @@ int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2) // Find the wall in b1 that overlaps b2->startangle for (int i = b1->startline; i <= b1->endline; i++) { - endang = ClipAngle(wall[i].point2); + endang = ClipAngle(sectionLines[i].endpoint); if (endang.asbam() > anglecheck.asbam()) { // found a line @@ -468,7 +470,7 @@ int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2) // Find the wall in b2 that overlaps b1->startangle for (int i = b2->startline; i <= b2->endline; i++) { - endang = ClipAngle(wall[i].point2); + endang = ClipAngle(sectionLines[i].endpoint); if (endang.asbam() > anglecheck.asbam()) { // found a line @@ -622,6 +624,7 @@ void BunchDrawer::ProcessSection(int sectionnum, bool portal) { if (walang1.asbam() >= angrange.asbam()) { walang1 = bamang(0); inbunch = false; } if (walang2.asbam() >= angrange.asbam()) walang2 = angrange; + if (section->lines[i] >= numwalls) inbunch = false; if (!inbunch) { //Printf("Starting bunch:\n\tWall %d\n", section->lines[i]);