]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/placementtrans.cxx
Improove bounding volume building in the scenery loading process.
[simgear.git] / simgear / scene / model / placementtrans.cxx
index 34a7f21567b4d8c359f2f5b193254e0f6fb9933b..a59c24d4afdcfc2555713de894eaceebd44ef7bf 100644 (file)
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
 #ifndef __cplusplus
 # error This library requires C++
 #endif
 
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/Output>
+
 #include <simgear/compiler.h>
 #include <simgear/constants.h>
 
 #include "placementtrans.hxx"
 
+#include <simgear/scene/util/SGUpdateVisitor.hxx>
+
+class SGPlacementTransform::UpdateCallback : public osg::NodeCallback {
+public:
+  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+  {
+    // short circuit updates if the model we place with that branch
+    // out of sight.
+    // Note that the transform is still correct.
+    SGUpdateVisitor* updateVisitor = dynamic_cast<SGUpdateVisitor*>(nv);
+    if (updateVisitor) {
+      SGPlacementTransform* placementTransform;
+      placementTransform = static_cast<SGPlacementTransform*>(node);
+      double dist2 = distSqr(updateVisitor->getGlobalEyePos(),
+                             placementTransform->getGlobalPos());
+      if (updateVisitor->getSqrVisibility() < dist2)
+        return;
+    }
+    // note, callback is responsible for scenegraph traversal so
+    // should always include call traverse(node,nv) to ensure 
+    // that the rest of cullbacks and the scene graph are traversed.
+    traverse(node, nv);
+  }
+};
+
+
 SGPlacementTransform::SGPlacementTransform(void) :
   _placement_offset(0, 0, 0),
-  _scenery_center(0, 0, 0),
   _rotation(1, 0, 0, 0,
             0, 1, 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1)
 {
+  setUpdateCallback(new UpdateCallback);
+}
+
+SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
+                                           const osg::CopyOp& copyop):
+  osg::Transform(trans, copyop),
+  _placement_offset(trans._placement_offset),
+  _rotation(trans._rotation)
+{
+  
 }
 
 SGPlacementTransform::~SGPlacementTransform(void)
@@ -52,7 +94,7 @@ SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
     for (int j = 0; j < 3; ++j) {
       t(j, i) = _rotation(i, j);
     }
-    t(3, i) = _placement_offset(i) - _scenery_center(i);
+    t(3, i) = _placement_offset(i);
   }
   
   if (_referenceFrame == RELATIVE_RF)
@@ -71,7 +113,7 @@ SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
     for (int j = 0; j < 3; ++j) {
       t(j, i) = _rotation(i, j);
     }
-    t(3, i) = _placement_offset(i) - _scenery_center(i);
+    t(3, i) = _placement_offset(i);
   }
   t = osg::Matrix::inverse(t);
 
@@ -81,3 +123,82 @@ SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
     matrix = t;
   return true;
 }
+
+// Functions to read / write SGPlacementTrans from / to a .osg file,
+// mostly for debugging purposes.
+
+namespace {
+
+bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
+{
+    SGPlacementTransform& trans = static_cast<SGPlacementTransform&>(obj);
+    SGMatrixd rotation(1, 0, 0, 0,
+                       0, 1, 0, 0,
+                       0, 0, 1, 0,
+                       0, 0, 0, 1);
+    SGVec3d placementOffset(0, 0, 0);
+    
+    if (fr[0].matchWord("rotation") && fr[1].isOpenBracket()) {
+        fr += 2;
+        for (int i = 0; i < 3; i++) {
+            SGVec3d scratch;
+            if (!fr.readSequence(scratch.osg()))
+                return false;
+            fr += 3;
+            for (int j = 0; j < 3; j++)
+                rotation(j, i) = scratch[j];
+        }
+        if (fr[0].isCloseBracket())
+            ++fr;
+        else
+            return false;
+    }
+    if (fr[0].matchWord("placement")) {
+        ++fr;
+        if (fr.readSequence(placementOffset.osg()))
+            fr += 3;
+        else
+            return false;
+    }
+    trans.setTransform(placementOffset, rotation);
+    return true;
+}
+
+bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
+{
+    const SGPlacementTransform& trans
+        = static_cast<const SGPlacementTransform&>(obj);
+    const SGMatrixd& rotation = trans.getRotation();
+    const SGVec3d& placement = trans.getGlobalPos();
+    
+    fw.indent() << "rotation {" << std::endl;
+    fw.moveIn();
+    for (int i = 0; i < 3; i++) {
+        fw.indent();
+        for (int j = 0; j < 3; j++) {
+            fw << rotation(j, i) << " ";
+        }
+        fw << std::endl;
+    }
+    fw.moveOut();
+    fw.indent() << "}" << std::endl;
+    int prec = fw.precision();
+    fw.precision(15);
+    fw.indent() << "placement ";
+    for (int i = 0; i < 3; i++) {
+        fw << placement(i) << " ";
+    }
+    fw << std::endl;
+    fw.precision(prec);
+    return true;
+}
+}
+
+osgDB::RegisterDotOsgWrapperProxy g_SGPlacementTransProxy
+(
+    new SGPlacementTransform,
+    "SGPlacementTransform",
+    "Object Node Transform SGPlacementTransform Group",
+    &PlacementTrans_readLocalData,
+    &PlacementTrans_writeLocalData
+);