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 "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) :
|
SGPlacementTransform::SGPlacementTransform(void) :
|
||||||
_placement_offset(0, 0, 0),
|
_placement_offset(0, 0, 0),
|
||||||
_rotation(SGQuatd::unit())
|
_rotation(SGQuatd::unit())
|
||||||
{
|
{
|
||||||
setUpdateCallback(new UpdateCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
|
SGPlacementTransform::SGPlacementTransform(const SGPlacementTransform& trans,
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
#include <simgear/scene/tgdb/obj.hxx>
|
#include <simgear/scene/tgdb/obj.hxx>
|
||||||
#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
|
#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
|
||||||
#include <simgear/scene/model/placementtrans.hxx>
|
#include <simgear/scene/model/placementtrans.hxx>
|
||||||
#include <simgear/scene/util/SGUpdateVisitor.hxx>
|
|
||||||
|
|
||||||
#include "ReaderWriterSTG.hxx"
|
#include "ReaderWriterSTG.hxx"
|
||||||
#include "TileEntry.hxx"
|
#include "TileEntry.hxx"
|
||||||
@@ -71,24 +70,6 @@ osgDB::RegisterReaderWriterProxy<ReaderWriterSTG> g_readerWriterSTGProxy;
|
|||||||
ModelRegistryCallbackProxy<LoadOnlyCallback> g_stgCallbackProxy("stg");
|
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
|
namespace
|
||||||
{
|
{
|
||||||
// Update the timestamp on a tile whenever it is in view.
|
// Update the timestamp on a tile whenever it is in view.
|
||||||
@@ -143,7 +124,6 @@ TileEntry::TileEntry ( const SGBucket& b )
|
|||||||
is_inner_ring(false),
|
is_inner_ring(false),
|
||||||
tileFileName(b.gen_index_str())
|
tileFileName(b.gen_index_str())
|
||||||
{
|
{
|
||||||
_node->setUpdateCallback(new FGTileUpdateCallback);
|
|
||||||
_node->setCullCallback(new TileCullCallback);
|
_node->setCullCallback(new TileCullCallback);
|
||||||
tileFileName += ".stg";
|
tileFileName += ".stg";
|
||||||
_node->setName(tileFileName);
|
_node->setName(tileFileName);
|
||||||
|
|||||||
@@ -32,16 +32,14 @@ public:
|
|||||||
SGUpdateVisitor() :
|
SGUpdateVisitor() :
|
||||||
mVisibility(-1)
|
mVisibility(-1)
|
||||||
{
|
{
|
||||||
// Need to traverse all children, else some LOD nodes do not get updated
|
setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
|
||||||
// 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);
|
|
||||||
setVisibility(10000);
|
setVisibility(10000);
|
||||||
}
|
}
|
||||||
void setViewData(const SGVec3d& globalEyePos,
|
void setViewData(const SGVec3d& globalEyePos,
|
||||||
const SGQuatd& globalViewOrientation)
|
const SGQuatd& globalViewOrientation)
|
||||||
{
|
{
|
||||||
mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
|
mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
|
||||||
|
_currentEyePos = globalEyePos.osg();
|
||||||
mGlobalEyePos = globalEyePos;
|
mGlobalEyePos = globalEyePos;
|
||||||
mGlobalViewOr = globalViewOrientation;
|
mGlobalViewOr = globalViewOrientation;
|
||||||
mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
|
mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
|
||||||
@@ -135,7 +133,33 @@ public:
|
|||||||
double getSunAngleDeg() const
|
double getSunAngleDeg() const
|
||||||
{ return mSunAngleDeg; }
|
{ 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:
|
private:
|
||||||
|
osg::Matrix _matrix;
|
||||||
|
osg::Vec3d _currentEyePos;
|
||||||
|
|
||||||
SGGeod mGlobalGeodEyePos;
|
SGGeod mGlobalGeodEyePos;
|
||||||
SGVec3d mGlobalEyePos;
|
SGVec3d mGlobalEyePos;
|
||||||
SGQuatd mGlobalViewOr;
|
SGQuatd mGlobalViewOr;
|
||||||
|
|||||||
Reference in New Issue
Block a user