]> 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 963244e99dd6c2699daa5a9a8eefb33b7d1064a9..a59c24d4afdcfc2555713de894eaceebd44ef7bf 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
 
-#ifndef __cplusplus                                                          
+#ifndef __cplusplus
 # error This library requires C++
-#endif                                   
+#endif
+
+#include <osgDB/Registry>
+#include <osgDB/Input>
+#include <osgDB/Output>
 
 #include <simgear/compiler.h>
 #include <simgear/constants.h>
 
-#include <plib/sg.h>
-#include <plib/ssg.h>
-
 #include "placementtrans.hxx"
 
-ssgPlacementTransform::ssgPlacementTransform(void)
+#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),
+  _rotation(1, 0, 0, 0,
+            0, 1, 0, 0,
+            0, 0, 1, 0,
+            0, 0, 0, 1)
 {
+  setUpdateCallback(new UpdateCallback);
 }
 
-ssgPlacementTransform::~ssgPlacementTransform(void)
+SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
+                                           const osg::CopyOp& copyop):
+  osg::Transform(trans, copyop),
+  _placement_offset(trans._placement_offset),
+  _rotation(trans._rotation)
 {
+  
 }
 
-ssgBase *ssgPlacementTransform::clone(int clone_flags)
+SGPlacementTransform::~SGPlacementTransform(void)
 {
-  ssgPlacementTransform *b = new ssgPlacementTransform;
-  b->copy_from(this, clone_flags);
-  return b;
 }
 
-void
-ssgPlacementTransform::copy_from(ssgPlacementTransform *src, int clone_flags)
+bool
+SGPlacementTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
+                                                osg::NodeVisitor*) const
 {
-  ssgBaseTransform::copy_from(src, clone_flags);
-  sgdCopyVec3(_placement_offset, src->_placement_offset);
-  sgdCopyVec3(_scenery_center,  src->_scenery_center);
+  osg::Matrix t;
+  for (int i = 0; i < 3; ++i) {
+    for (int j = 0; j < 3; ++j) {
+      t(j, i) = _rotation(i, j);
+    }
+    t(3, i) = _placement_offset(i);
+  }
+  
+  if (_referenceFrame == RELATIVE_RF)
+    matrix.preMult(t);
+  else
+    matrix = t;
+  return true;
 }
 
-void ssgPlacementTransform::setTransform(sgdVec3 off)
+bool
+SGPlacementTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
+                                                osg::NodeVisitor*) const
 {
-  sgdCopyVec3(_placement_offset, off);
-  sgdVec3 tmp;
-  sgdSubVec3(tmp, _placement_offset, _scenery_center);
-  sgMat4 tmat;
-  sgZeroVec4(tmat[0]);
-  tmat[0][0] = 1;
-  sgZeroVec4(tmat[1]);
-  tmat[1][1] = 1;
-  sgZeroVec4(tmat[2]);
-  tmat[2][2] = 1;
-  sgSetVec3(tmat[3], tmp);
-  tmat[3][3] = 1;
-  ssgTransform::setTransform(tmat);
+  osg::Matrix t;
+  for (int i = 0; i < 3; ++i) {
+    for (int j = 0; j < 3; ++j) {
+      t(j, i) = _rotation(i, j);
+    }
+    t(3, i) = _placement_offset(i);
+  }
+  t = osg::Matrix::inverse(t);
+
+  if (_referenceFrame == RELATIVE_RF)
+    matrix.postMult(t);
+  else
+    matrix = t;
+  return true;
 }
 
-void ssgPlacementTransform::setTransform(sgdVec3 off, sgMat4 rot)
+// Functions to read / write SGPlacementTrans from / to a .osg file,
+// mostly for debugging purposes.
+
+namespace {
+
+bool PlacementTrans_readLocalData(osg::Object& obj, osgDB::Input& fr)
 {
-  sgdCopyVec3(_placement_offset, off);
-  sgdVec3 tmp;
-  sgdSubVec3(tmp, _placement_offset, _scenery_center);
-  sgMat4 tmat;
-  sgCopyVec4(tmat[0], rot[0]);
-  sgCopyVec4(tmat[1], rot[1]);
-  sgCopyVec4(tmat[2], rot[2]);
-  sgSetVec3(tmat[3], tmp);
-  tmat[3][3] = 1;
-  ssgTransform::setTransform(tmat);
+    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;
 }
 
-void ssgPlacementTransform::setSceneryCenter(sgdVec3 xyz)
+bool PlacementTrans_writeLocalData(const osg::Object& obj, osgDB::Output& fw)
 {
-  sgdCopyVec3(_scenery_center, xyz);
-  sgdVec3 tmp;
-  sgdSubVec3(tmp, _placement_offset, _scenery_center);
-  sgMat4 tmat;
-  getTransform(tmat);
-  sgSetVec3(tmat[3], tmp);
-  ssgTransform::setTransform(tmat);
+    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
+);