]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/util/SGUpdateVisitor.hxx
Work around apparent OSG 3.2.0 normal binding bug.
[simgear.git] / simgear / scene / util / SGUpdateVisitor.hxx
index 8f23ed7b221f555df4483e9f3c46b14e465526f8..8f16a270353d21478b08c77dab3d9ae61163120a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c++-*-
  *
- * Copyright (C) 2006 Mathias Froehlich 
+ * Copyright (C) 2006-2009 Mathias Froehlich 
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 #define SG_SCENE_UPDATEVISITOR_HXX
 
 #include <osg/NodeVisitor>
+#include <osg/PagedLOD>
 #include <osgUtil/UpdateVisitor>
 
-#include "simgear/math/SGMath.hxx"
+#include "OsgMath.hxx"
 
 class SGUpdateVisitor : public osgUtil::UpdateVisitor {
 public:
@@ -39,7 +40,7 @@ public:
                    const SGQuatd& globalViewOrientation)
   {
     mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
-    _currentEyePos = globalEyePos.osg();
+    _currentEyePos = toOsg(globalEyePos);
     mGlobalEyePos = globalEyePos;
     mGlobalViewOr = globalViewOrientation;
     mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
@@ -132,11 +133,30 @@ public:
 
   double getSunAngleDeg() const
   { return mSunAngleDeg; }
-    
+
+  virtual void apply(osg::Node& node)
+  {
+    if (!needToEnterNode(node))
+      return;
+    osgUtil::UpdateVisitor::apply(node);
+  }
+  // To avoid expiry of LOD nodes that are in range and that are updated,
+  // mark them with the last traversal number, even if they are culled away
+  // by the cull frustum.
+  virtual void apply(osg::PagedLOD& pagedLOD)
+  {
+    if (!needToEnterNode(pagedLOD))
+      return;
+    if (getFrameStamp())
+      pagedLOD.setFrameNumberOfLastTraversal(getFrameStamp()->getFrameNumber());
+    osgUtil::UpdateVisitor::apply(pagedLOD);
+  }
   // To be able to traverse correctly only the active children, we need to
   // track the model view matrices during update.
   virtual void apply(osg::Transform& transform)
   {
+    if (!needToEnterNode(transform))
+      return;
     osg::Matrix matrix = _matrix;
     transform.computeLocalToWorldMatrix(_matrix, this);
     osgUtil::UpdateVisitor::apply(transform);
@@ -144,6 +164,8 @@ public:
   }
   virtual void apply(osg::Camera& camera)
   {
+    if (!needToEnterNode(camera))
+      return;
     if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
       osg::Vec3d currentEyePos = _currentEyePos;
       _currentEyePos = osg::Vec3d(0, 0, 0);
@@ -153,9 +175,27 @@ public:
       apply(static_cast<osg::Transform&>(camera));
     }
   }
+  // Function to make the LOD traversal only enter that children that
+  // are visible on the screen.
   virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
   { return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
 
+protected:
+  bool needToEnterNode(const osg::Node& node) const
+  {
+    if (!node.isCullingActive())
+      return true;
+    return isSphereInRange(node.getBound());
+  }
+  bool isSphereInRange(const osg::BoundingSphere& sphere) const
+  {
+    if (!sphere.valid())
+      return false;
+    float maxDist = mVisibility + sphere._radius;
+    osg::Vec3d center = _matrix.preMult(osg::Vec3d(sphere._center));
+    return (_currentEyePos - center).length2() <= maxDist*maxDist;
+  }
+    
 private:
   osg::Matrix _matrix;
   osg::Vec3d _currentEyePos;