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.