X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2FModelRegistry.hxx;h=8c8e7467386cd6c7bda347f6678cdb89147f9445;hb=32a6bd78d8bf143f40922f1a0bc7a88ea7706a7d;hp=770d4ee4f5ed45a135a3e5d0c3dc6c46bf0b1b95;hpb=2fbaddbecf27288e1da335dce591791e9a6016af;p=simgear.git diff --git a/simgear/scene/model/ModelRegistry.hxx b/simgear/scene/model/ModelRegistry.hxx index 770d4ee4..8c8e7467 100644 --- a/simgear/scene/model/ModelRegistry.hxx +++ b/simgear/scene/model/ModelRegistry.hxx @@ -1,5 +1,6 @@ // ModelRegistry.hxx -- interface to the OSG model registry // +// Copyright (C) 2005-2007 Mathias Froehlich // Copyright (C) 2007 Tim Moore // // This program is free software; you can redistribute it and/or @@ -19,39 +20,219 @@ #define _SG_MODELREGISTRY_HXX 1 #include +#include +#include +#include #include #include #include +#include -#include STL_STRING +#include #include +// Class to register per file extension read callbacks with the OSG +// registry, mostly to control caching and post load optimization / +// copying that happens above the level of the ReaderWriter. namespace simgear { -class ModelRegistry : public osgDB::Registry::ReadFileCallback { + +// Different caching and optimization strategies are needed for +// different file types. Most loaded files should be optimized and the +// optimized version should be cached. When an .osg file is +// substituted for another, it is assumed to be optimized already but +// it should be cached too (under the name of the original?). .stg +// files should not be cached (that's the pager's job) but the files +// it causes to be loaded should be. .btg files are already optimized +// and shouldn't be cached. +// +// Complicating this is the effect that removing CACHE_NODES has from +// the ReaderWriter options: it switches the object cache with an +// empty one, so that's not an option for the files that could be +// loaded from a .stg file. So, we'll let +// Registry::readNodeImplementation cache a loaded file and then add +// the optimized version to the cache ourselves, replacing the +// original subgraph. +// +// To support all these options with a minimum of duplication, the +// readNode function is specified as a template with a bunch of +// pluggable (and predefined) policies. +template +class ModelRegistryCallback : public osgDB::Registry::ReadFileCallback { public: + ModelRegistryCallback(const std::string& extension) : + _processPolicy(extension), _cachePolicy(extension), + _optimizePolicy(extension), + _substitutePolicy(extension), _bvhPolicy(extension) + { + } + virtual osgDB::ReaderWriter::ReadResult + readNode(const std::string& fileName, + const osgDB::Options* opt) + { + using namespace osg; + using namespace osgDB; + using osgDB::ReaderWriter; +// Registry* registry = Registry::instance(); + ref_ptr optimizedNode = _cachePolicy.find(fileName, opt); + if (!optimizedNode.valid()) { + std::string otherFileName = _substitutePolicy.substitute(fileName, + opt); + ReaderWriter::ReadResult res; + if (!otherFileName.empty()) { + res = loadUsingReaderWriter(otherFileName, opt); + if (res.validNode()) + optimizedNode = res.getNode(); + } + if (!optimizedNode.valid()) { + res = loadUsingReaderWriter(fileName, opt); + if (!res.validNode()) + return res; + ref_ptr processedNode + = _processPolicy.process(res.getNode(), fileName, opt); + optimizedNode = _optimizePolicy.optimize(processedNode.get(), + fileName, opt); + } + if (opt->getPluginStringData("SimGear::BOUNDINGVOLUMES") != "OFF") + _bvhPolicy.buildBVH(fileName, optimizedNode.get()); + _cachePolicy.addToCache(fileName, optimizedNode.get()); + } + return ReaderWriter::ReadResult(optimizedNode.get()); + } +protected: + static osgDB::ReaderWriter::ReadResult + loadUsingReaderWriter(const std::string& fileName, + const osgDB::Options* opt) + { + using namespace osgDB; + ReaderWriter* rw = Registry::instance() + ->getReaderWriterForExtension(osgDB::getFileExtension(fileName)); + if (!rw) + return ReaderWriter::ReadResult(); // FILE_NOT_HANDLED + return rw->readNode(fileName, opt); + } + + ProcessPolicy _processPolicy; + CachePolicy _cachePolicy; + OptimizePolicy _optimizePolicy; + SubstitutePolicy _substitutePolicy; + BVHPolicy _bvhPolicy; + virtual ~ModelRegistryCallback() {} +}; + +// Predefined policies + +struct DefaultProcessPolicy { + DefaultProcessPolicy(const std::string& extension) {} + osg::Node* process(osg::Node* node, const std::string& filename, + const osgDB::Options* opt); +}; + +struct DefaultCachePolicy { + DefaultCachePolicy(const std::string& extension) {} + osg::Node* find(const std::string& fileName, + const osgDB::Options* opt); + void addToCache(const std::string& filename, osg::Node* node); +}; + +struct NoCachePolicy { + NoCachePolicy(const std::string& extension) {} + osg::Node* find(const std::string& fileName, + const osgDB::Options* opt) + { + return 0; + } + void addToCache(const std::string& filename, osg::Node* node) {} +}; + +class OptimizeModelPolicy { +public: + OptimizeModelPolicy(const std::string& extension); + osg::Node* optimize(osg::Node* node, const std::string& fileName, + const osgDB::Options* opt); +protected: + unsigned _osgOptions; +}; + +struct NoOptimizePolicy { + NoOptimizePolicy(const std::string& extension) {} + osg::Node* optimize(osg::Node* node, const std::string& fileName, + const osgDB::Options* opt) + { + return node; + } +}; + +struct OSGSubstitutePolicy { + OSGSubstitutePolicy(const std::string& extension) {} + std::string substitute(const std::string& name, + const osgDB::Options* opt); +}; + +struct NoSubstitutePolicy { + NoSubstitutePolicy(const std::string& extension) {} + std::string substitute(const std::string& name, + const osgDB::Options* opt) + { + return std::string(); + } +}; + +struct BuildLeafBVHPolicy { + BuildLeafBVHPolicy(const std::string& extension) {} + void buildBVH(const std::string& fileName, osg::Node* node); +}; + +struct BuildGroupBVHPolicy { + BuildGroupBVHPolicy(const std::string& extension) {} + void buildBVH(const std::string& fileName, osg::Node* node); +}; + +struct NoBuildBVHPolicy { + NoBuildBVHPolicy(const std::string& extension) {} + void buildBVH(const std::string& fileName, osg::Node* node); +}; + +typedef ModelRegistryCallback +DefaultCallback; + +// The manager for the callbacks +class ModelRegistry : public osgDB::Registry::ReadFileCallback, + public ReferencedSingleton { +public: + ModelRegistry(); virtual osgDB::ReaderWriter::ReadResult readImage(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); + const osgDB::Options* opt); virtual osgDB::ReaderWriter::ReadResult readNode(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); + const osgDB::Options* opt); void addImageCallbackForExtension(const std::string& extension, osgDB::Registry::ReadFileCallback* callback); void addNodeCallbackForExtension(const std::string& extension, osgDB::Registry::ReadFileCallback* callback); - static ModelRegistry* getInstance(); + virtual ~ModelRegistry() {} protected: - static osg::ref_ptr instance; typedef std::map > CallbackMap; CallbackMap imageCallbackMap; CallbackMap nodeCallbackMap; + osg::ref_ptr _defaultCallback; }; +// Callback that only loads the file without any caching or +// postprocessing. +typedef ModelRegistryCallback +LoadOnlyCallback; + // Proxy for registering extension-based callbacks template @@ -60,23 +241,9 @@ class ModelRegistryCallbackProxy public: ModelRegistryCallbackProxy(std::string extension) { - ModelRegistry::getInstance()->addNodeCallbackForExtension(extension, - new T); + ModelRegistry::instance() + ->addNodeCallbackForExtension(extension, new T(extension)); } }; - -// Callback for file extensions that load files using the default OSG -// implementation. - -class OSGFileCallback : public osgDB::Registry::ReadFileCallback { -public: - virtual osgDB::ReaderWriter::ReadResult - readImage(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); - virtual osgDB::ReaderWriter::ReadResult - readNode(const std::string& fileName, - const osgDB::ReaderWriter::Options* opt); -}; - } #endif // _SG_MODELREGISTRY_HXX