]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/ModelRegistry.cxx
Do not modify danymically generated textures.
[simgear.git] / simgear / scene / model / ModelRegistry.cxx
index 315f079ea481b1eca6f288375d92fe72e4bec39c..861aee432949ac72fc3e28293ff6ca600e351ff0 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>
@@ -50,6 +55,8 @@
 #include <simgear/props/props_io.hxx>
 #include <simgear/props/condition.hxx>
 
+#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<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:
@@ -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,20 +306,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);
   }
 };
 
@@ -387,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
@@ -413,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;
 }
 
@@ -425,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(""))
 {
@@ -449,15 +511,19 @@ ModelRegistry::readNode(const string& fileName,
                         const ReaderWriter::Options* opt)
 {
     ScopedLock<ReentrantMutex> lock(readerMutex);
+
     // XXX Workaround for OSG plugin bug.
     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 {
@@ -528,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<ACProcessPolicy, DefaultCachePolicy,
                               ACOptimizePolicy, DefaultCopyPolicy,
-                              OSGSubstitutePolicy> ACCallback;
+                              OSGSubstitutePolicy, BuildLeafBVHPolicy>
+ACCallback;
 
 namespace
 {