From 3cb9af0dd6998444ee78605976158e22b33236a9 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 15 Jan 2007 10:11:23 +0000 Subject: [PATCH] From Brede Johansen, "The OpenFlight loader already have a caching mechanism for externals. The cache works for nested externals but is cleared before the master flight file is returned. I implemented texture caching using the same mechanism." --- src/osgPlugins/OpenFlight/PaletteRecords.cpp | 66 ++++++++++++------- src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp | 4 +- src/osgPlugins/OpenFlight/Registry.h | 31 +++++++-- 3 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/osgPlugins/OpenFlight/PaletteRecords.cpp b/src/osgPlugins/OpenFlight/PaletteRecords.cpp index 33d693915..356cd049d 100644 --- a/src/osgPlugins/OpenFlight/PaletteRecords.cpp +++ b/src/osgPlugins/OpenFlight/PaletteRecords.cpp @@ -246,7 +246,7 @@ protected: virtual ~TexturePalette() {} - osg::Texture2D::WrapMode convertWrapMode(int32 attrWrapMode, const Document& document) + osg::Texture2D::WrapMode convertWrapMode(int32 attrWrapMode, const Document& document) const { osg::Texture2D::WrapMode osgWrapMode = osg::Texture2D::REPEAT; switch (attrWrapMode) @@ -268,33 +268,19 @@ protected: return osgWrapMode; } - virtual void readRecord(RecordInputStream& in, Document& document) + osg::StateSet* readTexture(const std::string& filename, const Document& document) const { - if (document.getTexturePoolParent()) - // Using parent's texture pool -- ignore this record. - return; + osg::Image* image = osgDB::readImageFile(filename,document.getOptions()); + if (!image) return NULL; - int maxLength = (document.version() < VERSION_14) ? 80 : 200; - std::string filename = in.readString(maxLength); - int32 index = in.readInt32(-1); - /*int32 x =*/ in.readInt32(); - /*int32 y =*/ in.readInt32(); - - osg::ref_ptr image = osgDB::readImageFile(filename,document.getOptions()); - if (!image.valid()) - { - osg::notify(osg::WARN) << "Can't find texture (" << index << ") " << filename << std::endl; - return; - } - - // Create stateset - osg::ref_ptr stateset = new osg::StateSet; + // Create stateset to hold texture and attributes. + osg::StateSet* stateset = new osg::StateSet; osg::Texture2D* texture = new osg::Texture2D; texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT); texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT); texture->setResizeNonPowerOfTwoHint(true); - texture->setImage(image.get()); + texture->setImage(image); stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); // Read attribute file @@ -383,8 +369,44 @@ protected: stateset->setTextureAttribute(0, texenv); } + return stateset; + } + + virtual void readRecord(RecordInputStream& in, Document& document) + { + if (document.getTexturePoolParent()) + // Using parent's texture pool -- ignore this record. + return; + + int maxLength = (document.version() < VERSION_14) ? 80 : 200; + std::string filename = in.readString(maxLength); + int32 index = in.readInt32(-1); + /*int32 x =*/ in.readInt32(); + /*int32 y =*/ in.readInt32(); + + // Need full path for unique key in local texture cache. + std::string pathname = osgDB::findDataFile(filename,document.getOptions()); + if (pathname.empty()) + { + osg::notify(osg::WARN) << "Can't find texture (" << index << ") " << filename << std::endl; + return; + } + + // Is texture in local cache? + osg::StateSet* stateset = flt::Registry::instance()->getTextureFromLocalCache(pathname); + + // Read file if not in cache. + if (!stateset) + { + stateset = readTexture(pathname,document); + + // Add to texture cache. + flt::Registry::instance()->addTextureToLocalCache(pathname,stateset); + } + + // Add to texture pool. TexturePool* tp = document.getOrCreateTexturePool(); - (*tp)[index] = stateset.get(); + (*tp)[index] = stateset; } }; diff --git a/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp index d74d63f4f..1209ea240 100644 --- a/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp +++ b/src/osgPlugins/OpenFlight/ReaderWriterFLT.cpp @@ -95,7 +95,7 @@ class FLTReaderWriter : public ReaderWriter // in local cache? { - osg::Node* node = flt::Registry::instance()->getFromLocalCache(fileName); + osg::Node* node = flt::Registry::instance()->getExternalFromLocalCache(fileName); if (node) return ReadResult(node, ReaderWriter::ReadResult::FILE_LOADED_FROM_CACHE); } @@ -122,7 +122,7 @@ class FLTReaderWriter : public ReaderWriter if (rr.success()) { // add to local cache. - flt::Registry::instance()->addToLocalCache(fileName,rr.getNode()); + flt::Registry::instance()->addExternalToLocalCache(fileName,rr.getNode()); bool keepExternalReferences = false; if (options) diff --git a/src/osgPlugins/OpenFlight/Registry.h b/src/osgPlugins/OpenFlight/Registry.h index fe65b6123..8a6f79da7 100644 --- a/src/osgPlugins/OpenFlight/Registry.h +++ b/src/osgPlugins/OpenFlight/Registry.h @@ -34,8 +34,10 @@ class Registry : public osg::Referenced void addToExternalReadQueue(const std::string& filename, osg::Group* parent); // Local cache - void addToLocalCache(const std::string& filename, osg::Node* node); - osg::Node* getFromLocalCache(const std::string& filename); + void addExternalToLocalCache(const std::string& filename, osg::Node* node); + osg::Node* getExternalFromLocalCache(const std::string& filename); + void addTextureToLocalCache(const std::string& filename, osg::StateSet* stateset); + osg::StateSet* getTextureFromLocalCache(const std::string& filename); void clearLocalCache(); protected: @@ -47,8 +49,13 @@ class Registry : public osg::Referenced ExternalQueue _externalReadQueue; + // External cache typedef std::map > ExternalCacheMap; - ExternalCacheMap _externalCacheMap; + ExternalCacheMap _externalCacheMap; + + // Texture cache + typedef std::map > TextureCacheMap; + TextureCacheMap _textureCacheMap; }; inline void Registry::addToExternalReadQueue(const std::string& filename, osg::Group* parent) @@ -56,12 +63,12 @@ inline void Registry::addToExternalReadQueue(const std::string& filename, osg::G _externalReadQueue.push( FilenameParentPair(filename,parent) ); } -inline void Registry::addToLocalCache(const std::string& filename, osg::Node* node) +inline void Registry::addExternalToLocalCache(const std::string& filename, osg::Node* node) { _externalCacheMap[filename] = node; } -inline osg::Node* Registry::getFromLocalCache(const std::string& filename) +inline osg::Node* Registry::getExternalFromLocalCache(const std::string& filename) { ExternalCacheMap::iterator itr = _externalCacheMap.find(filename); if (itr != _externalCacheMap.end()) @@ -69,9 +76,23 @@ inline osg::Node* Registry::getFromLocalCache(const std::string& filename) return NULL; } +inline void Registry::addTextureToLocalCache(const std::string& filename, osg::StateSet* stateset) +{ + _textureCacheMap[filename] = stateset; +} + +inline osg::StateSet* Registry::getTextureFromLocalCache(const std::string& filename) +{ + TextureCacheMap::iterator itr = _textureCacheMap.find(filename); + if (itr != _textureCacheMap.end()) + return (*itr).second.get(); + return NULL; +} + inline void Registry::clearLocalCache() { _externalCacheMap.clear(); + _textureCacheMap.clear(); } /** Proxy class for automatic registration of reader/writers with the Registry.*/