]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/ModelRegistry.cxx
Add writeLocalData functions for internal scenegraph classes
[simgear.git] / simgear / scene / model / ModelRegistry.cxx
index 7c2afff648f3e10ab7aabf85770f3d22a02cf367..3b5b545c4101b48cd93129b34a716c9bef01cf0d 100644 (file)
 // 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 <simgear_config.h>
+#endif
+
 #include "ModelRegistry.hxx"
 
 #include <algorithm>
@@ -24,7 +29,6 @@
 
 #include <OpenThreads/ScopedLock>
 
-#include <osg/observer_ptr>
 #include <osg/ref_ptr>
 #include <osg/Group>
 #include <osg/NodeCallback>
@@ -221,6 +225,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<SGSceneUserData> 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:
@@ -231,9 +257,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;
@@ -258,6 +288,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);
   }
 
@@ -265,20 +305,8 @@ public:
   {
     if (!stateSet)
       return;
-    SGTextureStateAttributeVisitor::apply(stateSet);
     stateSet->setDataVariance(Object::STATIC);
-  }
-};
-
-class SGAcMaterialCrippleVisitor : public SGStateAttributeVisitor {
-public:
-  virtual void apply(StateSet::RefAttributePair& refAttr)
-  {
-    Material* material;
-    material = dynamic_cast<Material*>(refAttr.first.get());
-    if (!material)
-      return;
-    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
+    SGTextureStateAttributeVisitor::apply(stateSet);
   }
 };
 
@@ -319,10 +347,10 @@ ModelRegistry::readImage(const string& fileName,
         }
         
         if (res.loadedFromCache())
-            SG_LOG(SG_IO, SG_INFO, "Returning cached image \""
+            SG_LOG(SG_IO, SG_BULK, "Returning cached image \""
                    << res.getImage()->getFileName() << "\"");
         else
-            SG_LOG(SG_IO, SG_INFO, "Reading image \""
+            SG_LOG(SG_IO, SG_BULK, "Reading image \""
                    << res.getImage()->getFileName() << "\"");
 
         return res;
@@ -337,10 +365,10 @@ osg::Node* DefaultCachePolicy::find(const string& fileName,
     osg::Node* cached
         = dynamic_cast<Node*>(registry->getFromObjectCache(fileName));
     if (cached)
-        SG_LOG(SG_IO, SG_INFO, "Got cached model \""
+        SG_LOG(SG_IO, SG_BULK, "Got cached model \""
                << fileName << "\"");
     else
-        SG_LOG(SG_IO, SG_INFO, "Reading model \""
+        SG_LOG(SG_IO, SG_BULK, "Reading model \""
                << fileName << "\"");
     return cached;
 }
@@ -389,10 +417,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
@@ -415,6 +443,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;
 }
 
@@ -427,9 +460,34 @@ string OSGSubstitutePolicy::substitute(const string& name,
     return absFileName;
 }
 
+
+void
+BuildLeafBVHPolicy::buildBVH(const std::string& fileName, osg::Node* node)
+{
+    SG_LOG(SG_IO, SG_BULK, "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_BULK, "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_BULK, "Omitting boundingvolume tree for \""
+           << fileName << "\".");
+}
+
 ModelRegistry::ModelRegistry() :
-    _defaultCallback(new DefaultCallback("")),
-    _nestingLevel(0)
+    _defaultCallback(new DefaultCallback(""))
 {
 }
 
@@ -452,10 +510,9 @@ ModelRegistry::readNode(const string& fileName,
                         const ReaderWriter::Options* opt)
 {
     ScopedLock<ReentrantMutex> lock(readerMutex);
-    ++_nestingLevel;
 
     // XXX Workaround for OSG plugin bug.
-    Registry* registry = Registry::instance();
+//    Registry* registry = Registry::instance();
     ReaderWriter::ReadResult res;
     CallbackMap::iterator iter
         = nodeCallbackMap.find(getFileExtension(fileName));
@@ -465,15 +522,6 @@ ModelRegistry::readNode(const string& fileName,
     else
         result = _defaultCallback->readNode(fileName, opt);
 
-    if (0 == --_nestingLevel) {
-        SG_LOG(SG_IO, SG_INFO, "Building boundingvolume tree for \""
-               << fileName << "\".");
-        BoundingVolumeBuildVisitor bvBuilder;
-        result.getNode()->accept(bvBuilder);
-    } else {
-        SG_LOG(SG_IO, SG_INFO, "Defering boundingvolume tree built for \""
-               << fileName << "\" to parent.");
-    }
     return result;
 }
 
@@ -545,23 +593,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<ACProcessPolicy, DefaultCachePolicy,
                               ACOptimizePolicy, DefaultCopyPolicy,
-                              OSGSubstitutePolicy> ACCallback;
+                              OSGSubstitutePolicy, BuildLeafBVHPolicy>
+ACCallback;
 
 namespace
 {