From b29be7449153b5216e2285fa98aa71cfba25be39 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Tue, 23 May 2023 00:23:47 +0200 Subject: [PATCH] ground cover manager and object paging exists per worldspace. They don't work though. But at least it doesn't crash. You get a morrowind world on top of the skyrim world. But it fixes the crashes. --- apps/openmw/mwrender/renderingmanager.cpp | 73 ++++++++++++----------- apps/openmw/mwrender/renderingmanager.hpp | 17 ++++-- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 066f73514a..c7ec5d3972 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -321,6 +321,7 @@ namespace MWRender , mFieldOfViewOverride(0.f) , mFieldOfView(Settings::camera().mFieldOfView) , mFirstPersonFieldOfView(Settings::camera().mFirstPersonFieldOfView) + , mGroundCoverStore(groundcoverStore) { bool reverseZ = SceneUtil::AutoDepth::isReversed(); auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString( @@ -458,19 +459,10 @@ namespace MWRender mTerrainStorage = std::make_unique(mResourceSystem, normalMapPattern, heightMapPattern, useTerrainNormalMaps, specularMapPattern, useTerrainSpecularMaps); - mTerrain = &getWorldspaceTerrain(ESM::Cell::sDefaultWorldspaceId); - bool groundcover = Settings::Manager::getBool("enabled", "Groundcover"); - - if (groundcover) - { - float density = Settings::Manager::getFloat("density", "Groundcover"); - density = std::clamp(density, 0.f, 1.f); - - mGroundcover = std::make_unique( - mResourceSystem->getSceneManager(), density, groundcoverDistance, groundcoverStore); - static_cast(mTerrain)->addChunkManager(mGroundcover.get()); - mResourceSystem->addResourceManager(mGroundcover.get()); - } + WorldspaceChunkMgr& chunkMgr = getWorldspaceChunkMgr(ESM::Cell::sDefaultWorldspaceId); + mTerrain = chunkMgr.mTerrain.get(); + mGroundcover = chunkMgr.mGroundcover.get(); + mObjectPaging = chunkMgr.mObjectPaging.get(); mStateUpdater = new StateUpdater; sceneRoot->addUpdateCallback(mStateUpdater); @@ -757,8 +749,8 @@ namespace MWRender if (store->getCell()->isExterior()) { - getWorldspaceTerrain(store->getCell()->getWorldSpace()) - .unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); + getWorldspaceChunkMgr(store->getCell()->getWorldSpace()) + .mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY()); } mWater->removeCell(store); @@ -770,11 +762,13 @@ namespace MWRender mWater->setCullCallback(nullptr); else { - Terrain::World* newTerrain = &getWorldspaceTerrain(worldspace); - if (newTerrain != mTerrain) + WorldspaceChunkMgr& newChunks = getWorldspaceChunkMgr(worldspace); + if (newChunks.mTerrain.get() != mTerrain) { mTerrain->enable(false); - mTerrain = newTerrain; + mTerrain = newChunks.mTerrain.get(); + mGroundcover = newChunks.mGroundcover.get(); + mObjectPaging = newChunks.mObjectPaging.get(); } } mTerrain->enable(enable); @@ -1328,12 +1322,12 @@ namespace MWRender mStateUpdater->setFogColor(color); } - Terrain::World& RenderingManager::getWorldspaceTerrain(ESM::RefId worldspace) + RenderingManager::WorldspaceChunkMgr& RenderingManager::getWorldspaceChunkMgr(ESM::RefId worldspace) { - auto existingTerrain = mWorldspaceTerrains.find(worldspace); - if (existingTerrain != mWorldspaceTerrains.end()) - return *existingTerrain->second.get(); - std::unique_ptr newTerrain; + auto existingChunkMgr = mWorldspaceChunks.find(worldspace); + if (existingChunkMgr != mWorldspaceChunks.end()) + return existingChunkMgr->second; + RenderingManager::WorldspaceChunkMgr newChunkMgr; const float lodFactor = Settings::Manager::getFloat("lod factor", "Terrain"); bool groundcover = Settings::Manager::getBool("enabled", "Groundcover"); @@ -1348,27 +1342,38 @@ namespace MWRender float maxCompGeometrySize = Settings::Manager::getFloat("max composite geometry size", "Terrain"); maxCompGeometrySize = std::max(maxCompGeometrySize, 1.f); bool debugChunks = Settings::Manager::getBool("debug chunks", "Terrain"); - newTerrain = std::make_unique(mSceneRoot, mRootNode, mResourceSystem, + auto quadTreeWorld = std::make_unique(mSceneRoot, mRootNode, mResourceSystem, mTerrainStorage.get(), Mask_Terrain, Mask_PreCompile, Mask_Debug, compMapResolution, compMapLevel, lodFactor, vertexLodMod, maxCompGeometrySize, debugChunks, worldspace); if (Settings::Manager::getBool("object paging", "Terrain")) { - mObjectPaging = std::make_unique(mResourceSystem->getSceneManager()); - static_cast(newTerrain.get())->addChunkManager(mObjectPaging.get()); - mResourceSystem->addResourceManager(mObjectPaging.get()); + newChunkMgr.mObjectPaging = std::make_unique(mResourceSystem->getSceneManager()); + quadTreeWorld->addChunkManager(newChunkMgr.mObjectPaging.get()); + mResourceSystem->addResourceManager(newChunkMgr.mObjectPaging.get()); } + if (groundcover) + { + float groundcoverDistance + = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover")); + float density = Settings::Manager::getFloat("density", "Groundcover"); + density = std::clamp(density, 0.f, 1.f); + + newChunkMgr.mGroundcover = std::make_unique( + mResourceSystem->getSceneManager(), density, groundcoverDistance, mGroundCoverStore); + quadTreeWorld->addChunkManager(newChunkMgr.mGroundcover.get()); + mResourceSystem->addResourceManager(newChunkMgr.mGroundcover.get()); + } + newChunkMgr.mTerrain = std::move(quadTreeWorld); } else - newTerrain = std::make_unique(mSceneRoot, mRootNode, mResourceSystem, + newChunkMgr.mTerrain = std::make_unique(mSceneRoot, mRootNode, mResourceSystem, mTerrainStorage.get(), Mask_Terrain, worldspace, Mask_PreCompile, Mask_Debug); - newTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells")); + newChunkMgr.mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells")); float distanceMult = std::cos(osg::DegreesToRadians(std::min(mFieldOfView, 140.f)) / 2.f); - newTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f / distanceMult : 1.f)); + newChunkMgr.mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f / distanceMult : 1.f)); - Terrain::World* result = newTerrain.get(); - mWorldspaceTerrains.emplace(worldspace, std::move(newTerrain)); - return *result; + return mWorldspaceChunks.emplace(worldspace, std::move(newChunkMgr)).first->second; } void RenderingManager::reportStats() const @@ -1474,7 +1479,7 @@ namespace MWRender float RenderingManager::getTerrainHeightAt(const osg::Vec3f& pos, ESM::RefId worldspace) { - return getWorldspaceTerrain(worldspace).getHeightAt(pos); + return getWorldspaceChunkMgr(worldspace).mTerrain->getHeightAt(pos); } void RenderingManager::overrideFieldOfView(float val) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 5811387284..0e2ece7de9 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -282,7 +282,15 @@ namespace MWRender void updateAmbient(); void setFogColor(const osg::Vec4f& color); void updateThirdPersonViewMode(); - Terrain::World& getWorldspaceTerrain(ESM::RefId worldspace); + + struct WorldspaceChunkMgr + { + std::unique_ptr mTerrain; + std::unique_ptr mObjectPaging; + std::unique_ptr mGroundcover; + }; + + WorldspaceChunkMgr& getWorldspaceChunkMgr(ESM::RefId worldspace); void reportStats() const; @@ -314,11 +322,11 @@ namespace MWRender std::unique_ptr mPathgrid; std::unique_ptr mObjects; std::unique_ptr mWater; - std::unordered_map> mWorldspaceTerrains; + std::unordered_map mWorldspaceChunks; Terrain::World* mTerrain; std::unique_ptr mTerrainStorage; - std::unique_ptr mObjectPaging; - std::unique_ptr mGroundcover; + ObjectPaging* mObjectPaging; + Groundcover* mGroundcover; std::unique_ptr mSky; std::unique_ptr mFog; std::unique_ptr mScreenshotManager; @@ -346,6 +354,7 @@ namespace MWRender float mFirstPersonFieldOfView; bool mUpdateProjectionMatrix = false; bool mNight = false; + const MWWorld::GroundcoverStore& mGroundCoverStore; void operator=(const RenderingManager&); RenderingManager(const RenderingManager&);