mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 18:45:38 +00:00
terrain: factor out texture caching into a separate class
This commit is contained in:
parent
4cd4457d21
commit
804f873649
8 changed files with 128 additions and 48 deletions
|
@ -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;
|
||||
|
||||
|
|
64
components/terrain/texturemanager.cpp
Normal file
64
components/terrain/texturemanager.cpp
Normal file
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
39
components/terrain/texturemanager.hpp
Normal file
39
components/terrain/texturemanager.hpp
Normal file
|
@ -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…
Reference in a new issue