X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2Fmodel.cxx;h=749b45c3f7d2a023a85f9b908f01a0c0c00e8db8;hb=084a24e958bbd7a040c3dafd09f74bb9e1c334ce;hp=1d278f7ee63faeb0647185340c8f7c057a6a6bd4;hpb=04cd9b3eb60f1b920d2270b3f87d8bc05af505b8;p=simgear.git diff --git a/simgear/scene/model/model.cxx b/simgear/scene/model/model.cxx index 1d278f7e..749b45c3 100644 --- a/simgear/scene/model/model.cxx +++ b/simgear/scene/model/model.cxx @@ -136,6 +136,9 @@ public: if (!texture) return; + // Hmm, true?? + texture->setDataVariance(osg::Object::STATIC); + osg::Image* image = texture->getImage(0); if (!image) return; @@ -207,28 +210,47 @@ public: readNode(const std::string& fileName, const osgDB::ReaderWriter::Options* opt) { - std::string absFileName = osgDB::findDataFile(fileName); + osgDB::Registry* registry = osgDB::Registry::instance(); + osgDB::ReaderWriter::ReadResult res; + osg::Node* cached = 0; + // The BTG loader automatically looks for ".btg.gz" if a file with + // the .btg extension doesn't exist. Also, we don't want to add + // nodes, run the optimizer, etc. on the btg model.So, let it do + // its thing. + if (osgDB::equalCaseInsensitive(osgDB::getFileExtension(fileName), "btg")) { + return registry->readNodeImplementation(fileName, opt); + } + // First, look for a file with the same name, and the extension + // ".osg" and, if it exists, load it instead. This allows for + // substitution of optimized models for ones named in the scenery. + bool optimizeModel = true; + std::string fileSansExtension = osgDB::getNameLessExtension(fileName); + std::string osgFileName = fileSansExtension + ".osg"; + std::string absFileName = osgDB::findDataFile(osgFileName); + if (osgDB::fileExists(absFileName)) { + optimizeModel = false; + } else { + absFileName = osgDB::findDataFile(fileName); + } if (!osgDB::fileExists(absFileName)) { SG_LOG(SG_IO, SG_ALERT, "Cannot find model file \"" << fileName << "\""); return osgDB::ReaderWriter::ReadResult::FILE_NOT_FOUND; } - - osgDB::Registry* registry = osgDB::Registry::instance(); - osgDB::ReaderWriter::ReadResult res; - res = registry->readNodeImplementation(absFileName, opt); - if (!res.validNode()) - return res; - - if (res.loadedFromCache()) { - SG_LOG(SG_IO, SG_INFO, "Returning cached model \"" + cached + = dynamic_cast(registry->getFromObjectCache(absFileName)); + if (cached) { + SG_LOG(SG_IO, SG_INFO, "Got cached model \"" << absFileName << "\""); } else { SG_LOG(SG_IO, SG_INFO, "Reading model \"" << absFileName << "\""); + res = registry->readNodeImplementation(absFileName, opt); + if (!res.validNode()) + return res; bool needTristrip = true; - if (osgDB::getLowerCaseFileExtension(absFileName) == "ac") { + if (osgDB::getLowerCaseFileExtension(fileName) == "ac") { // we get optimal geometry from the loader. needTristrip = false; osg::Matrix m(1, 0, 0, 0, @@ -245,10 +267,12 @@ public: transform->addChild(res.getNode()); res = osgDB::ReaderWriter::ReadResult(0); - - osgUtil::Optimizer optimizer; - unsigned opts = osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; - optimizer.optimize(root.get(), opts); + + if (optimizeModel) { + osgUtil::Optimizer optimizer; + unsigned opts = osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; + optimizer.optimize(root.get(), opts); + } // strip away unneeded groups if (root->getNumChildren() == 1 && root->getName().empty()) { @@ -267,26 +291,27 @@ public: SGAcMaterialCrippleVisitor matCriple; res.getNode()->accept(matCriple); } - - osgUtil::Optimizer optimizer; - unsigned opts = 0; - // Don't use this one. It will break animation names ... - // opts |= osgUtil::Optimizer::REMOVE_REDUNDANT_NODES; - - // opts |= osgUtil::Optimizer::REMOVE_LOADED_PROXY_NODES; - // opts |= osgUtil::Optimizer::COMBINE_ADJACENT_LODS; - // opts |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE; - opts |= osgUtil::Optimizer::MERGE_GEOMETRY; - // opts |= osgUtil::Optimizer::CHECK_GEOMETRY; - // opts |= osgUtil::Optimizer::SPATIALIZE_GROUPS; - // opts |= osgUtil::Optimizer::COPY_SHARED_NODES; - opts |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; - if (needTristrip) - opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY; - // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY; - // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS; - optimizer.optimize(res.getNode(), opts); + if (optimizeModel) { + osgUtil::Optimizer optimizer; + unsigned opts = 0; + // Don't use this one. It will break animation names ... + // opts |= osgUtil::Optimizer::REMOVE_REDUNDANT_NODES; + + // opts |= osgUtil::Optimizer::REMOVE_LOADED_PROXY_NODES; + // opts |= osgUtil::Optimizer::COMBINE_ADJACENT_LODS; + // opts |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE; + opts |= osgUtil::Optimizer::MERGE_GEOMETRY; + // opts |= osgUtil::Optimizer::CHECK_GEOMETRY; + // opts |= osgUtil::Optimizer::SPATIALIZE_GROUPS; + // opts |= osgUtil::Optimizer::COPY_SHARED_NODES; + opts |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS; + if (needTristrip) + opts |= osgUtil::Optimizer::TRISTRIP_GEOMETRY; + // opts |= osgUtil::Optimizer::TESSELATE_GEOMETRY; + // opts |= osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS; + optimizer.optimize(res.getNode(), opts); + } // Make sure the data variance of sharable objects is set to STATIC ... SGTexDataVarianceVisitor dataVarianceVisitor; res.getNode()->accept(dataVarianceVisitor); @@ -295,15 +320,16 @@ public: SGTexCompressionVisitor texComp; res.getNode()->accept(texComp); + cached = res.getNode(); + registry->addEntryToObjectCache(absFileName, cached); } - // Add an extra reference to the model stored in the database. // That it to avoid expiring the object from the cache even if it is still // in use. Note that the object cache will think that a model is unused // if the reference count is 1. If we clone all structural nodes here // we need that extra reference to the original object SGDatabaseReference* databaseReference; - databaseReference = new SGDatabaseReference(res.getNode()); + databaseReference = new SGDatabaseReference(cached); osg::CopyOp::CopyFlags flags = osg::CopyOp::DEEP_COPY_ALL; flags &= ~osg::CopyOp::DEEP_COPY_TEXTURES; flags &= ~osg::CopyOp::DEEP_COPY_IMAGES; @@ -312,7 +338,7 @@ public: // This will safe display lists ... flags &= ~osg::CopyOp::DEEP_COPY_DRAWABLES; flags &= ~osg::CopyOp::DEEP_COPY_SHAPES; - res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(res.getNode())); + res = osgDB::ReaderWriter::ReadResult(osg::CopyOp(flags)(cached)); res.getNode()->addObserver(databaseReference); // Update liveries @@ -337,7 +363,11 @@ public: osgDB::Registry* registry = osgDB::Registry::instance(); osgDB::ReaderWriter::Options* options = new osgDB::ReaderWriter::Options; - options->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL); + // We manage node caching ourselves + int cacheOptions = osgDB::ReaderWriter::Options::CACHE_ALL + & ~osgDB::ReaderWriter::Options::CACHE_NODES; + options-> + setObjectCacheHint((osgDB::ReaderWriter::Options::CacheHintOptions)cacheOptions); registry->setOptions(options); registry->getOrCreateSharedStateManager()->setShareMode(osgDB::SharedStateManager::SHARE_TEXTURES); registry->setReadFileCallback(new SGReadFileCallback); @@ -352,6 +382,7 @@ SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int) osg::Image* image = osgDB::readImageFile(path); osg::ref_ptr texture = new osg::Texture2D; texture->setImage(image); + texture->setDataVariance(osg::Object::STATIC); if (wrapu) texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); else @@ -381,7 +412,7 @@ SGLoadTexture2D(const std::string& path, bool wrapu, bool wrapv, int) // OSGFIXME: don't forget that mutex here osgDB::Registry* registry = osgDB::Registry::instance(); - registry->getOrCreateSharedStateManager()->share(tmpNode.get(), 0); + registry->getSharedStateManager()->share(tmpNode.get(), 0); // should be the same, but be paranoid ... stateSet = tmpNode->getStateSet();