X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmodel%2FModelRegistry.cxx;h=861aee432949ac72fc3e28293ff6ca600e351ff0;hb=daa0fbdc6ba4a2c0548d71737953aa0901b5d71d;hp=b19c853c12389940121086aaf921bf6783b573e8;hpb=ac57eab8ac64401280c71fec26cdbfb5efed1ae7;p=simgear.git diff --git a/simgear/scene/model/ModelRegistry.cxx b/simgear/scene/model/ModelRegistry.cxx index b19c853c..861aee43 100644 --- a/simgear/scene/model/ModelRegistry.cxx +++ b/simgear/scene/model/ModelRegistry.cxx @@ -16,6 +16,11 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +# include +#endif + #include "ModelRegistry.hxx" #include @@ -50,6 +55,8 @@ #include #include +#include "BoundingVolumeBuildVisitor.hxx" + using namespace std; using namespace osg; using namespace osgUtil; @@ -219,6 +226,28 @@ private: FilePathList _pathList; }; +// Create new userdata structs in a copied model. +// The BVH trees are shared with the original model, but the velocity fields +// should usually be distinct fields for distinct models. +class UserDataCopyVisitor : public osg::NodeVisitor { +public: + UserDataCopyVisitor() : + osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR, + osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) + { + } + virtual void apply(osg::Node& node) + { + osg::ref_ptr userData; + userData = SGSceneUserData::getSceneUserData(&node); + if (userData.valid()) { + SGSceneUserData* newUserData = new SGSceneUserData(*userData); + newUserData->setVelocity(0); + node.setUserData(newUserData); + } + node.traverse(*this); + } +}; class SGTexCompressionVisitor : public SGTextureStateAttributeVisitor { public: @@ -229,9 +258,13 @@ public: if (!texture) return; - // Hmm, true?? - texture->setDataVariance(osg::Object::STATIC); + // Do not touch dynamically generated textures. + if (texture->getReadPBuffer()) + return; + if (texture->getDataVariance() == osg::Object::DYNAMIC) + return; + // If no image attached, we assume this one is dynamically generated Image* image = texture->getImage(0); if (!image) return; @@ -256,6 +289,16 @@ public: if (!texture) return; + // Cannot be static if this is a render to texture thing + if (texture->getReadPBuffer()) + return; + if (texture->getDataVariance() == osg::Object::DYNAMIC) + return; + // If no image attached, we assume this one is dynamically generated + Image* image = texture->getImage(0); + if (!image) + return; + texture->setDataVariance(Object::STATIC); } @@ -263,56 +306,11 @@ public: { if (!stateSet) return; - SGTextureStateAttributeVisitor::apply(stateSet); stateSet->setDataVariance(Object::STATIC); + SGTextureStateAttributeVisitor::apply(stateSet); } }; -class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor { -public: - virtual void apply(StateSet::RefAttributePair& refAttr) - { - Material* material; - material = dynamic_cast(refAttr.first.get()); - if (!material) - return; - material->setColorMode(Material::AMBIENT_AND_DIFFUSE); - } -}; - -// Work around an OSG bug - the file loaders don't use the file path -// in options while the file is being loaded. - -struct OptionsPusher { - FilePathList localPathList; - bool validOptions; - OptionsPusher(const ReaderWriter::Options* options): - validOptions(false) - { - if (!options) - return; - Registry* registry = Registry::instance(); - localPathList = registry->getDataFilePathList(); - const FilePathList& regPathList = registry->getDataFilePathList(); - const FilePathList& optionsPathList = options->getDatabasePathList(); - for (FilePathList::const_iterator iter = optionsPathList.begin(); - iter != optionsPathList.end(); - ++iter) { - if (find(regPathList.begin(), regPathList.end(), *iter) - == regPathList.end()) - localPathList.push_back(*iter); - } - // Save the current Registry path list and install the augmented one. - localPathList.swap(registry->getDataFilePathList()); - validOptions = true; - } - ~OptionsPusher() - { - // Restore the old path list - if (validOptions) - localPathList.swap(Registry::instance()->getDataFilePathList()); - } -}; } // namespace Node* DefaultProcessPolicy::process(Node* node, const string& filename, @@ -332,10 +330,9 @@ ModelRegistry::readImage(const string& fileName, = imageCallbackMap.find(getFileExtension(fileName)); // XXX Workaround for OSG plugin bug { - OptionsPusher pusher(opt); if (iter != imageCallbackMap.end() && iter->second.valid()) return iter->second->readImage(fileName, opt); - string absFileName = findDataFile(fileName); + string absFileName = findDataFile(fileName, opt); if (!fileExists(absFileName)) { SG_LOG(SG_IO, SG_ALERT, "Cannot find image file \"" << fileName << "\""); @@ -421,10 +418,10 @@ osg::Node* OptimizeModelPolicy::optimize(osg::Node* node, } osg::Node* DefaultCopyPolicy::copy(osg::Node* model, const string& fileName, - const osgDB::ReaderWriter::Options* opt) + const osgDB::ReaderWriter::Options* opt) { // 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 + // That is 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 @@ -447,6 +444,11 @@ osg::Node* DefaultCopyPolicy::copy(osg::Node* model, const string& fileName, TextureUpdateVisitor liveryUpdate(opt->getDatabasePathList()); res->accept(liveryUpdate); + // Copy the userdata fields, still sharing the boundingvolumes, + // but introducing new data for velocities. + UserDataCopyVisitor userDataCopyVisitor; + res->accept(userDataCopyVisitor); + return res; } @@ -459,6 +461,32 @@ string OSGSubstitutePolicy::substitute(const string& name, return absFileName; } + +void +BuildLeafBVHPolicy::buildBVH(const std::string& fileName, osg::Node* node) +{ + SG_LOG(SG_IO, SG_INFO, "Building leaf attached boundingvolume tree for \"" + << fileName << "\"."); + BoundingVolumeBuildVisitor bvBuilder(true); + node->accept(bvBuilder); +} + +void +BuildGroupBVHPolicy::buildBVH(const std::string& fileName, osg::Node* node) +{ + SG_LOG(SG_IO, SG_INFO, "Building group attached boundingvolume tree for \"" + << fileName << "\"."); + BoundingVolumeBuildVisitor bvBuilder(false); + node->accept(bvBuilder); +} + +void +NoBuildBVHPolicy::buildBVH(const std::string& fileName, osg::Node*) +{ + SG_LOG(SG_IO, SG_INFO, "Omitting boundingvolume tree for \"" + << fileName << "\"."); +} + ModelRegistry::ModelRegistry() : _defaultCallback(new DefaultCallback("")) { @@ -483,16 +511,19 @@ ModelRegistry::readNode(const string& fileName, const ReaderWriter::Options* opt) { ScopedLock lock(readerMutex); + // XXX Workaround for OSG plugin bug. - OptionsPusher pusher(opt); Registry* registry = Registry::instance(); ReaderWriter::ReadResult res; - Node* cached = 0; CallbackMap::iterator iter = nodeCallbackMap.find(getFileExtension(fileName)); + ReaderWriter::ReadResult result; if (iter != nodeCallbackMap.end() && iter->second.valid()) - return iter->second->readNode(fileName, opt); - return _defaultCallback->readNode(fileName, opt); + result = iter->second->readNode(fileName, opt); + else + result = _defaultCallback->readNode(fileName, opt); + + return result; } class SGReadCallbackInstaller { @@ -529,13 +560,14 @@ struct ACOptimizePolicy : public OptimizeModelPolicy { { ref_ptr optimized = OptimizeModelPolicy::optimize(node, fileName, opt); + Group* group = dynamic_cast(optimized.get()); MatrixTransform* transform = dynamic_cast(optimized.get()); - if (transform && transform->getMatrix().isIdentity() - && transform->getName().empty() - && transform->getNumChildren() == 1) { - optimized = static_cast(transform->getChild(0)); - Group* group = dynamic_cast(optimized.get()); + if (((transform && transform->getMatrix().isIdentity()) || group) + && group->getName().empty() + && group->getNumChildren() == 1) { + optimized = static_cast(group->getChild(0)); + group = dynamic_cast(optimized.get()); if (group && group->getName().empty() && group->getNumChildren() == 1) optimized = static_cast(group->getChild(0)); @@ -562,23 +594,15 @@ struct ACProcessPolicy { transform->setDataVariance(Object::STATIC); transform->setMatrix(m); transform->addChild(node); - // Ok, this step is questionable. - // It is there to have the same visual appearance of ac objects for the - // first cut. Osg's ac3d loader will correctly set materials from the - // ac file. But the old plib loader used GL_AMBIENT_AND_DIFFUSE for the - // materials that in effect igored the ambient part specified in the - // file. We emulate that for the first cut here by changing all - // ac models here. But in the long term we should use the - // unchanged model and fix the input files instead ... - SGAcMaterialCrippleVisitor matCriple; - root->accept(matCriple); + return root; } }; typedef ModelRegistryCallback ACCallback; + OSGSubstitutePolicy, BuildLeafBVHPolicy> +ACCallback; namespace {