From 9d661359a160c3fb265c71cbcacbd08945407e4c Mon Sep 17 00:00:00 2001 From: Bo Svensson <90132211+bosvensson1@users.noreply.github.com> Date: Thu, 9 Sep 2021 21:10:22 +0000 Subject: [PATCH] Groundcover consolidation (#3096) * chunkmanager.hpp viewdistance * chunkmanager.cpp viewdistance * chunkmanager.hpp viewdistance * quadtreeworld.cpp viewdistance * quadtreeworld.cpp consolidate * quadtreeworld.hpp consolidate * renderingmanager.cpp groundcover consolidate * renderingmanager.hpp groundcover consolidate * renderingmanager.cpp updater move * renderingmanager.hpp updater move * groundcover.hpp activegrid consolidation * groundcover.cpp activegrid consolidation * settings-default.cfg dead settings remove * viewdata.cpp revert * wrong file paste mistake * wrong file paste mistake * wrong file paste mistake * renderingmanager.cpp updatecallback fix * renderingmanager.cpp namespace fix * groundcover.hpp redefinition fix * groundcover.cpp redefinition fix * renderingmanager.cpp crash fix * renderingmanager.cpp euclidean groundcover distance * viewdata.hpp getreusedistance * quadtreeworld.cpp reusedistance * groundcover.rst [ci skip] --- apps/openmw/mwrender/groundcover.cpp | 4 +- apps/openmw/mwrender/groundcover.hpp | 4 +- apps/openmw/mwrender/renderingmanager.cpp | 52 +++++-------------- apps/openmw/mwrender/renderingmanager.hpp | 4 +- components/terrain/quadtreeworld.cpp | 26 +++++----- components/terrain/quadtreeworld.hpp | 7 ++- components/terrain/viewdata.cpp | 9 +--- components/terrain/viewdata.hpp | 2 + .../modding/settings/groundcover.rst | 14 ----- files/settings-default.cfg | 3 -- 10 files changed, 40 insertions(+), 85 deletions(-) diff --git a/apps/openmw/mwrender/groundcover.cpp b/apps/openmw/mwrender/groundcover.cpp index 947bdad202..a00d21bc97 100644 --- a/apps/openmw/mwrender/groundcover.cpp +++ b/apps/openmw/mwrender/groundcover.cpp @@ -180,7 +180,7 @@ namespace MWRender osg::ref_ptr Groundcover::getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile) { - ChunkId id = std::make_tuple(center, size, activeGrid); + GroundcoverChunkId id = std::make_tuple(center, size); osg::ref_ptr obj = mCache->getRefFromObjectCache(id); if (obj) @@ -196,7 +196,7 @@ namespace MWRender } Groundcover::Groundcover(Resource::SceneManager* sceneManager, float density) - : GenericResourceManager(nullptr) + : GenericResourceManager(nullptr) , mSceneManager(sceneManager) , mDensity(density) { diff --git a/apps/openmw/mwrender/groundcover.hpp b/apps/openmw/mwrender/groundcover.hpp index b92ab97c95..10874b7e8b 100644 --- a/apps/openmw/mwrender/groundcover.hpp +++ b/apps/openmw/mwrender/groundcover.hpp @@ -29,8 +29,8 @@ namespace MWRender osg::Vec3f mPlayerPos; }; - typedef std::tuple ChunkId; // Center, Size, ActiveGrid - class Groundcover : public Resource::GenericResourceManager, public Terrain::QuadTreeWorld::ChunkManager + typedef std::tuple GroundcoverChunkId; // Center, Size + class Groundcover : public Resource::GenericResourceManager, public Terrain::QuadTreeWorld::ChunkManager { public: Groundcover(Resource::SceneManager* sceneManager, float density); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 381a2e5f62..56d3ba4a43 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -373,7 +373,9 @@ namespace MWRender mTerrainStorage.reset(new TerrainStorage(mResourceSystem, normalMapPattern, heightMapPattern, useTerrainNormalMaps, specularMapPattern, useTerrainSpecularMaps)); const float lodFactor = Settings::Manager::getFloat("lod factor", "Terrain"); - if (Settings::Manager::getBool("distant terrain", "Terrain")) + bool groundcover = Settings::Manager::getBool("enabled", "Groundcover"); + bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain"); + if (distantTerrain || groundcover) { const int compMapResolution = Settings::Manager::getInt("composite map resolution", "Terrain"); int compMapPower = Settings::Manager::getInt("composite map level", "Terrain"); @@ -398,41 +400,27 @@ namespace MWRender mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells")); mTerrain->setWorkQueue(mWorkQueue.get()); - if (Settings::Manager::getBool("enabled", "Groundcover")) + osg::ref_ptr composite = new SceneUtil::CompositeStateSetUpdater; + + if (groundcover) { - osg::ref_ptr groundcoverRoot = new osg::Group; - groundcoverRoot->setNodeMask(Mask_Groundcover); - groundcoverRoot->setName("Groundcover Root"); - sceneRoot->addChild(groundcoverRoot); - - mGroundcoverUpdater = new GroundcoverUpdater; - groundcoverRoot->addUpdateCallback(mGroundcoverUpdater); - - float chunkSize = Settings::Manager::getFloat("min chunk size", "Groundcover"); - if (chunkSize >= 1.0f) - chunkSize = 1.0f; - else if (chunkSize >= 0.5f) - chunkSize = 0.5f; - else if (chunkSize >= 0.25f) - chunkSize = 0.25f; - else if (chunkSize != 0.125f) - chunkSize = 0.125f; - float density = Settings::Manager::getFloat("density", "Groundcover"); density = std::clamp(density, 0.f, 1.f); - mGroundcoverWorld.reset(new Terrain::QuadTreeWorld(groundcoverRoot, mTerrainStorage.get(), Mask_Groundcover, lodFactor, chunkSize)); + mGroundcoverUpdater = new GroundcoverUpdater; + composite->addController(mGroundcoverUpdater); + mGroundcover.reset(new Groundcover(mResourceSystem->getSceneManager(), density)); - static_cast(mGroundcoverWorld.get())->addChunkManager(mGroundcover.get()); + static_cast(mTerrain.get())->addChunkManager(mGroundcover.get()); mResourceSystem->addResourceManager(mGroundcover.get()); - // Groundcover it is handled in the same way indifferently from if it is from active grid or from distant cell. - // Use a stub grid to avoid splitting between chunks for active grid and chunks for distant cells. - mGroundcoverWorld->setActiveGrid(osg::Vec4i(0, 0, 0, 0)); + float groundcoverDistance = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover")); + mGroundcover->setViewDistance(groundcoverDistance); } mStateUpdater = new StateUpdater; - sceneRoot->addUpdateCallback(mStateUpdater); + composite->addController(mStateUpdater); + sceneRoot->addUpdateCallback(composite); mSharedUniformStateUpdater = new SharedUniformStateUpdater; rootNode->addUpdateCallback(mSharedUniformStateUpdater); @@ -693,8 +681,6 @@ namespace MWRender if (store->getCell()->isExterior()) { mTerrain->loadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); - if (mGroundcoverWorld) - mGroundcoverWorld->loadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); } } void RenderingManager::removeCell(const MWWorld::CellStore *store) @@ -706,8 +692,6 @@ namespace MWRender if (store->getCell()->isExterior()) { mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); - if (mGroundcoverWorld) - mGroundcoverWorld->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); } mWater->removeCell(store); @@ -718,8 +702,6 @@ namespace MWRender if (!enable) mWater->setCullCallback(nullptr); mTerrain->enable(enable); - if (mGroundcoverWorld) - mGroundcoverWorld->enable(enable); } void RenderingManager::setSkyEnabled(bool enabled) @@ -1179,12 +1161,6 @@ namespace MWRender fov = std::min(mFieldOfView, 140.f); float distanceMult = std::cos(osg::DegreesToRadians(fov)/2.f); mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f/distanceMult : 1.f)); - - if (mGroundcoverWorld) - { - float groundcoverDistance = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover")); - mGroundcoverWorld->setViewDistance(groundcoverDistance * (distanceMult ? 1.f/distanceMult : 1.f)); - } } void RenderingManager::updateTextureFiltering() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index d6d7e74634..b991b08efa 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -262,8 +262,6 @@ namespace MWRender osg::ref_ptr mSceneRoot; Resource::ResourceSystem* mResourceSystem; - osg::ref_ptr mGroundcoverUpdater; - osg::ref_ptr mWorkQueue; osg::ref_ptr mUnrefQueue; @@ -278,10 +276,10 @@ namespace MWRender std::unique_ptr mObjects; std::unique_ptr mWater; std::unique_ptr mTerrain; - std::unique_ptr mGroundcoverWorld; std::unique_ptr mTerrainStorage; std::unique_ptr mObjectPaging; std::unique_ptr mGroundcover; + osg::ref_ptr mGroundcoverUpdater; std::unique_ptr mSky; std::unique_ptr mFog; std::unique_ptr mScreenshotManager; diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 9ca504ebeb..6a228a75af 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -259,17 +259,6 @@ QuadTreeWorld::QuadTreeWorld(osg::Group *parent, osg::Group *compileRoot, Resour mChunkManagers.push_back(mChunkManager.get()); } -QuadTreeWorld::QuadTreeWorld(osg::Group *parent, Storage *storage, unsigned int nodeMask, float lodFactor, float chunkSize) - : TerrainGrid(parent, storage, nodeMask) - , mViewDataMap(new ViewDataMap) - , mQuadTreeBuilt(false) - , mLodFactor(lodFactor) - , mVertexLodMod(0) - , mViewDistance(std::numeric_limits::max()) - , mMinSize(chunkSize) -{ -} - QuadTreeWorld::~QuadTreeWorld() { } @@ -325,7 +314,7 @@ unsigned int getLodFlags(QuadTreeNode* node, int ourLod, int vertexLodMod, const return lodFlags; } -void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, float cellWorldSize, const osg::Vec4i &gridbounds, const std::vector& chunkManagers, bool compile) +void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, float cellWorldSize, const osg::Vec4i &gridbounds, const std::vector& chunkManagers, bool compile, float reuseDistance) { if (!vd->hasChanged() && entry.mRenderingNode) return; @@ -353,6 +342,8 @@ void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, f for (QuadTreeWorld::ChunkManager* m : chunkManagers) { + if (m->getViewDistance() && entry.mNode->distance(vd->getViewPoint()) > m->getViewDistance() + reuseDistance*10) + continue; osg::ref_ptr n = m->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), ourLod, entry.mLodFlags, activeGrid, vd->getViewPoint(), compile); if (n) pat->addChild(n); } @@ -447,7 +438,7 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv) for (unsigned int i=0; igetNumEntries(); ++i) { ViewData::Entry& entry = vd->getEntry(i); - loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, mActiveGrid, mChunkManagers, false); + loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, mActiveGrid, mChunkManagers, false, mViewDataMap->getReuseDistance()); entry.mRenderingNode->accept(nv); } @@ -517,8 +508,15 @@ void QuadTreeWorld::preload(View *view, const osg::Vec3f &viewPoint, const osg:: for (unsigned int i=0; igetNumEntries() && !abort; ++i) { ViewData::Entry& entry = vd->getEntry(i); - loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, grid, mChunkManagers, true); + + + + loadRenderingNode(entry, vd, mVertexLodMod, cellWorldSize, grid, mChunkManagers, true, mViewDataMap->getReuseDistance()); reporter.addProgress(entry.mNode->getSize()); + + + + } vd->markUnchanged(); } diff --git a/components/terrain/quadtreeworld.hpp b/components/terrain/quadtreeworld.hpp index 3a2aa8349d..3dd96a0b84 100644 --- a/components/terrain/quadtreeworld.hpp +++ b/components/terrain/quadtreeworld.hpp @@ -22,8 +22,6 @@ namespace Terrain public: QuadTreeWorld(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem, Storage* storage, unsigned int nodeMask, unsigned int preCompileMask, unsigned int borderMask, int compMapResolution, float comMapLevel, float lodFactor, int vertexLodMod, float maxCompGeometrySize); - QuadTreeWorld(osg::Group *parent, Storage *storage, unsigned int nodeMask, float lodFactor, float chunkSize); - ~QuadTreeWorld(); void accept(osg::NodeVisitor& nv); @@ -51,6 +49,11 @@ namespace Terrain virtual ~ChunkManager(){} virtual osg::ref_ptr getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile) = 0; virtual unsigned int getNodeMask() { return 0; } + + void setViewDistance(float viewDistance) { mViewDistance = viewDistance; } + float getViewDistance() const { return mViewDistance; } + private: + float mViewDistance = 0.f; }; void addChunkManager(ChunkManager*); diff --git a/components/terrain/viewdata.cpp b/components/terrain/viewdata.cpp index 996bf909c8..e4d043ffc4 100644 --- a/components/terrain/viewdata.cpp +++ b/components/terrain/viewdata.cpp @@ -141,9 +141,9 @@ ViewData *ViewDataMap::getViewData(osg::Object *viewer, const osg::Vec3f& viewPo vd = found->second; needsUpdate = false; - if (!vd->suitableToUse(activeGrid) || (vd->getViewPoint()-viewPoint).length2() >= mReuseDistance*mReuseDistance || vd->getWorldUpdateRevision() < mWorldUpdateRevision) + if (!(vd->suitableToUse(activeGrid) && (vd->getViewPoint()-viewPoint).length2() < mReuseDistance*mReuseDistance && vd->getWorldUpdateRevision() >= mWorldUpdateRevision)) { - float shortestDist = viewer ? mReuseDistance*mReuseDistance : std::numeric_limits::max(); + float shortestDist = std::numeric_limits::max(); const ViewData* mostSuitableView = nullptr; for (const ViewData* other : mUsedViews) { @@ -162,11 +162,6 @@ ViewData *ViewDataMap::getViewData(osg::Object *viewer, const osg::Vec3f& viewPo vd->copyFrom(*mostSuitableView); return vd; } - else if (!mostSuitableView) - { - vd->setViewPoint(viewPoint); - needsUpdate = true; - } } if (!vd->suitableToUse(activeGrid)) { diff --git a/components/terrain/viewdata.hpp b/components/terrain/viewdata.hpp index 0289352585..378d07663c 100644 --- a/components/terrain/viewdata.hpp +++ b/components/terrain/viewdata.hpp @@ -95,6 +95,8 @@ namespace Terrain void rebuildViews(); bool storeView(const ViewData* view, double referenceTime); + float getReuseDistance() const { return mReuseDistance; } + private: std::list mViewVector; diff --git a/docs/source/reference/modding/settings/groundcover.rst b/docs/source/reference/modding/settings/groundcover.rst index 7c5a965e01..3e943e4284 100644 --- a/docs/source/reference/modding/settings/groundcover.rst +++ b/docs/source/reference/modding/settings/groundcover.rst @@ -40,20 +40,6 @@ May affect performance a lot. This setting can only be configured by editing the settings configuration file. -min chunk size --------------- - -:Type: floating point -:Range: 0.125, 0.25, 0.5, 1.0 -:Default: 0.5 - -Determines a minimum size of groundcover chunks in cells. For example, with 0.5 value -chunks near player will have size 4096x4096 game units. Larger chunks reduce CPU usage -(Draw and Cull bars), but can increase GPU usage (GPU bar) since culling becomes less efficient. -Smaller values do an opposite. - -This setting can only be configured by editing the settings configuration file. - stomp mode ---------- diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 4737fcf5ee..7f57ba529d 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -1087,9 +1087,6 @@ density = 1.0 # A maximum distance in game units on which groundcover is rendered. rendering distance = 6144.0 -# A minimum size of groundcover chunk in cells (0.125, 0.25, 0.5, 1.0) -min chunk size = 0.5 - # Whether grass should respond to the player treading on it. # 0 - Grass cannot be trampled. # 1 - The player's XY position is taken into account.