From af9636b7c3d811f82d76106d72f8701f12292d7a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 4 Feb 2019 13:06:54 +0100 Subject: [PATCH] - fixed glitches with some poorly set up sector stack portals. --- src/gl/system/gl_buffers.cpp | 1 - src/hwrenderer/scene/hw_flats.cpp | 6 +- src/hwrenderer/scene/hw_renderhacks.cpp | 215 ------------------------ src/maploader/maploader.h | 1 + src/maploader/renderinfo.cpp | 172 ++++++++++++++++++- src/r_data/r_sections.cpp | 1 + src/r_data/r_sections.h | 6 + 7 files changed, 182 insertions(+), 220 deletions(-) diff --git a/src/gl/system/gl_buffers.cpp b/src/gl/system/gl_buffers.cpp index 39535fd03a..b67bb99b97 100644 --- a/src/gl/system/gl_buffers.cpp +++ b/src/gl/system/gl_buffers.cpp @@ -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) { diff --git a/src/hwrenderer/scene/hw_flats.cpp b/src/hwrenderer/scene/hw_flats.cpp index a72122a488..1ba3b9ce7d 100644 --- a/src/hwrenderer/scene/hw_flats.cpp +++ b/src/hwrenderer/scene/hw_flats.cpp @@ -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. @@ -554,9 +554,9 @@ void GLFlat::ProcessSector(HWDrawInfo *di, sector_t * frontsector, int which) // // do ceilings // + // // - // - 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. diff --git a/src/hwrenderer/scene/hw_renderhacks.cpp b/src/hwrenderer/scene/hw_renderhacks.cpp index b2467a5eb3..76add43c9b 100644 --- a/src/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/hwrenderer/scene/hw_renderhacks.cpp @@ -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;jnumlines;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;jnumlines;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;iGetPortalGroup(sector_t::ceiling); - if (portal != NULL) for(int k=0;ksubsectorcount;k++) - { - subsector_t * sub = sec->subsectors[k]; - if (ss_renderflags[sub->Index()] & SSRF_PROCESSED) - { - HandledSubsectors.Clear(); - for(uint32_t j=0;jnumlines;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;jIndex()] &= ~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;iGetPortalGroup(sector_t::floor); - if (portal != NULL) for(int k=0;ksubsectorcount;k++) - { - subsector_t * sub = sec->subsectors[k]; - if (ss_renderflags[sub->Index()] & SSRF_PROCESSED) - { - HandledSubsectors.Clear(); - for(uint32_t j=0;jnumlines;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;jIndex()] &= ~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 diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 38a68b0fab..4b5832f53a 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -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(); diff --git a/src/maploader/renderinfo.cpp b/src/maploader/renderinfo.cpp index 3a366b7e04..c60b846948 100644 --- a/src/maploader/renderinfo.cpp +++ b/src/maploader/renderinfo.cpp @@ -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 &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 &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 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 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 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() } } } - diff --git a/src/r_data/r_sections.cpp b/src/r_data/r_sections.cpp index b896f1ddb6..18a26b1817 100644 --- a/src/r_data/r_sections.cpp +++ b/src/r_data/r_sections.cpp @@ -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(); diff --git a/src/r_data/r_sections.h b/src/r_data/r_sections.h index 5ac7188ea3..c971cb09bc 100644 --- a/src/r_data/r_sections.h +++ b/src/r_data/r_sections.h @@ -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 segments; TArrayView 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