forked from mirror/openmw-tes3mp
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);
|
mResourceSystem->updateCache(mReferenceTime);
|
||||||
|
|
||||||
mTerrain->updateCache();
|
mTerrain->updateCache(mReferenceTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -114,7 +114,7 @@ add_component_dir (translation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (terrain
|
add_component_dir (terrain
|
||||||
storage world buffercache defs terraingrid material terraindrawable
|
storage world buffercache defs terraingrid material terraindrawable texturemanager
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (loadinglistener
|
add_component_dir (loadinglistener
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "material.hpp"
|
#include "material.hpp"
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
#include "terraindrawable.hpp"
|
#include "terraindrawable.hpp"
|
||||||
|
#include "texturemanager.hpp"
|
||||||
|
|
||||||
namespace
|
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
|
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;
|
std::vector<TextureLayer> layers;
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
|
|
||||||
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
|
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
|
||||||
{
|
{
|
||||||
TextureLayer textureLayer;
|
TextureLayer textureLayer;
|
||||||
textureLayer.mParallax = it->mParallax;
|
textureLayer.mParallax = it->mParallax;
|
||||||
textureLayer.mSpecular = it->mSpecular;
|
textureLayer.mSpecular = it->mSpecular;
|
||||||
osg::ref_ptr<osg::Texture2D> texture = mTextureCache[it->mDiffuseMap];
|
|
||||||
if (!texture)
|
textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap);
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!it->mNormalMap.empty())
|
if (!it->mNormalMap.empty())
|
||||||
{
|
{
|
||||||
texture = mTextureCache[it->mNormalMap];
|
textureLayer.mNormalMap = mTextureManager->getTexture(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it->requiresShaders())
|
if (it->requiresShaders())
|
||||||
|
@ -266,7 +249,7 @@ void TerrainGrid::unloadCell(int x, int y)
|
||||||
mGrid.erase(it);
|
mGrid.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainGrid::updateCache()
|
void TerrainGrid::updateCache(double referenceTime)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||||
|
@ -278,24 +261,11 @@ void TerrainGrid::updateCache()
|
||||||
++it;
|
++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()
|
void TerrainGrid::updateTextureFiltering()
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mTextureCacheMutex);
|
mTextureManager->updateTextureFiltering();
|
||||||
for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end(); ++it)
|
|
||||||
mResourceSystem->getSceneManager()->applyFilterSettings(it->second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainGrid::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
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);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||||
stats->setAttribute(frameNumber, "Terrain Cell", mGridCache.size());
|
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
|
/// Clear cached objects that are no longer referenced
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
void updateCache();
|
void updateCache(double referenceTime);
|
||||||
|
|
||||||
/// Apply the scene manager's texture filtering settings to all cached textures.
|
/// Apply the scene manager's texture filtering settings to all cached textures.
|
||||||
/// @note Thread safe.
|
/// @note Thread safe.
|
||||||
|
@ -57,10 +57,6 @@ namespace Terrain
|
||||||
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
|
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
|
||||||
unsigned int mNumSplits;
|
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;
|
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > Grid;
|
||||||
Grid mGrid;
|
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 <osg/Group>
|
||||||
#include <osgUtil/IncrementalCompileOperation>
|
#include <osgUtil/IncrementalCompileOperation>
|
||||||
|
|
||||||
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
|
#include "texturemanager.hpp"
|
||||||
|
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
|
@ -21,10 +24,16 @@ World::World(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUt
|
||||||
mTerrainRoot->setName("Terrain Root");
|
mTerrainRoot->setName("Terrain Root");
|
||||||
|
|
||||||
mParent->addChild(mTerrainRoot);
|
mParent->addChild(mTerrainRoot);
|
||||||
|
|
||||||
|
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
|
||||||
|
|
||||||
|
mResourceSystem->addResourceManager(mTextureManager.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
World::~World()
|
World::~World()
|
||||||
{
|
{
|
||||||
|
mResourceSystem->removeResourceManager(mTextureManager.get());
|
||||||
|
|
||||||
mParent->removeChild(mTerrainRoot);
|
mParent->removeChild(mTerrainRoot);
|
||||||
|
|
||||||
delete mStorage;
|
delete mStorage;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
#include "buffercache.hpp"
|
#include "buffercache.hpp"
|
||||||
|
|
||||||
|
@ -26,6 +28,8 @@ namespace Terrain
|
||||||
{
|
{
|
||||||
class Storage;
|
class Storage;
|
||||||
|
|
||||||
|
class TextureManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
|
* @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
|
||||||
* is up to the implementation.
|
* is up to the implementation.
|
||||||
|
@ -42,7 +46,7 @@ namespace Terrain
|
||||||
|
|
||||||
virtual void updateTextureFiltering() {}
|
virtual void updateTextureFiltering() {}
|
||||||
|
|
||||||
virtual void updateCache() {}
|
virtual void updateCache(double referenceTime) {}
|
||||||
|
|
||||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
||||||
|
|
||||||
|
@ -65,6 +69,8 @@ namespace Terrain
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
||||||
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
||||||
|
|
||||||
|
std::auto_ptr<TextureManager> mTextureManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue