terrain: factor out texture caching into a separate class

0.6.1
scrawl 8 years ago
parent 4cd4457d21
commit 804f873649

@ -174,7 +174,7 @@ namespace MWWorld
{
mResourceSystem->updateCache(mReferenceTime);
mTerrain->updateCache();
mTerrain->updateCache(mReferenceTime);
}
private:

@ -114,7 +114,7 @@ add_component_dir (translation
)
add_component_dir (terrain
storage world buffercache defs terraingrid material terraindrawable
storage world buffercache defs terraingrid material terraindrawable texturemanager
)
add_component_dir (loadinglistener

@ -23,6 +23,7 @@
#include "material.hpp"
#include "storage.hpp"
#include "terraindrawable.hpp"
#include "texturemanager.hpp"
namespace
{
@ -150,35 +151,17 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
useShaders = true; // always use shaders when lighting is unclamped, this is to avoid lighting seams between a terrain chunk with normal maps and one without normal maps
std::vector<TextureLayer> layers;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
{
TextureLayer textureLayer;
textureLayer.mParallax = it->mParallax;
textureLayer.mSpecular = it->mSpecular;
osg::ref_ptr<osg::Texture2D> texture = mTextureCache[it->mDiffuseMap];
if (!texture)
{
texture = new osg::Texture2D(mResourceSystem->getImageManager()->getImage(it->mDiffuseMap));
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mResourceSystem->getSceneManager()->applyFilterSettings(texture);
mTextureCache[it->mDiffuseMap] = texture;
}
textureLayer.mDiffuseMap = texture;
textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap);
if (!it->mNormalMap.empty())
{
texture = mTextureCache[it->mNormalMap];
if (!texture)
{
texture = new osg::Texture2D(mResourceSystem->getImageManager()->getImage(it->mNormalMap));
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mResourceSystem->getSceneManager()->applyFilterSettings(texture);
mTextureCache[it->mNormalMap] = texture;
}
textureLayer.mNormalMap = texture;
textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap);
}
if (it->requiresShaders())
@ -266,7 +249,7 @@ void TerrainGrid::unloadCell(int x, int y)
mGrid.erase(it);
}
void TerrainGrid::updateCache()
void TerrainGrid::updateCache(double referenceTime)
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
@ -278,24 +261,11 @@ void TerrainGrid::updateCache()
++it;
}
}
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end();)
{
if (it->second->referenceCount() <= 1)
mTextureCache.erase(it++);
else
++it;
}
}
}
void TerrainGrid::updateTextureFiltering()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end(); ++it)
mResourceSystem->getSceneManager()->applyFilterSettings(it->second);
mTextureManager->updateTextureFiltering();
}
void TerrainGrid::reportStats(unsigned int frameNumber, osg::Stats *stats)
@ -304,10 +274,6 @@ void TerrainGrid::reportStats(unsigned int frameNumber, osg::Stats *stats)
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
stats->setAttribute(frameNumber, "Terrain Cell", mGridCache.size());
}
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
stats->setAttribute(frameNumber, "Terrain Texture", mTextureCache.size());
}
}
}

@ -43,7 +43,7 @@ namespace Terrain
/// Clear cached objects that are no longer referenced
/// @note Thread safe.
void updateCache();
void updateCache(double referenceTime);
/// Apply the scene manager's texture filtering settings to all cached textures.
/// @note Thread safe.
@ -57,10 +57,6 @@ namespace Terrain
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
unsigned int mNumSplits;
typedef std::map<std::string, osg::ref_ptr<osg::Texture2D> > TextureCache;
TextureCache mTextureCache;
OpenThreads::Mutex mTextureCacheMutex;
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > Grid;
Grid mGrid;

@ -0,0 +1,64 @@
#include "texturemanager.hpp"
#include <osg/Stats>
#include <osg/Texture2D>
#include <components/resource/scenemanager.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/resource/objectcache.hpp>
namespace Terrain
{
TextureManager::TextureManager(Resource::SceneManager *sceneMgr)
: ResourceManager(sceneMgr->getVFS())
, mSceneManager(sceneMgr)
{
}
struct UpdateTextureFilteringFunctor
{
UpdateTextureFilteringFunctor(Resource::SceneManager* sceneMgr)
: mSceneManager(sceneMgr)
{
}
Resource::SceneManager* mSceneManager;
void operator()(osg::Object* obj)
{
mSceneManager->applyFilterSettings(static_cast<osg::Texture2D*>(obj));
}
};
void TextureManager::updateTextureFiltering()
{
UpdateTextureFilteringFunctor f(mSceneManager);
mCache->call(f);
}
osg::ref_ptr<osg::Texture2D> TextureManager::getTexture(const std::string &name)
{
// don't bother with case folding, since there is only one way of referring to terrain textures we can assume the case is always the same
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(name);
if (obj)
return static_cast<osg::Texture2D*>(obj.get());
else
{
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(mSceneManager->getImageManager()->getImage(name)));
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mSceneManager->applyFilterSettings(texture);
mCache->addEntryToObjectCache(name, texture.get());
return texture;
}
}
void TextureManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
{
stats->setAttribute(frameNumber, "Terrain Texture", mCache->getCacheSize());
}
}

@ -0,0 +1,39 @@
#ifndef OPENMW_COMPONENTS_TERRAIN_TEXTUREMANAGER_H
#define OPENMW_COMPONENTS_TERRAIN_TEXTUREMANAGER_H
#include <string>
#include <components/resource/resourcemanager.hpp>
namespace Resource
{
class SceneManager;
}
namespace osg
{
class Texture2D;
}
namespace Terrain
{
class TextureManager : public Resource::ResourceManager
{
public:
TextureManager(Resource::SceneManager* sceneMgr);
void updateTextureFiltering();
osg::ref_ptr<osg::Texture2D> getTexture(const std::string& name);
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats);
private:
Resource::SceneManager* mSceneManager;
};
}
#endif

@ -3,7 +3,10 @@
#include <osg/Group>
#include <osgUtil/IncrementalCompileOperation>
#include <components/resource/resourcesystem.hpp>
#include "storage.hpp"
#include "texturemanager.hpp"
namespace Terrain
{
@ -21,10 +24,16 @@ World::World(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUt
mTerrainRoot->setName("Terrain Root");
mParent->addChild(mTerrainRoot);
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
mResourceSystem->addResourceManager(mTextureManager.get());
}
World::~World()
{
mResourceSystem->removeResourceManager(mTextureManager.get());
mParent->removeChild(mTerrainRoot);
delete mStorage;

@ -3,6 +3,8 @@
#include <osg/ref_ptr>
#include <memory>
#include "defs.hpp"
#include "buffercache.hpp"
@ -26,6 +28,8 @@ namespace Terrain
{
class Storage;
class TextureManager;
/**
* @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
* is up to the implementation.
@ -42,7 +46,7 @@ namespace Terrain
virtual void updateTextureFiltering() {}
virtual void updateCache() {}
virtual void updateCache(double referenceTime) {}
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
@ -65,6 +69,8 @@ namespace Terrain
Resource::ResourceSystem* mResourceSystem;
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
std::auto_ptr<TextureManager> mTextureManager;
};
}

Loading…
Cancel
Save