- fixed glitches with some poorly set up sector stack portals.

This commit is contained in:
Christoph Oelckers 2019-02-04 13:06:54 +01:00
parent 20f29ab808
commit af9636b7c3
7 changed files with 182 additions and 220 deletions

View file

@ -67,7 +67,6 @@ void GLBuffer::Bind()
void GLBuffer::SetData(size_t size, const void *data, bool staticdata) void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
{ {
assert(nomap); // once it's mappable, it cannot be recreated anymore.
Bind(); Bind();
if (data != nullptr) if (data != nullptr)
{ {

View file

@ -500,7 +500,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
// //
// //
// //
if ((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z) if ((which & SSRF_RENDERFLOOR) && frontsector->floorplane.ZatPoint(vp.Pos) <= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERFLOOR)))
{ {
// process the original floor first. // process the original floor first.
@ -554,9 +554,9 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
// //
// do ceilings // do ceilings
// //
//
// //
// if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z)
{ {
// process the original ceiling first. // process the original ceiling first.

View file

@ -1173,218 +1173,3 @@ void HWDrawInfo::HandleHackedSubsectors()
SubsectorHacks.Clear(); SubsectorHacks.Clear();
} }
// This code was meant to fix the portal in KDIZD's Z1M1, but later versions of that mod do not need it anymore.
// I am not aware of other portals ever having been set up so badly as this one so it probably is not needed anymore.
// Even if needed this must be done differently because this code depends on hacking the render data in a bad way.
#if 0
//==========================================================================
//
// This merges visplanes that lie inside a sector stack together
// to avoid rendering these unneeded flats
//
//==========================================================================
void HWDrawInfo::AddFloorStack(sector_t * sec)
{
FloorStacks.Push(sec);
}
void HWDrawInfo::AddCeilingStack(sector_t * sec)
{
CeilingStacks.Push(sec);
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor, area_t in_area)
{
// mark it checked
sub->validcount=validcount;
// Has a sector stack or skybox itself!
if (sub->render_sector->GetPortalGroup(sector_t::ceiling) != nullptr) return;
// Don't bother processing unrendered subsectors
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
if (me->GetTexture(sector_t::ceiling) != anchor->GetTexture(sector_t::ceiling) ||
me->ceilingplane != anchor->ceilingplane ||
me->GetCeilingLight() != anchor->GetCeilingLight() ||
me->Colormap != anchor->Colormap ||
me->SpecialColors[sector_t::ceiling] != anchor->SpecialColors[sector_t::ceiling] ||
me->planes[sector_t::ceiling].xform != anchor->planes[sector_t::ceiling].xform)
{
// different visplane so it can't belong to this stack
return;
}
HandledSubsectors.Push (sub);
for(uint32_t j=0;j<sub->numlines;j++)
{
seg_t * seg = sub->firstline + j;
if (seg->PartnerSeg)
{
subsector_t * backsub = seg->PartnerSeg->Subsector;
if (backsub->validcount!=validcount) CollectSectorStacksCeiling (backsub, anchor, in_area);
}
}
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor, area_t in_area)
{
// mark it checked
sub->validcount=validcount;
// Has a sector stack or skybox itself!
if (sub->render_sector->GetPortalGroup(sector_t::floor) != nullptr) return;
// Don't bother processing unrendered subsectors
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
// Must be the exact same visplane
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
if (me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
me->floorplane != anchor->floorplane ||
me->GetFloorLight() != anchor->GetFloorLight() ||
me->Colormap != anchor->Colormap ||
me->SpecialColors[sector_t::floor] != anchor->SpecialColors[sector_t::floor] ||
me->planes[sector_t::floor].xform != anchor->planes[sector_t::floor].xform)
{
// different visplane so it can't belong to this stack
return;
}
HandledSubsectors.Push (sub);
for(uint32_t j=0;j<sub->numlines;j++)
{
seg_t * seg = sub->firstline + j;
if (seg->PartnerSeg)
{
subsector_t * backsub = seg->PartnerSeg->Subsector;
if (backsub->validcount!=validcount) CollectSectorStacksFloor (backsub, anchor, in_area);
}
}
}
//==========================================================================
//
//
//
//==========================================================================
void HWDrawInfo::ProcessSectorStacks(area_t in_area)
{
unsigned int i;
validcount++;
for (i=0;i<CeilingStacks.Size (); i++)
{
sector_t *sec = hw_FakeFlat(CeilingStacks[i], in_area, false);
auto portal = sec->GetPortalGroup(sector_t::ceiling);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{
subsector_t * sub = sec->subsectors[k];
if (ss_renderflags[sub->Index()] & SSRF_PROCESSED)
{
HandledSubsectors.Clear();
for(uint32_t j=0;j<sub->numlines;j++)
{
seg_t * seg = sub->firstline + j;
if (seg->PartnerSeg)
{
subsector_t * backsub = seg->PartnerSeg->Subsector;
if (backsub->validcount!=validcount) CollectSectorStacksCeiling (backsub, sec, in_area);
}
}
for(unsigned int j=0;j<HandledSubsectors.Size();j++)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERCEILING;
if (sub->portalcoverage[sector_t::ceiling].subsectors == NULL)
{
BuildPortalCoverage(&sub->portalcoverage[sector_t::ceiling], sub, portal->mDisplacement);
}
AddSubsectorToPortal(portal, sub);
if (sec->GetAlpha(sector_t::ceiling) != 0 && sec->GetTexture(sector_t::ceiling) != skyflatnum)
{
gl_subsectorrendernode * node = NewSubsectorRenderNode();
node->sub = sub;
AddOtherCeilingPlane(sec->sectornum, node);
}
}
}
}
}
validcount++;
for (i=0;i<FloorStacks.Size (); i++)
{
sector_t *sec = hw_FakeFlat(FloorStacks[i], in_area, false);
auto portal = sec->GetPortalGroup(sector_t::floor);
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
{
subsector_t * sub = sec->subsectors[k];
if (ss_renderflags[sub->Index()] & SSRF_PROCESSED)
{
HandledSubsectors.Clear();
for(uint32_t j=0;j<sub->numlines;j++)
{
seg_t * seg = sub->firstline + j;
if (seg->PartnerSeg)
{
subsector_t * backsub = seg->PartnerSeg->Subsector;
if (backsub->validcount!=validcount) CollectSectorStacksFloor (backsub, sec, in_area);
}
}
for(unsigned int j=0;j<HandledSubsectors.Size();j++)
{
subsector_t *sub = HandledSubsectors[j];
ss_renderflags[sub->Index()] &= ~SSRF_RENDERFLOOR;
if (sub->portalcoverage[sector_t::floor].subsectors == NULL)
{
BuildPortalCoverage(&sub->portalcoverage[sector_t::floor], sub, portal->mDisplacement);
}
AddSubsectorToPortal(portal, sub);
if (sec->GetAlpha(sector_t::floor) != 0 && sec->GetTexture(sector_t::floor) != skyflatnum)
{
gl_subsectorrendernode * node = NewSubsectorRenderNode();
node->sub = sub;
AddOtherFloorPlane(sec->sectornum, node);
}
}
}
}
}
FloorStacks.Clear();
CeilingStacks.Clear();
}
#endif

View file

@ -163,6 +163,7 @@ private:
void InitVertexData(); void InitVertexData();
void GetSideVertices(int sdnum, DVector2 *v1, DVector2 *v2); void GetSideVertices(int sdnum, DVector2 *v1, DVector2 *v2);
void PrepareSegs(); void PrepareSegs();
void FloodSectorStacks();
void InitRenderInfo(); void InitRenderInfo();
void FixMinisegReferences(); void FixMinisegReferences();
void FixHoles(); void FixHoles();

View file

@ -35,6 +35,7 @@
#include "p_setup.h" #include "p_setup.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "maploader.h" #include "maploader.h"
#include "r_utility.h"
//========================================================================== //==========================================================================
// //
@ -527,6 +528,175 @@ void MapLoader::PrepareSegs()
} }
} }
//==========================================================================
//
// account for a bug in the original software renderer
// which did not properly check visplanes for sectors inside a portal sector
//
//==========================================================================
bool CollectSectorStacksCeiling(FSection * section, sector_t * anchor, TArray<FSection *> &HandledSections)
{
// mark it checked
section->validcount = validcount;
auto me = section->sector; // this is always the render sector.
if (me != anchor)
{
// If the plane doesn't match, this one isn't a candidate.
if (me->GetHeightSec() ||
(me->GetTexture(sector_t::ceiling) != anchor->GetTexture(sector_t::ceiling)) ||
me->ceilingplane != anchor->ceilingplane ||
me->GetCeilingLight() != anchor->GetCeilingLight() ||
me->Colormap != anchor->Colormap ||
(me->planes[sector_t::ceiling].alpha != 1. && me->planes[sector_t::ceiling].alpha != 0.) ||
me->SpecialColors[sector_t::ceiling] != anchor->SpecialColors[sector_t::ceiling] ||
me->planes[sector_t::ceiling].xform != anchor->planes[sector_t::ceiling].xform)
{
// different visplane so it can't belong to this stack
return false;
}
// Any non-stacked-sector portal will be rejected, any stacked sector portal will skip processing this subsector.
auto po = me->GetPortal(sector_t::ceiling);
if (po->mType != PORTS_SKYVIEWPOINT) // sky is the default for all sectors
{
return po->mType == PORTS_STACKEDSECTORTHING;
}
}
for (auto &segment : section->segments)
{
if (segment.partner == nullptr) return false;
auto partner = segment.partner->section;
if (partner->validcount != validcount)
{
// Abort if we found something that doesn't match
if (!CollectSectorStacksCeiling(partner, anchor, HandledSections))
{
if (section->sector != anchor)
return false;
}
}
}
HandledSections.Push(section);
return true;
}
//==========================================================================
//
//
//
//==========================================================================
bool CollectSectorStacksFloor(FSection * section, sector_t * anchor, TArray<FSection *> &HandledSections)
{
// mark it checked
section->validcount = validcount;
auto me = section->sector; // this is always the render sector.
if (me != anchor)
{
// If the plane doesn't match, this one isn't a candidate.
if (me->GetHeightSec() ||
me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
me->floorplane != anchor->floorplane ||
me->GetFloorLight() != anchor->GetFloorLight() ||
me->Colormap != anchor->Colormap ||
(me->planes[sector_t::floor].alpha != 1. && me->planes[sector_t::floor].alpha != 0.) ||
me->SpecialColors[sector_t::floor] != anchor->SpecialColors[sector_t::floor] ||
me->planes[sector_t::floor].xform != anchor->planes[sector_t::floor].xform)
{
// different visplane so it can't belong to this stack
return false;
}
// Any non-stacked-sector portal will be rejected, any stacked sector portal will skip processing this subsector.
auto po = me->GetPortal(sector_t::floor);
if (po->mType != PORTS_SKYVIEWPOINT) // sky is the default for all sectors
{
return po->mType == PORTS_STACKEDSECTORTHING;
}
}
for (auto &segment : section->segments)
{
if (segment.partner == nullptr) return false;
auto partner = segment.partner->section;
if (partner->validcount != validcount)
{
// Abort if we found something that doesn't match
if (!CollectSectorStacksFloor(partner, anchor, HandledSections))
{
if (section->sector != anchor)
return false;
}
}
}
HandledSections.Push(section);
return true;
}
//==========================================================================
//
//
//
//==========================================================================
void MapLoader::FloodSectorStacks()
{
for (auto &sector : Level->sectors)
{
auto po = sector.GetPortal(sector_t::ceiling);
if (po->mType == PORTS_STACKEDSECTORTHING && sector.planes[sector_t::ceiling].alpha == 0.)
{
TArray<FSection *> HandledSections;
for (auto &section : Level->sections.SectionsForSector(&sector))
{
auto size = HandledSections.Size();
if (!CollectSectorStacksCeiling(&section, &sector, HandledSections))
{
// Delete everything that got already collected in this iteration.
HandledSections.Resize(size);
}
}
for (auto section : HandledSections)
{
if (section->sector != &sector)
Printf("Marked section of sector %d for ceiling portal\n", section->sector->Index());
section->flags |= FSection::DONTRENDERCEILING;
}
}
po = sector.GetPortal(sector_t::floor);
if (po->mType == PORTS_STACKEDSECTORTHING && sector.planes[sector_t::floor].alpha == 0.)
{
TArray<FSection *> HandledSections;
for (auto &section : Level->sections.SectionsForSector(&sector))
{
auto size = HandledSections.Size();
if (!CollectSectorStacksFloor(&section, &sector, HandledSections))
{
// Delete everything that got already collected in this iteration.
HandledSections.Resize(size);
}
}
for (auto section : HandledSections)
{
if (section->sector != &sector)
Printf("Marked section of sector %d for floor portal\n", section->sector->Index());
section->flags |= FSection::DONTRENDERFLOOR;
}
}
}
}
//========================================================================== //==========================================================================
// //
// Initialize the level data for the GL renderer // Initialize the level data for the GL renderer
@ -538,6 +708,7 @@ void MapLoader::InitRenderInfo()
PrepareSegs(); PrepareSegs();
PrepareSectorData(); PrepareSectorData();
InitVertexData(); InitVertexData();
FloodSectorStacks();
TArray<int> checkmap(Level->vertexes.Size()); TArray<int> checkmap(Level->vertexes.Size());
memset(checkmap.Data(), -1, sizeof(int)*Level->vertexes.Size()); memset(checkmap.Data(), -1, sizeof(int)*Level->vertexes.Size());
for(auto &sec : Level->sectors) for(auto &sec : Level->sectors)
@ -782,4 +953,3 @@ void MapLoader::FixHoles()
} }
} }
} }

View file

@ -718,6 +718,7 @@ public:
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size()); dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
dest.vertexindex = -1; dest.vertexindex = -1;
dest.vertexcount = 0; dest.vertexcount = 0;
dest.flags = 0;
dest.bounds.setEmpty(); dest.bounds.setEmpty();
numsegments += group.segments.Size(); numsegments += group.segments.Size();

View file

@ -103,6 +103,11 @@ struct FSectionLine
struct FSection struct FSection
{ {
enum
{
DONTRENDERCEILING = 1,
DONTRENDERFLOOR = 2
};
// tbd: Do we need a list of subsectors here? Ideally the subsectors should not be used anywhere anymore except for finding out where a location is. // tbd: Do we need a list of subsectors here? Ideally the subsectors should not be used anywhere anymore except for finding out where a location is.
TArrayView<FSectionLine> segments; TArrayView<FSectionLine> segments;
TArrayView<side_t *> sides; // contains all sidedefs, including the internal ones that do not make up the outer shape. TArrayView<side_t *> sides; // contains all sidedefs, including the internal ones that do not make up the outer shape.
@ -115,6 +120,7 @@ struct FSection
int validcount; int validcount;
short mapsection; short mapsection;
char hacked; // 1: is part of a render hack char hacked; // 1: is part of a render hack
char flags;
}; };
class FSectionContainer class FSectionContainer