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.
coverity_scan
scrawl 9 years ago
parent fbd4ad9b0c
commit 6ef848b7c5

@ -2015,9 +2015,9 @@ namespace MWGui
continue; continue;
std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture; std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture;
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(tex_name, osg::Texture::CLAMP, osg::Texture::CLAMP); osg::ref_ptr<osg::Image> image = mResourceSystem->getTextureManager()->getImage(tex_name);
if(tex.valid()) if(image.valid())
{ {
//everything looks good, send it to the cursor manager //everything looks good, send it to the cursor manager
Uint8 size_x = imgSetPointer->getSize().width; Uint8 size_x = imgSetPointer->getSize().width;
@ -2026,7 +2026,7 @@ namespace MWGui
Uint8 hotspot_y = imgSetPointer->getHotSpot().top; Uint8 hotspot_y = imgSetPointer->getHotSpot().top;
int rotation = imgSetPointer->getRotation(); 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);
} }
} }
} }

@ -1059,7 +1059,10 @@ namespace MWRender
stream << i; stream << i;
stream << ".dds"; stream << ".dds";
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(stream.str(), osg::Texture2D::REPEAT, osg::Texture2D::REPEAT); osg::ref_ptr<osg::Image> image = mResourceSystem->getTextureManager()->getImage(stream.str());
osg::ref_ptr<osg::Texture2D> 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); mResourceSystem->getSceneManager()->applyFilterSettings(tex);
textures.push_back(tex); textures.push_back(tex);
} }

@ -231,6 +231,13 @@ namespace MWRender
return mResourceSystem; return mResourceSystem;
} }
void RenderingManager::clearCache()
{
mResourceSystem->clearCache();
if (mTerrain.get())
mTerrain->clearCache();
}
osg::Group* RenderingManager::getLightRoot() osg::Group* RenderingManager::getLightRoot()
{ {
return mLightRoot.get(); return mLightRoot.get();

@ -65,6 +65,8 @@ namespace MWRender
Resource::ResourceSystem* getResourceSystem(); Resource::ResourceSystem* getResourceSystem();
void clearCache();
osg::Group* getLightRoot(); osg::Group* getLightRoot();
void setNightEyeFactor(float factor); void setNightEyeFactor(float factor);

@ -15,6 +15,7 @@
#include <components/nifosg/controller.hpp> #include <components/nifosg/controller.hpp>
#include <components/resource/texturemanager.hpp> #include <components/resource/texturemanager.hpp>
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/fallback/fallback.hpp> #include <components/fallback/fallback.hpp>
#include "vismask.hpp" #include "vismask.hpp"
@ -39,7 +40,11 @@ namespace
{ {
std::ostringstream texname; std::ostringstream texname;
texname << "textures/water/" << tex << std::setw(2) << std::setfill('0') << i << ".dds"; 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<osg::Texture2D> 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<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 0.3f/rippleFrameCount, textures)); osg::ref_ptr<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 0.3f/rippleFrameCount, textures));

@ -476,9 +476,9 @@ public:
mTransform->addUpdateCallback(mUpdater); mTransform->addUpdateCallback(mUpdater);
mTransform->setNodeMask(Mask_Sun); mTransform->setNodeMask(Mask_Sun);
osg::ref_ptr<osg::Texture2D> sunTex = textureManager.getTexture2D("textures/tx_sun_05.dds", osg::ref_ptr<osg::Texture2D> sunTex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_05.dds")));
osg::Texture::CLAMP, sunTex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
osg::Texture::CLAMP); sunTex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, sunTex, osg::StateAttribute::ON); mGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, sunTex, osg::StateAttribute::ON);
@ -604,9 +604,9 @@ private:
void createSunFlash(Resource::TextureManager& textureManager) void createSunFlash(Resource::TextureManager& textureManager)
{ {
osg::ref_ptr<osg::Texture2D> tex = textureManager.getTexture2D("textures/tx_sun_flash_grey_05.dds", osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(textureManager.getImage("textures/tx_sun_flash_grey_05.dds")));
osg::Texture::CLAMP, tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
osg::Texture::CLAMP); tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
osg::ref_ptr<osg::PositionAttitudeTransform> transform (new osg::PositionAttitudeTransform); osg::ref_ptr<osg::PositionAttitudeTransform> transform (new osg::PositionAttitudeTransform);
const float scale = 2.6f; const float scale = 2.6f;
@ -1055,8 +1055,12 @@ private:
void setTextures(const std::string& phaseTex, const std::string& circleTex) void setTextures(const std::string& phaseTex, const std::string& circleTex)
{ {
mPhaseTex = mTextureManager.getTexture2D(phaseTex, osg::Texture::CLAMP, osg::Texture::CLAMP); mPhaseTex = new osg::Texture2D(mTextureManager.getImage(phaseTex));
mCircleTex = mTextureManager.getTexture2D(circleTex, osg::Texture::CLAMP, osg::Texture::CLAMP); 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(); reset();
} }
@ -1342,8 +1346,12 @@ void SkyManager::createRain()
mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,-1)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,-1));
osg::ref_ptr<osg::StateSet> stateset (mRainParticleSystem->getOrCreateStateSet()); osg::ref_ptr<osg::StateSet> 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<osg::Texture2D> 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->setNestRenderBins(false);
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); 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()); std::string texture = Misc::ResourceHelpers::correctTexturePath(mClouds, mSceneManager->getVFS());
mCloudUpdater->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture, osg::ref_ptr<osg::Texture2D> cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture)));
osg::Texture::REPEAT, osg::Texture::REPEAT)); 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) if (mNextClouds != weather.mNextCloudTexture)
@ -1561,8 +1572,11 @@ void SkyManager::setWeather(const WeatherResult& weather)
{ {
std::string texture = Misc::ResourceHelpers::correctTexturePath(mNextClouds, mSceneManager->getVFS()); std::string texture = Misc::ResourceHelpers::correctTexturePath(mNextClouds, mSceneManager->getVFS());
mCloudUpdater2->setTexture(mSceneManager->getTextureManager()->getTexture2D(texture, osg::ref_ptr<osg::Texture2D> cloudTex (new osg::Texture2D(mSceneManager->getTextureManager()->getImage(texture)));
osg::Texture::REPEAT, osg::Texture::REPEAT)); cloudTex->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
cloudTex->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
mCloudUpdater2->setTexture(cloudTex);
} }
} }

@ -15,8 +15,10 @@ void overrideTexture(const std::string &texture, Resource::ResourceSystem *resou
return; return;
std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, resourceSystem->getVFS()); std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, resourceSystem->getVFS());
// Not sure if wrap settings should be pulled from the overridden texture? // Not sure if wrap settings should be pulled from the overridden texture?
osg::ref_ptr<osg::Texture2D> tex = resourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP, osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D(resourceSystem->getTextureManager()->getImage(correctedTexture));
osg::Texture2D::CLAMP); 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<osg::StateSet> stateset; osg::ref_ptr<osg::StateSet> stateset;
if (node->getStateSet()) if (node->getStateSet())
stateset = static_cast<osg::StateSet*>(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY)); stateset = static_cast<osg::StateSet*>(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY));

@ -317,6 +317,7 @@ public:
mRefractionTexture->setInternalFormat(GL_RGB); mRefractionTexture->setInternalFormat(GL_RGB);
mRefractionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mRefractionTexture->setFilter(osg::Texture::MAG_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); attach(osg::Camera::COLOR_BUFFER, mRefractionTexture);
@ -328,6 +329,7 @@ public:
mRefractionDepthTexture->setSourceType(GL_UNSIGNED_INT); mRefractionDepthTexture->setSourceType(GL_UNSIGNED_INT);
mRefractionDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mRefractionDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mRefractionDepthTexture->setFilter(osg::Texture::MAG_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); attach(osg::Camera::DEPTH_BUFFER, mRefractionDepthTexture);
} }
@ -388,6 +390,7 @@ public:
mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 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_S, osg::Texture::CLAMP_TO_EDGE);
mReflectionTexture->setWrap(osg::Texture::WRAP_T, 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); attach(osg::Camera::COLOR_BUFFER, mReflectionTexture);
@ -553,7 +556,10 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
{ {
std::ostringstream texname; std::ostringstream texname;
texname << "textures/water/" << texture << std::setw(2) << std::setfill('0') << i << ".dds"; 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<osg::Texture2D> 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()) if (!textures.size())

@ -402,7 +402,7 @@ namespace MWWorld
mCellChanged = true; mCellChanged = true;
mRendering.getResourceSystem()->clearCache(); mRendering.clearCache();
} }
void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos) void Scene::changePlayerCell(CellStore *cell, const ESM::Position &pos, bool adjustPlayerPos)
@ -515,7 +515,7 @@ namespace MWWorld
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell); MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
mRendering.getResourceSystem()->clearCache(); mRendering.clearCache();
} }
void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos) void Scene::changeToExteriorCell (const ESM::Position& position, bool adjustPlayerPos)

@ -709,7 +709,9 @@ namespace NifOsg
} }
std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, textureManager->getVFS()); std::string filename = Misc::ResourceHelpers::correctTexturePath(st->filename, textureManager->getVFS());
osg::ref_ptr<osg::Texture2D> texture = textureManager->getTexture2D(filename, wrapS, wrapT); osg::ref_ptr<osg::Texture2D> 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); textures.push_back(texture);
} }
osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures)); osg::ref_ptr<FlipController> callback(new FlipController(flipctrl, textures));
@ -1376,9 +1378,10 @@ namespace NifOsg
int wrapT = (clamp) & 0x1; int wrapT = (clamp) & 0x1;
int wrapS = (clamp >> 1) & 0x1; int wrapS = (clamp >> 1) & 0x1;
osg::ref_ptr<osg::Texture2D> texture2d = textureManager->getTexture2D(filename, // create a new texture, will later attempt to share using the SharedStateManager
wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP, osg::ref_ptr<osg::Texture2D> texture2d (new osg::Texture2D(textureManager->getImage(filename)));
wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP); 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(); int texUnit = boundTextures.size();

@ -4,8 +4,6 @@
#include <osg/GLExtensions> #include <osg/GLExtensions>
#include <osg/Version> #include <osg/Version>
#include <stdexcept>
#include <components/vfs/manager.hpp> #include <components/vfs/manager.hpp>
#ifdef OSG_LIBRARY_STATIC #ifdef OSG_LIBRARY_STATIC
@ -47,6 +45,7 @@ namespace Resource
TextureManager::TextureManager(const VFS::Manager *vfs) TextureManager::TextureManager(const VFS::Manager *vfs)
: mVFS(vfs) : mVFS(vfs)
, mWarningTexture(createWarningTexture()) , mWarningTexture(createWarningTexture())
, mWarningImage(mWarningTexture->getImage())
, mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba")) , mOptions(new osgDB::Options("dds_flip dds_dxt1_detect_rgba"))
{ {
} }
@ -56,13 +55,6 @@ namespace Resource
} }
/*
osg::ref_ptr<osg::Image> TextureManager::getImage(const std::string &filename)
{
}
*/
bool checkSupported(osg::Image* image, const std::string& filename) bool checkSupported(osg::Image* image, const std::string& filename)
{ {
switch(image->getPixelFormat()) switch(image->getPixelFormat())
@ -113,7 +105,7 @@ namespace Resource
catch (std::exception& e) catch (std::exception& e)
{ {
std::cerr << "Failed to open image: " << e.what() << std::endl; std::cerr << "Failed to open image: " << e.what() << std::endl;
return NULL; return mWarningImage;
} }
size_t extPos = normalized.find_last_of('.'); size_t extPos = normalized.find_last_of('.');
@ -124,20 +116,20 @@ namespace Resource
if (!reader) if (!reader)
{ {
std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl; std::cerr << "Error loading " << filename << ": no readerwriter for '" << ext << "' found" << std::endl;
return NULL; return mWarningImage;
} }
osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions); osgDB::ReaderWriter::ReadResult result = reader->readImage(*stream, mOptions);
if (!result.success()) if (!result.success())
{ {
std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl; std::cerr << "Error loading " << filename << ": " << result.message() << " code " << result.status() << std::endl;
return NULL; return mWarningImage;
} }
osg::Image* image = result.getImage(); osg::Image* image = result.getImage();
if (!checkSupported(image, filename)) if (!checkSupported(image, filename))
{ {
return NULL; return mWarningImage;
} }
mImages.insert(std::make_pair(normalized, image)); mImages.insert(std::make_pair(normalized, image));
@ -145,63 +137,6 @@ namespace Resource
} }
} }
osg::ref_ptr<osg::Texture2D> 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<MapKey, osg::ref_ptr<osg::Texture2D> >::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<osg::Texture2D> 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() osg::Texture2D* TextureManager::getWarningTexture()
{ {
return mWarningTexture.get(); return mWarningTexture.get();

@ -26,18 +26,15 @@ namespace osgDB
namespace Resource namespace Resource
{ {
/// @brief Handles loading/caching of Images and Texture StateAttributes. /// @brief Handles loading/caching of Images.
class TextureManager class TextureManager
{ {
public: public:
TextureManager(const VFS::Manager* vfs); TextureManager(const VFS::Manager* vfs);
~TextureManager(); ~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<osg::Texture2D> getTexture2D(const std::string& filename, osg::Texture::WrapMode wrapS, osg::Texture::WrapMode wrapT);
/// Create or retrieve an Image /// Create or retrieve an Image
/// Returns the dummy image if the given image is not found.
osg::ref_ptr<osg::Image> getImage(const std::string& filename); osg::ref_ptr<osg::Image> getImage(const std::string& filename);
const VFS::Manager* getVFS() { return mVFS; } const VFS::Manager* getVFS() { return mVFS; }
@ -47,13 +44,11 @@ namespace Resource
private: private:
const VFS::Manager* mVFS; const VFS::Manager* mVFS;
typedef std::pair<std::pair<int, int>, std::string> MapKey; // TODO: use ObjectCache
std::map<std::string, osg::ref_ptr<osg::Image> > mImages; std::map<std::string, osg::ref_ptr<osg::Image> > mImages;
std::map<MapKey, osg::ref_ptr<osg::Texture2D> > mTextures;
osg::ref_ptr<osg::Texture2D> mWarningTexture; osg::ref_ptr<osg::Texture2D> mWarningTexture;
osg::ref_ptr<osg::Image> mWarningImage;
osg::ref_ptr<osgDB::Options> mOptions; osg::ref_ptr<osgDB::Options> mOptions;
TextureManager(const TextureManager&); TextureManager(const TextureManager&);

@ -4,6 +4,7 @@
#include <components/resource/resourcesystem.hpp> #include <components/resource/resourcesystem.hpp>
#include <components/resource/texturemanager.hpp> #include <components/resource/texturemanager.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/positionattitudetransform.hpp> #include <components/sceneutil/positionattitudetransform.hpp>
@ -134,10 +135,19 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
// For compiling textures, I don't think the osgFX::Effect does it correctly // For compiling textures, I don't think the osgFX::Effect does it correctly
osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node); osg::ref_ptr<osg::Node> textureCompileDummy (new osg::Node);
unsigned int dummyTextureCounter = 0; unsigned int dummyTextureCounter = 0;
std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures; std::vector<osg::ref_ptr<osg::Texture2D> > layerTextures;
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)
{ {
layerTextures.push_back(mResourceSystem->getTextureManager()->getTexture2D(it->mDiffuseMap, osg::Texture::REPEAT, osg::Texture::REPEAT)); osg::ref_ptr<osg::Texture2D> 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()); textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, layerTextures.back());
} }
@ -148,15 +158,18 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
texture->setImage(*it); texture->setImage(*it);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, 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->setResizeNonPowerOfTwoHint(false);
texture->getOrCreateUserDataContainer()->addDescription("dont_override_filter"); texture->getOrCreateUserDataContainer()->addDescription("dont_override_filter");
blendmapTextures.push_back(texture); blendmapTextures.push_back(texture);
mResourceSystem->getSceneManager()->applyFilterSettings(texture);
textureCompileDummy->getOrCreateStateSet()->setTextureAttributeAndModes(dummyTextureCounter++, blendmapTextures.back()); 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 // use texture coordinates for both texture units, the layer texture and blend texture
for (unsigned int i=0; i<2; ++i) for (unsigned int i=0; i<2; ++i)
geometry->setTexCoordArray(i, mCache.getUVBuffer()); geometry->setTexCoordArray(i, mCache.getUVBuffer());
@ -226,4 +239,15 @@ void TerrainGrid::unloadCell(int x, int y)
mGrid.erase(it); 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;
}
}
} }

@ -27,12 +27,18 @@ namespace Terrain
virtual void loadCell(int x, int y); virtual void loadCell(int x, int y);
virtual void unloadCell(int x, int y); virtual void unloadCell(int x, int y);
/// Clear cached textures that are no longer referenced
void clearCache();
private: private:
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter); osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
// 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;
typedef std::map<std::pair<int, int>, GridElement*> Grid; typedef std::map<std::pair<int, int>, GridElement*> Grid;
Grid mGrid; Grid mGrid;

@ -39,6 +39,8 @@ namespace Terrain
Storage* storage, int nodeMask); Storage* storage, int nodeMask);
virtual ~World(); virtual ~World();
virtual void clearCache() {}
float getHeightAt (const osg::Vec3f& worldPos); float getHeightAt (const osg::Vec3f& worldPos);
// This is only a hint and may be ignored by the implementation. // This is only a hint and may be ignored by the implementation.

Loading…
Cancel
Save