mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 12:32:34 +00:00
- fixed glitches with some poorly set up sector stack portals.
This commit is contained in:
parent
20f29ab808
commit
af9636b7c3
7 changed files with 182 additions and 220 deletions
|
@ -67,7 +67,6 @@ void GLBuffer::Bind()
|
|||
|
||||
void GLBuffer::SetData(size_t size, const void *data, bool staticdata)
|
||||
{
|
||||
assert(nomap); // once it's mappable, it cannot be recreated anymore.
|
||||
Bind();
|
||||
if (data != nullptr)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
@ -556,7 +556,7 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which)
|
|||
//
|
||||
//
|
||||
//
|
||||
if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z)
|
||||
if ((which & SSRF_RENDERCEILING) && frontsector->ceilingplane.ZatPoint(vp.Pos) >= vp.Pos.Z && (!section || !(section->flags & FSection::DONTRENDERCEILING)))
|
||||
{
|
||||
// process the original ceiling first.
|
||||
|
||||
|
|
|
@ -1173,218 +1173,3 @@ void HWDrawInfo::HandleHackedSubsectors()
|
|||
|
||||
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
|
||||
|
|
|
@ -163,6 +163,7 @@ private:
|
|||
void InitVertexData();
|
||||
void GetSideVertices(int sdnum, DVector2 *v1, DVector2 *v2);
|
||||
void PrepareSegs();
|
||||
void FloodSectorStacks();
|
||||
void InitRenderInfo();
|
||||
void FixMinisegReferences();
|
||||
void FixHoles();
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "p_setup.h"
|
||||
#include "g_levellocals.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 §or : 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 §ion : Level->sections.SectionsForSector(§or))
|
||||
{
|
||||
auto size = HandledSections.Size();
|
||||
if (!CollectSectorStacksCeiling(§ion, §or, HandledSections))
|
||||
{
|
||||
// Delete everything that got already collected in this iteration.
|
||||
HandledSections.Resize(size);
|
||||
}
|
||||
}
|
||||
for (auto section : HandledSections)
|
||||
{
|
||||
if (section->sector != §or)
|
||||
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 §ion : Level->sections.SectionsForSector(§or))
|
||||
{
|
||||
auto size = HandledSections.Size();
|
||||
if (!CollectSectorStacksFloor(§ion, §or, HandledSections))
|
||||
{
|
||||
// Delete everything that got already collected in this iteration.
|
||||
HandledSections.Resize(size);
|
||||
}
|
||||
}
|
||||
for (auto section : HandledSections)
|
||||
{
|
||||
if (section->sector != §or)
|
||||
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
|
||||
|
@ -538,6 +708,7 @@ void MapLoader::InitRenderInfo()
|
|||
PrepareSegs();
|
||||
PrepareSectorData();
|
||||
InitVertexData();
|
||||
FloodSectorStacks();
|
||||
TArray<int> checkmap(Level->vertexes.Size());
|
||||
memset(checkmap.Data(), -1, sizeof(int)*Level->vertexes.Size());
|
||||
for(auto &sec : Level->sectors)
|
||||
|
@ -782,4 +953,3 @@ void MapLoader::FixHoles()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -718,6 +718,7 @@ public:
|
|||
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
|
||||
dest.vertexindex = -1;
|
||||
dest.vertexcount = 0;
|
||||
dest.flags = 0;
|
||||
dest.bounds.setEmpty();
|
||||
numsegments += group.segments.Size();
|
||||
|
||||
|
|
|
@ -103,6 +103,11 @@ struct FSectionLine
|
|||
|
||||
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.
|
||||
TArrayView<FSectionLine> segments;
|
||||
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;
|
||||
short mapsection;
|
||||
char hacked; // 1: is part of a render hack
|
||||
char flags;
|
||||
};
|
||||
|
||||
class FSectionContainer
|
||||
|
|
Loading…
Reference in a new issue