Use osg's builtin mechanisms to traverse only in range nodes with the
update visitor. Modified Files: simgear/scene/util/SGUpdateVisitor.hxx simgear/scene/tgdb/TileEntry.cxx simgear/scene/model/placementtrans.cxx
This commit is contained in:
@@ -36,37 +36,10 @@
|
||||
|
||||
#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),
|
||||
_rotation(SGQuatd::unit())
|
||||
{
|
||||
setUpdateCallback(new UpdateCallback);
|
||||
}
|
||||
|
||||
SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
#include <simgear/scene/tgdb/obj.hxx>
|
||||
#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
|
||||
#include <simgear/scene/model/placementtrans.hxx>
|
||||
#include <simgear/scene/util/SGUpdateVisitor.hxx>
|
||||
|
||||
#include "ReaderWriterSTG.hxx"
|
||||
#include "TileEntry.hxx"
|
||||
@@ -71,24 +70,6 @@ osgDB::RegisterReaderWriterProxy<ReaderWriterSTG> g_readerWriterSTGProxy;
|
||||
ModelRegistryCallbackProxy<LoadOnlyCallback> g_stgCallbackProxy("stg");
|
||||
}
|
||||
|
||||
// FIXME: investigate what huge update flood is clamped away here ...
|
||||
class FGTileUpdateCallback : public osg::NodeCallback {
|
||||
public:
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
assert(dynamic_cast<SGUpdateVisitor*>(nv));
|
||||
SGUpdateVisitor* updateVisitor = static_cast<SGUpdateVisitor*>(nv);
|
||||
|
||||
osg::Vec3 center = node->getBound().center();
|
||||
double distance = dist(updateVisitor->getGlobalEyePos(),
|
||||
SGVec3d(center[0], center[1], center[2]));
|
||||
if (updateVisitor->getVisibility() + node->getBound().radius() < distance)
|
||||
return;
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
// Update the timestamp on a tile whenever it is in view.
|
||||
@@ -143,7 +124,6 @@ TileEntry::TileEntry ( const SGBucket& b )
|
||||
is_inner_ring(false),
|
||||
tileFileName(b.gen_index_str())
|
||||
{
|
||||
_node->setUpdateCallback(new FGTileUpdateCallback);
|
||||
_node->setCullCallback(new TileCullCallback);
|
||||
tileFileName += ".stg";
|
||||
_node->setName(tileFileName);
|
||||
|
||||
@@ -32,16 +32,14 @@ public:
|
||||
SGUpdateVisitor() :
|
||||
mVisibility(-1)
|
||||
{
|
||||
// Need to traverse all children, else some LOD nodes do not get updated
|
||||
// Note that the broad number of updates is not done due to
|
||||
// the update callback in the global position node.
|
||||
setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN);
|
||||
setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
|
||||
setVisibility(10000);
|
||||
}
|
||||
void setViewData(const SGVec3d& globalEyePos,
|
||||
const SGQuatd& globalViewOrientation)
|
||||
{
|
||||
mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
|
||||
_currentEyePos = globalEyePos.osg();
|
||||
mGlobalEyePos = globalEyePos;
|
||||
mGlobalViewOr = globalViewOrientation;
|
||||
mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
|
||||
@@ -134,8 +132,34 @@ public:
|
||||
|
||||
double getSunAngleDeg() const
|
||||
{ return mSunAngleDeg; }
|
||||
|
||||
// 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)
|
||||
{
|
||||
osg::Matrix matrix = _matrix;
|
||||
transform.computeLocalToWorldMatrix(_matrix, this);
|
||||
osgUtil::UpdateVisitor::apply(transform);
|
||||
_matrix = matrix;
|
||||
}
|
||||
virtual void apply(osg::Camera& camera)
|
||||
{
|
||||
if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
|
||||
osg::Vec3d currentEyePos = _currentEyePos;
|
||||
_currentEyePos = osg::Vec3d(0, 0, 0);
|
||||
apply(static_cast<osg::Transform&>(camera));
|
||||
_currentEyePos = currentEyePos;
|
||||
} else {
|
||||
apply(static_cast<osg::Transform&>(camera));
|
||||
}
|
||||
}
|
||||
virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
|
||||
{ return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
|
||||
|
||||
private:
|
||||
osg::Matrix _matrix;
|
||||
osg::Vec3d _currentEyePos;
|
||||
|
||||
SGGeod mGlobalGeodEyePos;
|
||||
SGVec3d mGlobalEyePos;
|
||||
SGQuatd mGlobalViewOr;
|
||||
|
||||
Reference in New Issue
Block a user