From 6ef848b7c50497438dd0cf85a17709a7bb0dfb75 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 5 Feb 2016 22:58:02 +0100 Subject: [PATCH] Remove TextureManager::getTexture2D Instead use getImage and let the caller create the Texture. Sharing of textures is then handled in post by the SharedStateManager. This is closer to what the OSG serializer does. Streamlines the TextureManager and will make it easier to multithread. --- apps/openmw/mwgui/windowmanagerimp.cpp | 6 +- apps/openmw/mwrender/animation.cpp | 5 +- apps/openmw/mwrender/renderingmanager.cpp | 7 +++ apps/openmw/mwrender/renderingmanager.hpp | 2 + apps/openmw/mwrender/ripplesimulation.cpp | 7 ++- apps/openmw/mwrender/sky.cpp | 42 ++++++++----- apps/openmw/mwrender/util.cpp | 6 +- apps/openmw/mwrender/water.cpp | 8 ++- apps/openmw/mwworld/scene.cpp | 4 +- components/nifosg/nifloader.cpp | 11 ++-- components/resource/texturemanager.cpp | 75 ++--------------------- components/resource/texturemanager.hpp | 13 ++-- components/terrain/terraingrid.cpp | 30 ++++++++- components/terrain/terraingrid.hpp | 6 ++ components/terrain/world.hpp | 2 + 15 files changed, 114 insertions(+), 110 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 90c0494f6..346c672f7 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -2015,9 +2015,9 @@ namespace MWGui continue; std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture; - osg::ref_ptr tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP); + osg::ref_ptr image = mResourceSystem->getTextureManager()->getImage(tex_name); - if(tex.valid()) + if(image.valid()) { //everything looks good, send it to the cursor manager Uint8 size_x = imgSetPointer->getSize().width; @@ -2026,7 +2026,7 @@ namespace MWGui Uint8 hotspot_y = imgSetPointer->getHotSpot().top; int rotation = imgSetPointer->getRotation(); - mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, tex->getImage(), size_x, size_y, hotspot_x, hotspot_y); + mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, image, size_x, size_y, hotspot_x, hotspot_y); } } } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a7bb3f128..35602fa17 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1059,7 +1059,10 @@ namespace MWRender stream << i; stream << ".dds"; - osg::ref_ptr tex = mResourceSystem->getTextureManager()->getTexture2D(stream.str(), osg::Texture2D::REPEAT, osg::Texture2D::REPEAT); + osg::ref_ptr image = mResourceSystem->getTextureManager()->getImage(stream.str()); + osg::ref_ptr tex (new osg::Texture2D(image)); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture2D::REPEAT); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture2D::REPEAT); mResourceSystem->getSceneManager()->applyFilterSettings(tex); textures.push_back(tex); } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 755a8019b..2237d8125 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -231,6 +231,13 @@ namespace MWRender return mResourceSystem; } + void RenderingManager::clearCache() + { + mResourceSystem->clearCache(); + if (mTerrain.get()) + mTerrain->clearCache(); + } + osg::Group* RenderingManager::getLightRoot() { return mLightRoot.get(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 3b583af89..550e48e63 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -65,6 +65,8 @@ namespace MWRender Resource::ResourceSystem* getResourceSystem(); + void clearCache(); + osg::Group* getLightRoot(); void setNightEyeFactor(float factor); diff --git a/apps/openmw/mwrender/ripplesimulation.cpp b/apps/openmw/mwrender/ripplesimulation.cpp index f74631c4a..603cd397b 100644 --- a/apps/openmw/mwrender/ripplesimulation.cpp +++ b/apps/openmw/mwrender/ripplesimulation.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "vismask.hpp" @@ -39,7 +40,11 @@ namespace { std::ostringstream texname; texname << "textures/water/" << tex << std::setw(2) << std::setfill('0') << i << ".dds"; - textures.push_back(resourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT)); + osg::ref_ptr tex (new osg::Texture2D(resourceSystem->getTextureManager()->getImage(texname.str()))); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + resourceSystem->getSceneManager()->applyFilterSettings(tex); + textures.push_back(tex); } osg::ref_ptr controller (new NifOsg::FlipController(0, 0.3f/rippleFrameCount, textures)); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 513fc74a3..2a25baea9 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -476,9 +476,9 @@ public: mTransform->addUpdateCallback(mUpdater); mTransform->setNodeMask(Mask_Sun); - osg::ref_ptr sunTex = textureManager.getTexture2D("textures/tx_sun_05.dds", - osg::Texture::CLAMP, - osg::Texture::CLAMP); + osg::ref_ptr sunTex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_05.dds"))); + sunTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + sunTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); mGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, sunTex, osg::StateAttribute::ON); @@ -604,9 +604,9 @@ private: void createSunFlash(Resource::TextureManager& textureManager) { - osg::ref_ptr tex = textureManager.getTexture2D("textures/tx_sun_flash_grey_05.dds", - osg::Texture::CLAMP, - osg::Texture::CLAMP); + osg::ref_ptr tex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_flash_grey_05.dds"))); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); osg::ref_ptr transform (new osg::PositionAttitudeTransform); const float scale = 2.6f; @@ -1055,8 +1055,12 @@ private: void setTextures(const std::string& phaseTex, const std::string& circleTex) { - mPhaseTex = mTextureManager.getTexture2D(phaseTex, osg::Texture::CLAMP, osg::Texture::CLAMP); - mCircleTex = mTextureManager.getTexture2D(circleTex, osg::Texture::CLAMP, osg::Texture::CLAMP); + mPhaseTex = new osg::Texture2D(mTextureManager.getImage(phaseTex)); + mPhaseTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mPhaseTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mCircleTex = new osg::Texture2D(mTextureManager.getImage(circleTex)); + mCircleTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + mCircleTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); reset(); } @@ -1342,8 +1346,12 @@ void SkyManager::createRain() mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,-1)); osg::ref_ptr stateset (mRainParticleSystem->getOrCreateStateSet()); - stateset->setTextureAttributeAndModes(0, mSceneManager->getTextureManager()->getTexture2D("textures/tx_raindrop_01.dds", - osg::Texture::CLAMP, osg::Texture::CLAMP), osg::StateAttribute::ON); + + osg::ref_ptr raindropTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage("textures/tx_raindrop_01.dds"))); + raindropTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + raindropTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + + stateset->setTextureAttributeAndModes(0, raindropTex, osg::StateAttribute::ON); stateset->setNestRenderBins(false); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); @@ -1549,8 +1557,11 @@ void SkyManager::setWeather(const WeatherResult& weather) std::string texture = Misc::ResourceHelpers::correctTexturePath(mClouds, mSceneManager->getVFS()); - mCloudUpdater->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture, - osg::Texture::REPEAT, osg::Texture::REPEAT)); + osg::ref_ptr cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture))); + cloudTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + cloudTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + + mCloudUpdater->setTexture(cloudTex); } if (mNextClouds != weather.mNextCloudTexture) @@ -1561,8 +1572,11 @@ void SkyManager::setWeather(const WeatherResult& weather) { std::string texture = Misc::ResourceHelpers::correctTexturePath(mNextClouds, mSceneManager->getVFS()); - mCloudUpdater2->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture, - osg::Texture::REPEAT, osg::Texture::REPEAT)); + osg::ref_ptr cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture))); + cloudTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + cloudTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + + mCloudUpdater2->setTexture(cloudTex); } } diff --git a/apps/openmw/mwrender/util.cpp b/apps/openmw/mwrender/util.cpp index e1af1c339..df6a0497f 100644 --- a/apps/openmw/mwrender/util.cpp +++ b/apps/openmw/mwrender/util.cpp @@ -15,8 +15,10 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou return; std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, resourceSystem->getVFS()); // Not sure if wrap settings should be pulled from the overridden texture? - osg::ref_ptr tex = resourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP, - osg::Texture2D::CLAMP); + osg::ref_ptr tex = new osg::Texture2D(resourceSystem->getTextureManager()->getImage(correctedTexture)); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + osg::ref_ptr stateset; if (node->getStateSet()) stateset = static_cast(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY)); diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index c7f2c9cc6..ff3156411 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -317,6 +317,7 @@ public: mRefractionTexture->setInternalFormat(GL_RGB); mRefractionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mRefractionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::COLOR_BUFFER, mRefractionTexture); @@ -328,6 +329,7 @@ public: mRefractionDepthTexture->setSourceType(GL_UNSIGNED_INT); mRefractionDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionDepthTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mRefractionDepthTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::DEPTH_BUFFER, mRefractionDepthTexture); } @@ -388,6 +390,7 @@ public: mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); mReflectionTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); mReflectionTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mReflectionTexture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); attach(osg::Camera::COLOR_BUFFER, mReflectionTexture); @@ -553,7 +556,10 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha) { std::ostringstream texname; texname << "textures/water/" << texture << std::setw(2) << std::setfill('0') << i << ".dds"; - textures.push_back(mResourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT)); + osg::ref_ptr tex (new osg::Texture2D(mResourceSystem->getTextureManager()->getImage(texname.str()))); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + textures.push_back(tex); } if (!textures.size()) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 618a219f3..f30e6efe1 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -402,7 +402,7 @@ namespace MWWorld mCellChanged = true; - mRendering.getResourceSystem()->clearCache(); + mRendering.clearCache(); } void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos) @@ -515,7 +515,7 @@ namespace MWWorld MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); - mRendering.getResourceSystem()->clearCache(); + mRendering.clearCache(); } void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 79f837953..190fd020f 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -709,7 +709,9 @@ namespace NifOsg } std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, textureManager->getVFS()); - osg::ref_ptr texture = textureManager->getTexture2D(filename, wrapS, wrapT); + osg::ref_ptr texture (new osg::Texture2D(textureManager->getImage(filename))); + texture->setWrap(osg::Texture::WRAP_S, wrapS); + texture->setWrap(osg::Texture::WRAP_T, wrapT); textures.push_back(texture); } osg::ref_ptr callback(new FlipController(flipctrl, textures)); @@ -1376,9 +1378,10 @@ namespace NifOsg int wrapT = (clamp) & 0x1; int wrapS = (clamp >> 1) & 0x1; - osg::ref_ptr texture2d = textureManager->getTexture2D(filename, - wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP, - wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); + // create a new texture, will later attempt to share using the SharedStateManager + osg::ref_ptr texture2d (new osg::Texture2D(textureManager->getImage(filename))); + texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP); + texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); int texUnit = boundTextures.size(); diff --git a/components/resource/texturemanager.cpp b/components/resource/texturemanager.cpp index 709b925f1..b3f23ab40 100644 --- a/components/resource/texturemanager.cpp +++ b/components/resource/texturemanager.cpp @@ -4,8 +4,6 @@ #include #include -#include - #include #ifdef OSG_LIBRARY_STATIC @@ -47,6 +45,7 @@ namespace Resource TextureManager::TextureManager(const VFS::Manager *vfs) : mVFS(vfs) , mWarningTexture(createWarningTexture()) + , mWarningImage(mWarningTexture->getImage()) , mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba")) { } @@ -56,13 +55,6 @@ namespace Resource } - /* - osg::ref_ptr TextureManager::getImage(const std::string &filename) - { - - } - */ - bool checkSupported(osg::Image* image, const std::string& filename) { switch(image->getPixelFormat()) @@ -113,7 +105,7 @@ namespace Resource catch (std::exception& e) { std::cerr << "Failed to open image: " << e.what() << std::endl; - return NULL; + return mWarningImage; } size_t extPos = normalized.find_last_of('.'); @@ -124,20 +116,20 @@ namespace Resource if (!reader) { std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl; - return NULL; + return mWarningImage; } osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); if (!result.success()) { std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl; - return NULL; + return mWarningImage; } osg::Image* image = result.getImage(); if (!checkSupported(image, filename)) { - return NULL; + return mWarningImage; } mImages.insert(std::make_pair(normalized, image)); @@ -145,63 +137,6 @@ namespace Resource } } - osg::ref_ptr TextureManager::getTexture2D(const std::string &filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT) - { - std::string normalized = filename; - mVFS->normalizeFilename(normalized); - MapKey key = std::make_pair(std::make_pair(wrapS, wrapT), normalized); - std::map >::iterator found = mTextures.find(key); - if (found != mTextures.end()) - { - return found->second; - } - else - { - Files::IStreamPtr stream; - try - { - stream = mVFS->get(normalized.c_str()); - } - catch (std::exception& e) - { - std::cerr << "Failed to open texture: " << e.what() << std::endl; - return mWarningTexture; - } - - size_t extPos = normalized.find_last_of('.'); - std::string ext; - if (extPos != std::string::npos && extPos+1 < normalized.size()) - ext = normalized.substr(extPos+1); - osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension(ext); - if (!reader) - { - std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl; - return mWarningTexture; - } - - osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); - if (!result.success()) - { - std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl; - return mWarningTexture; - } - - osg::Image* image = result.getImage(); - if (!checkSupported(image, filename)) - { - return mWarningTexture; - } - - osg::ref_ptr texture(new osg::Texture2D); - texture->setImage(image); - texture->setWrap(osg::Texture::WRAP_S, wrapS); - texture->setWrap(osg::Texture::WRAP_T, wrapT); - - mTextures.insert(std::make_pair(key, texture)); - return texture; - } - } - osg::Texture2D* TextureManager::getWarningTexture() { return mWarningTexture.get(); diff --git a/components/resource/texturemanager.hpp b/components/resource/texturemanager.hpp index cb2711aa7..0290d2340 100644 --- a/components/resource/texturemanager.hpp +++ b/components/resource/texturemanager.hpp @@ -26,18 +26,15 @@ namespace osgDB namespace Resource { - /// @brief Handles loading/caching of Images and Texture StateAttributes. + /// @brief Handles loading/caching of Images. class TextureManager { public: TextureManager(const VFS::Manager* vfs); ~TextureManager(); - /// Create or retrieve a Texture2D using the specified image filename, and wrap parameters. - /// Returns the dummy texture if the given texture is not found. - osg::ref_ptr getTexture2D(const std::string& filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT); - /// Create or retrieve an Image + /// Returns the dummy image if the given image is not found. osg::ref_ptr getImage(const std::string& filename); const VFS::Manager* getVFS() { return mVFS; } @@ -47,13 +44,11 @@ namespace Resource private: const VFS::Manager* mVFS; - typedef std::pair, std::string> MapKey; - + // TODO: use ObjectCache std::map > mImages; - std::map > mTextures; - osg::ref_ptr mWarningTexture; + osg::ref_ptr mWarningImage; osg::ref_ptr mOptions; TextureManager(const TextureManager&); diff --git a/components/terrain/terraingrid.cpp b/components/terrain/terraingrid.cpp index b7d727730..58675a714 100644 --- a/components/terrain/terraingrid.cpp +++ b/components/terrain/terraingrid.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -134,10 +135,19 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu // For compiling textures, I don't think the osgFX::Effect does it correctly osg::ref_ptr textureCompileDummy (new osg::Node); unsigned int dummyTextureCounter = 0; + std::vector > layerTextures; for (std::vector::const_iterator it = layerList.begin(); it != layerList.end(); ++it) { - layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT)); + osg::ref_ptr tex = mTextureCache[it->mDiffuseMap]; + if (!tex) + { + tex = new osg::Texture2D(mResourceSystem->getTextureManager()->getImage(it->mDiffuseMap)); + tex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); + tex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); + mTextureCache[it->mDiffuseMap] = tex; + } + layerTextures.push_back(tex); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, layerTextures.back()); } @@ -148,15 +158,18 @@ osg::ref_ptr TerrainGrid::buildTerrain (osg::Group* parent, float chu texture->setImage(*it); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); - texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture->setResizeNonPowerOfTwoHint(false); texture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); blendmapTextures.push_back(texture); + mResourceSystem->getSceneManager()->applyFilterSettings(texture); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, blendmapTextures.back()); } + // SharedStatemanager->share(textureCompileDummy); + + // Remove unrefImageDataAfterApply for better state sharing + // use texture coordinates for both texture units, the layer texture and blend texture for (unsigned int i=0; i<2; ++i) geometry->setTexCoordArray(i, mCache.getUVBuffer()); @@ -226,4 +239,15 @@ void TerrainGrid::unloadCell(int x, int y) mGrid.erase(it); } +void TerrainGrid::clearCache() +{ + for (TextureCache::iterator it = mTextureCache.begin(); it != mTextureCache.end();) + { + if (it->second->referenceCount() <= 1) + mTextureCache.erase(it++); + else + ++it; + } +} + } diff --git a/components/terrain/terraingrid.hpp b/components/terrain/terraingrid.hpp index 169a9a622..81bfc4211 100644 --- a/components/terrain/terraingrid.hpp +++ b/components/terrain/terraingrid.hpp @@ -27,12 +27,18 @@ namespace Terrain virtual void loadCell(int x, int y); virtual void unloadCell(int x, int y); + /// Clear cached textures that are no longer referenced + void clearCache(); + private: osg::ref_ptr buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter); // split each ESM::Cell into mNumSplits*mNumSplits terrain chunks unsigned int mNumSplits; + typedef std::map > TextureCache; + TextureCache mTextureCache; + typedef std::map, GridElement*> Grid; Grid mGrid; diff --git a/components/terrain/world.hpp b/components/terrain/world.hpp index 4212f2a0c..bd5d0a466 100644 --- a/components/terrain/world.hpp +++ b/components/terrain/world.hpp @@ -39,6 +39,8 @@ namespace Terrain Storage* storage, int nodeMask); virtual ~World(); + virtual void clearCache() {} + float getHeightAt (const osg::Vec3f& worldPos); // This is only a hint and may be ignored by the implementation.