mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
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]
This commit is contained in:
parent
c284d0cf5c
commit
9d661359a1
10 changed files with 40 additions and 85 deletions
|
@ -180,7 +180,7 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<osg::Node> 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<osg::Object> obj = mCache->getRefFromObjectCache(id);
|
||||
if (obj)
|
||||
|
@ -196,7 +196,7 @@ namespace MWRender
|
|||
}
|
||||
|
||||
Groundcover::Groundcover(Resource::SceneManager* sceneManager, float density)
|
||||
: GenericResourceManager<ChunkId>(nullptr)
|
||||
: GenericResourceManager<GroundcoverChunkId>(nullptr)
|
||||
, mSceneManager(sceneManager)
|
||||
, mDensity(density)
|
||||
{
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace MWRender
|
|||
osg::Vec3f mPlayerPos;
|
||||
};
|
||||
|
||||
typedef std::tuple<osg::Vec2f, float, bool> ChunkId; // Center, Size, ActiveGrid
|
||||
class Groundcover : public Resource::GenericResourceManager<ChunkId>, public Terrain::QuadTreeWorld::ChunkManager
|
||||
typedef std::tuple<osg::Vec2f, float> GroundcoverChunkId; // Center, Size
|
||||
class Groundcover : public Resource::GenericResourceManager<GroundcoverChunkId>, public Terrain::QuadTreeWorld::ChunkManager
|
||||
{
|
||||
public:
|
||||
Groundcover(Resource::SceneManager* sceneManager, float density);
|
||||
|
|
|
@ -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<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
|
||||
|
||||
if (groundcover)
|
||||
{
|
||||
osg::ref_ptr<osg::Group> 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<Terrain::QuadTreeWorld*>(mGroundcoverWorld.get())->addChunkManager(mGroundcover.get());
|
||||
static_cast<Terrain::QuadTreeWorld*>(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()
|
||||
|
|
|
@ -262,8 +262,6 @@ namespace MWRender
|
|||
osg::ref_ptr<osg::Group> mSceneRoot;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
||||
osg::ref_ptr<GroundcoverUpdater> mGroundcoverUpdater;
|
||||
|
||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||
|
||||
|
@ -278,10 +276,10 @@ namespace MWRender
|
|||
std::unique_ptr<Objects> mObjects;
|
||||
std::unique_ptr<Water> mWater;
|
||||
std::unique_ptr<Terrain::World> mTerrain;
|
||||
std::unique_ptr<Terrain::World> mGroundcoverWorld;
|
||||
std::unique_ptr<TerrainStorage> mTerrainStorage;
|
||||
std::unique_ptr<ObjectPaging> mObjectPaging;
|
||||
std::unique_ptr<Groundcover> mGroundcover;
|
||||
osg::ref_ptr<GroundcoverUpdater> mGroundcoverUpdater;
|
||||
std::unique_ptr<SkyManager> mSky;
|
||||
std::unique_ptr<FogManager> mFog;
|
||||
std::unique_ptr<ScreenshotManager> mScreenshotManager;
|
||||
|
|
|
@ -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<float>::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<QuadTreeWorld::ChunkManager*>& chunkManagers, bool compile)
|
||||
void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, float cellWorldSize, const osg::Vec4i &gridbounds, const std::vector<QuadTreeWorld::ChunkManager*>& 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<osg::Node> 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; i<vd->getNumEntries(); ++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; i<vd->getNumEntries() && !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();
|
||||
}
|
||||
|
|
|
@ -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<osg::Node> 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*);
|
||||
|
||||
|
|
|
@ -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<float>::max();
|
||||
float shortestDist = std::numeric_limits<float>::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))
|
||||
{
|
||||
|
|
|
@ -95,6 +95,8 @@ namespace Terrain
|
|||
void rebuildViews();
|
||||
bool storeView(const ViewData* view, double referenceTime);
|
||||
|
||||
float getReuseDistance() const { return mReuseDistance; }
|
||||
|
||||
private:
|
||||
std::list<ViewData> mViewVector;
|
||||
|
||||
|
|
|
@ -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
|
||||
----------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue