- fixed: It may happen that a degenerate subsector ends up without any section or sector. Try to assign the best fit in such a case so that the relevant pointers are not null.

This commit is contained in:
Christoph Oelckers 2018-11-11 09:33:40 +01:00
parent c946edd9bf
commit 094afdfd5f
2 changed files with 87 additions and 4 deletions

View file

@ -184,6 +184,33 @@ public:
{ {
CompileSections(pair->Value, rawsections); CompileSections(pair->Value, rawsections);
} }
// Make sure that all subsectors have a sector. In some degenerate cases a subsector may come up empty.
// An example is in Doom.wad E3M4 near linedef 1087. With the grouping data here this is relatively easy to fix.
sector_t *lastsector = &level.sectors[0];
for (auto &rawsection : rawsections)
{
sector_t *mysector = nullptr;
bool missing = false;
for (auto num : rawsection)
{
auto &sub = level.subsectors[num];
if (sub.sector == nullptr) missing = true;
else mysector = sub.sector;
}
// Should the worst case happen and no sector be found, use the last used one. Subsectors must not be sector-less!
if (mysector == nullptr) mysector = lastsector;
else lastsector = mysector;
for (auto num : rawsection)
{
auto &sub = level.subsectors[num];
if (sub.sector == nullptr)
{
sub.sector = mysector;
}
}
}
subsectormap.Clear(); subsectormap.Clear();
return rawsections; return rawsections;
} }
@ -253,8 +280,7 @@ public:
{ {
MakeOutline(list, lineForSeg); MakeOutline(list, lineForSeg);
} }
rawsections.Clear(); rawsections.Reset();
rawsections.ShrinkToFit();
// Assign partners after everything has been collected // Assign partners after everything has been collected
for (auto &section : sections) for (auto &section : sections)
@ -720,8 +746,59 @@ public:
curgroup++; curgroup++;
} }
} }
};
//=============================================================================
//
// Check if some subsectors have come up empty on sections.
// In this case assign the best fit from the containing sector.
// This is only to ensure that the section pointer is not null.
// These are always degenerate and do not produce any actual render output.
//
//=============================================================================
void FixMissingReferences()
{
for (auto &sub : level.subsectors)
{
if (sub.section == nullptr)
{
int sector = sub.sector->Index();
int mapsection = sub.mapsection;
auto sections = level.sections.SectionsForSector(sector);
FSection *bestfit = nullptr;
for (auto &section : sections)
{
if (bestfit == nullptr)
{
bestfit = &section;
}
else if (bestfit->mapsection != section.mapsection && section.mapsection == mapsection)
{
bestfit = &section;
}
else if (section.mapsection == mapsection)
{
BoundingRect rc;
for (unsigned i = 0; i < sub.numlines; i++)
{
rc.addVertex(sub.firstline[i].v1->fX(), sub.firstline[i].v1->fY());
rc.addVertex(sub.firstline[i].v2->fX(), sub.firstline[i].v2->fY());
}
// Pick the one closer to this subsector.
if (rc.distanceTo(section.bounds) < rc.distanceTo(bestfit->bounds))
{
bestfit = &section;
}
}
}
// This should really never happen, but better be safe than sorry and assign at least something.
if (bestfit == nullptr) bestfit = &level.sections.allSections[0];
sub.section = bestfit;
}
}
}
};
//============================================================================= //=============================================================================
@ -787,6 +864,7 @@ void CreateSections(FSectionContainer &container)
creat.FindOuterLoops(); creat.FindOuterLoops();
creat.GroupSections(); creat.GroupSections();
creat.ConstructOutput(container); creat.ConstructOutput(container);
creat.FixMissingReferences();
} }
CCMD(printsections) CCMD(printsections)

View file

@ -458,7 +458,12 @@ public:
void Reset() void Reset()
{ {
Clear(); Clear();
ShrinkToFit(); Most = 0;
if (Array != nullptr)
{
M_Free(Array);
Array = nullptr;
}
} }
private: private:
T *Array; T *Array;