From 8aea6048ec8b0a35454ed94ab1d3c1754e1cfca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Tue, 10 Dec 2019 18:51:34 +0200 Subject: [PATCH] Fixed|Renderer: Light decorations are not visible IssueID #2365 --- .../client/src/client/clientsubsector.cpp | 84 ++++++++++++++----- doomsday/apps/client/src/render/rend_main.cpp | 4 +- .../apps/client/src/world/base/surface.cpp | 6 +- 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/doomsday/apps/client/src/client/clientsubsector.cpp b/doomsday/apps/client/src/client/clientsubsector.cpp index a0f5db06a8..cf7eb96000 100644 --- a/doomsday/apps/client/src/client/clientsubsector.cpp +++ b/doomsday/apps/client/src/client/clientsubsector.cpp @@ -187,6 +187,13 @@ DENG2_PIMPL(ClientSubsector) if (::ddMapSetup) return; needUpdate = yes; } + + void clear() + { + markForUpdate(false); + qDeleteAll(decorations); + decorations.clear(); + } }; dint validFrame; @@ -274,6 +281,11 @@ DENG2_PIMPL(ClientSubsector) } } + static bool hasDecoratedMaterial(const Surface &surface) + { + return surface.hasMaterial() && surface.material().as().hasDecorations(); + } + void observeSurface(Surface *surface, bool yes = true) { if (!surface) return; @@ -283,12 +295,19 @@ DENG2_PIMPL(ClientSubsector) surface->audienceForMaterialChange () += this; surface->audienceForOriginChange () += this; surface->audienceForOriginSmoothedChange() += this; + + if (hasDecoratedMaterial(*surface)) + { + allocDecorationState(*surface); + } } else { surface->audienceForOriginSmoothedChange() -= this; surface->audienceForOriginChange () -= this; surface->audienceForMaterialChange () -= this; + + decorSurfaces.remove(surface); } } @@ -521,6 +540,8 @@ DENG2_PIMPL(ClientSubsector) void remapVisPlanes() { + /// @todo Has performance issues -- disabled; needs reworking. + // By default both planes are mapped to the parent sector. if (!floorIsMapped()) map(Sector::Floor, thisPublic); if (!ceilingIsMapped()) map(Sector::Ceiling, thisPublic); @@ -1014,7 +1035,18 @@ DENG2_PIMPL(ClientSubsector) } void decorate(Surface &surface) - { + { + if (!hasDecoratedMaterial(surface)) + { + // Just clear the state. + if (surface.decorationState()) + { + static_cast(surface.decorationState())->clear(); + } + return; + } + + // Has a decorated material, so needs decoration state. auto &ds = allocDecorationState(surface); if (!ds.needUpdate) return; @@ -1025,21 +1057,14 @@ DENG2_PIMPL(ClientSubsector) && &surface.parent() == mappedPlane(surface.parent().as().indexInSector()) ? " (mapped)" : "") ); - ds.markForUpdate(false); + ds.clear(); - qDeleteAll(ds.decorations); - ds.decorations.clear(); - - // Clear any existing decorations. - if (surface.hasMaterial()) + Vector2f materialOrigin; + Vector3d bottomRight, topLeft; + if (prepareGeometry(surface, topLeft, bottomRight, materialOrigin)) { - Vector2f materialOrigin; - Vector3d bottomRight, topLeft; - if (prepareGeometry(surface, topLeft, bottomRight, materialOrigin)) - { - MaterialAnimator &animator = *surface.materialAnimator(); - projectDecorations(surface, animator, materialOrigin, topLeft, bottomRight); - } + MaterialAnimator &animator = *surface.materialAnimator(); + projectDecorations(surface, animator, materialOrigin, topLeft, bottomRight); } } @@ -1312,17 +1337,30 @@ DENG2_PIMPL(ClientSubsector) void surfaceMaterialChanged(Surface &surface) { LOG_AS("ClientSubsector"); - //DecoratedSurface &ds = decorSurfaces[surface.uniqueId()]; - DecoratedSurface &ds = allocDecorationState(surface); + if (auto *ds = static_cast(surface.decorationState())) + { + // Clear any existing decorations (now invalid). + ds->clear(); +// qDeleteAll(ds->decorations); +// ds->decorations.clear(); +// ds->markForUpdate(); + } - // Clear any existing decorations (now invalid). - qDeleteAll(ds.decorations); - ds.decorations.clear(); - ds.markForUpdate(); + if (hasDecoratedMaterial(surface)) + { + auto &ds = allocDecorationState(surface); + ds.markForUpdate(); + } // Begin observing the new material (if any). - /// @todo fixme: stop observing the old one!? -ds + // + // Note that the subsector keeps observing all the materials of all surfaces. + // To stop observing old ones, one needs to make sure that no surface in the + // subsector is no longer using the material. + // + /// @todo Stop observing unused materials. + // observeMaterial(surface.materialPtr()); } @@ -1889,6 +1927,8 @@ void ClientSubsector::decorate() bool ClientSubsector::hasDecorations() const { + return !d.getConst()->decorSurfaces.isEmpty(); + /* for (Surface *surface : d.getConst()->decorSurfaces) { if (!static_cast @@ -1897,7 +1937,7 @@ bool ClientSubsector::hasDecorations() const return true; } } - return false; + return false;*/ } void ClientSubsector::generateLumobjs() diff --git a/doomsday/apps/client/src/render/rend_main.cpp b/doomsday/apps/client/src/render/rend_main.cpp index b744f24f7d..b1cfc9c8e2 100644 --- a/doomsday/apps/client/src/render/rend_main.cpp +++ b/doomsday/apps/client/src/render/rend_main.cpp @@ -5426,8 +5426,8 @@ static void drawLumobjs(Map &map) if (!devDrawLums) return; + DGL_PushState(); DGL_Disable(DGL_DEPTH_TEST); - //glDisable(GL_CULL_FACE); DGL_CullFace(DGL_NONE); map.forAllLumobjs([] (Lumobj &lob) @@ -5471,9 +5471,7 @@ static void drawLumobjs(Map &map) return LoopContinue; }); - //glEnable(GL_CULL_FACE); DGL_PopState(); - DGL_Enable(DGL_DEPTH_TEST); } static String labelForLineSideSection(LineSide &side, dint sectionId) diff --git a/doomsday/apps/client/src/world/base/surface.cpp b/doomsday/apps/client/src/world/base/surface.cpp index f34818e9ad..e46ca396e0 100644 --- a/doomsday/apps/client/src/world/base/surface.cpp +++ b/doomsday/apps/client/src/world/base/surface.cpp @@ -267,8 +267,10 @@ Surface &Surface::setMaterial(Material *newMaterial, bool isMissingFix) #endif // Notify interested parties. - DENG2_FOR_AUDIENCE2(MaterialChange, i) i->surfaceMaterialChanged(*this); - + DENG2_FOR_AUDIENCE2(MaterialChange, i) + { + i->surfaceMaterialChanged(*this); + } return *this; }