From Farshid Lashkari, "As discussed, I've added the ability to handle Drawable objects within the NodeVisitor class. Here is an overview of the changes:

- Added apply(Drawable) and apply(Geometry) to NodeVisitor

- Added accept(NodeVisitor) method to Drawable/Geometry

- Added traverse(NodeVisitor) to Geode which calls accept(NodeVisitor) on all Drawables

- Updated CullVisitor to use new apply(Drawable) to handle drawables. The apply(Billboard) method still manually handles the drawables since it is depends on the billboard settings. I needed to disable the traverse within billboard to prevent duplicate traversal of drawables.

- Update other osgUtil node visitors (GLObjectsVisitor, IncrementalCompileOperation, ..) to use new apply(Drawable) method.
"
This commit is contained in:
Robert Osfield 2014-05-12 12:10:35 +00:00
parent ead92353fe
commit b2c7bacfe9
13 changed files with 130 additions and 118 deletions

View File

@ -115,6 +115,8 @@ class OSG_EXPORT Drawable : public Object
* Equivalent to dynamic_cast<const Geometry*>(this).*/ * Equivalent to dynamic_cast<const Geometry*>(this).*/
virtual const Geometry* asGeometry() const { return 0; } virtual const Geometry* asGeometry() const { return 0; }
/** Visitor Pattern : calls the apply method of a NodeVisitor with this drawable's type.*/
virtual void accept(NodeVisitor& nv);
/** Compute the DataVariance based on an assessment of callback etc.*/ /** Compute the DataVariance based on an assessment of callback etc.*/
virtual void computeDataVariance(); virtual void computeDataVariance();

View File

@ -41,6 +41,8 @@ class OSG_EXPORT Geode : public Node
virtual Geode* asGeode() { return this; } virtual Geode* asGeode() { return this; }
virtual const Geode* asGeode() const { return this; } virtual const Geode* asGeode() const { return this; }
virtual void traverse(NodeVisitor& nv);
/** Add a \c Drawable to the \c Geode. /** Add a \c Drawable to the \c Geode.
* If \c drawable is not \c NULL and is not contained in the \c Geode * If \c drawable is not \c NULL and is not contained in the \c Geode
* then increment its reference count, add it to the drawables list and * then increment its reference count, add it to the drawables list and

View File

@ -44,6 +44,8 @@ class OSG_EXPORT Geometry : public Drawable
virtual Geometry* asGeometry() { return this; } virtual Geometry* asGeometry() { return this; }
virtual const Geometry* asGeometry() const { return this; } virtual const Geometry* asGeometry() const { return this; }
virtual void accept(NodeVisitor& nv) { nv.apply(*this); }
bool empty() const; bool empty() const;
typedef std::vector< osg::ref_ptr<osg::Array> > ArrayList; typedef std::vector< osg::ref_ptr<osg::Array> > ArrayList;

View File

@ -41,6 +41,8 @@ class TexGenNode;
class Transform; class Transform;
class Camera; class Camera;
class CameraView; class CameraView;
class Drawable;
class Geometry;
const unsigned int UNINITIALIZED_FRAME_NUMBER=0xffffffff; const unsigned int UNINITIALIZED_FRAME_NUMBER=0xffffffff;
@ -89,7 +91,7 @@ class OSG_EXPORT NodeVisitor : public virtual Object
NodeVisitor(const NodeVisitor& nv, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); NodeVisitor(const NodeVisitor& nv, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
virtual ~NodeVisitor(); virtual ~NodeVisitor();
META_Object(osg, NodeVisitor) META_Object(osg, NodeVisitor)
@ -237,6 +239,8 @@ class OSG_EXPORT NodeVisitor : public virtual Object
* If the getDistanceToViewPoint(pos) is not implemented then a default value of 0.0 is returned.*/ * If the getDistanceToViewPoint(pos) is not implemented then a default value of 0.0 is returned.*/
virtual float getDistanceToViewPoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; } virtual float getDistanceToViewPoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
virtual void apply(Drawable& drawable);
virtual void apply(Geometry& drawable);
virtual void apply(Node& node); virtual void apply(Node& node);

View File

@ -90,6 +90,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac
virtual void apply(osg::Node&); virtual void apply(osg::Node&);
virtual void apply(osg::Geode& node); virtual void apply(osg::Geode& node);
virtual void apply(osg::Drawable& drawable);
virtual void apply(osg::Billboard& node); virtual void apply(osg::Billboard& node);
virtual void apply(osg::LightSource& node); virtual void apply(osg::LightSource& node);
virtual void apply(osg::ClipNode& node); virtual void apply(osg::ClipNode& node);

View File

@ -44,7 +44,6 @@ class OSGUTIL_EXPORT StateToCompile : public osg::NodeVisitor
bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); } bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); }
virtual void apply(osg::Node& node); virtual void apply(osg::Node& node);
virtual void apply(osg::Geode& node);
virtual void apply(osg::Drawable& drawable); virtual void apply(osg::Drawable& drawable);
virtual void apply(osg::StateSet& stateset); virtual void apply(osg::StateSet& stateset);

View File

@ -272,6 +272,11 @@ Drawable::~Drawable()
dirtyDisplayList(); dirtyDisplayList();
} }
void Drawable::accept(NodeVisitor& nv)
{
nv.apply(*this);
}
osg::MatrixList Drawable::getWorldMatrices(const osg::Node* haltTraversalAtNode) const osg::MatrixList Drawable::getWorldMatrices(const osg::Node* haltTraversalAtNode) const
{ {
osg::MatrixList matrices; osg::MatrixList matrices;

View File

@ -48,6 +48,16 @@ Geode::~Geode()
} }
} }
void Geode::traverse(NodeVisitor& nv)
{
for(DrawableList::iterator itr=_drawables.begin();
itr!=_drawables.end();
++itr)
{
(*itr)->accept(nv);
}
}
bool Geode::addDrawable( Drawable *drawable ) bool Geode::addDrawable( Drawable *drawable )
{ {
if (drawable /* && !containsDrawable(drawable)*/) if (drawable /* && !containsDrawable(drawable)*/)

View File

@ -33,6 +33,7 @@
#include <osg/Transform> #include <osg/Transform>
#include <osg/Camera> #include <osg/Camera>
#include <osg/CameraView> #include <osg/CameraView>
#include <osg/Geometry>
#include <stdlib.h> #include <stdlib.h>
@ -75,6 +76,16 @@ NodeVisitor::~NodeVisitor()
// if (_traversalVisitor) detach from _traversalVisitor; // if (_traversalVisitor) detach from _traversalVisitor;
} }
void NodeVisitor::apply(Drawable& drawable)
{
// It all ends here...
}
void NodeVisitor::apply(Geometry& drawable)
{
apply(static_cast<Drawable&>(drawable));
}
void NodeVisitor::apply(Node& node) void NodeVisitor::apply(Node& node)
{ {
traverse(node); traverse(node);

View File

@ -961,91 +961,94 @@ void CullVisitor::apply(Geode& node)
{ {
if (isCulled(node)) return; if (isCulled(node)) return;
// push the culling mode.
pushCurrentMask();
// push the node's state. // push the node's state.
StateSet* node_state = node.getStateSet(); StateSet* node_state = node.getStateSet();
if (node_state) pushStateSet(node_state); if (node_state) pushStateSet(node_state);
// traverse any call callbacks and traverse any children.
handle_cull_callbacks_and_traverse(node); handle_cull_callbacks_and_traverse(node);
RefMatrix& matrix = *getModelViewMatrix();
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
Drawable* drawable = node.getDrawable(i);
const BoundingBox &bb =drawable->getBound();
if( drawable->getCullCallback() )
{
if( drawable->getCullCallback()->cull( this, drawable, &_renderInfo ) == true )
continue;
}
//else
{
if (node.isCullingActive() && isCulled(bb)) continue;
}
if (_computeNearFar && bb.valid())
{
if (!updateCalculatedNearFar(matrix,*drawable,false)) continue;
}
// need to track how push/pops there are, so we can unravel the stack correctly.
unsigned int numPopStateSetRequired = 0;
// push the geoset's state on the geostate stack.
StateSet* stateset = drawable->getStateSet();
if (stateset)
{
++numPopStateSetRequired;
pushStateSet(stateset);
}
CullingSet& cs = getCurrentCullingSet();
if (!cs.getStateFrustumList().empty())
{
osg::CullingSet::StateFrustumList& sfl = cs.getStateFrustumList();
for(osg::CullingSet::StateFrustumList::iterator itr = sfl.begin();
itr != sfl.end();
++itr)
{
if (itr->second.contains(bb))
{
++numPopStateSetRequired;
pushStateSet(itr->first.get());
}
}
}
float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f;
if (osg::isNaN(depth))
{
OSG_NOTICE<<"CullVisitor::apply(Geode&) detected NaN,"<<std::endl
<<" depth="<<depth<<", center=("<<bb.center()<<"),"<<std::endl
<<" matrix="<<matrix<<std::endl;
OSG_DEBUG << " NodePath:" << std::endl;
for (NodePath::const_iterator i = getNodePath().begin(); i != getNodePath().end(); ++i)
{
OSG_DEBUG << " \"" << (*i)->getName() << "\"" << std::endl;
}
}
else
{
addDrawableAndDepth(drawable,&matrix,depth);
}
for(unsigned int i=0;i< numPopStateSetRequired; ++i)
{
popStateSet();
}
}
// pop the node's state off the geostate stack. // pop the node's state off the geostate stack.
if (node_state) popStateSet(); if (node_state) popStateSet();
// pop the culling mode.
popCurrentMask();
}
void CullVisitor::apply(osg::Drawable& drawable)
{
RefMatrix& matrix = *getModelViewMatrix();
const BoundingBox &bb =drawable.getBound();
if( drawable.getCullCallback() )
{
if( drawable.getCullCallback()->cull( this, &drawable, &_renderInfo ) == true )
return;
}
//else
{
if (getNodePath().back()->isCullingActive() && isCulled(bb)) return;
}
if (_computeNearFar && bb.valid())
{
if (!updateCalculatedNearFar(matrix,drawable,false)) return;
}
// need to track how push/pops there are, so we can unravel the stack correctly.
unsigned int numPopStateSetRequired = 0;
// push the geoset's state on the geostate stack.
StateSet* stateset = drawable.getStateSet();
if (stateset)
{
++numPopStateSetRequired;
pushStateSet(stateset);
}
CullingSet& cs = getCurrentCullingSet();
if (!cs.getStateFrustumList().empty())
{
osg::CullingSet::StateFrustumList& sfl = cs.getStateFrustumList();
for(osg::CullingSet::StateFrustumList::iterator itr = sfl.begin();
itr != sfl.end();
++itr)
{
if (itr->second.contains(bb))
{
++numPopStateSetRequired;
pushStateSet(itr->first.get());
}
}
}
float depth = bb.valid() ? distance(bb.center(),matrix) : 0.0f;
if (osg::isNaN(depth))
{
OSG_NOTICE<<"CullVisitor::apply(Geode&) detected NaN,"<<std::endl
<<" depth="<<depth<<", center=("<<bb.center()<<"),"<<std::endl
<<" matrix="<<matrix<<std::endl;
OSG_DEBUG << " NodePath:" << std::endl;
for (NodePath::const_iterator i = getNodePath().begin(); i != getNodePath().end(); ++i)
{
OSG_DEBUG << " \"" << (*i)->getName() << "\"" << std::endl;
}
}
else
{
addDrawableAndDepth(&drawable,&matrix,depth);
}
for(unsigned int i=0;i< numPopStateSetRequired; ++i)
{
popStateSet();
}
} }
@ -1057,8 +1060,8 @@ void CullVisitor::apply(Billboard& node)
StateSet* node_state = node.getStateSet(); StateSet* node_state = node.getStateSet();
if (node_state) pushStateSet(node_state); if (node_state) pushStateSet(node_state);
// traverse any call callbacks and traverse any children. // Don't traverse billboard, since drawables are handled manually below
handle_cull_callbacks_and_traverse(node); //handle_cull_callbacks_and_traverse(node);
const Vec3& eye_local = getEyeLocal(); const Vec3& eye_local = getEyeLocal();
const RefMatrix& modelview = *getModelViewMatrix(); const RefMatrix& modelview = *getModelViewMatrix();

View File

@ -61,18 +61,7 @@ void GLObjectsVisitor::apply(osg::Geode& node)
apply(*(node.getStateSet())); apply(*(node.getStateSet()));
} }
for(unsigned int i=0;i<node.getNumDrawables();++i) traverse(node);
{
osg::Drawable* drawable = node.getDrawable(i);
if (drawable)
{
apply(*drawable);
if (drawable->getStateSet())
{
apply(*(drawable->getStateSet()));
}
}
}
bool programSetAfter = _lastCompiledProgram.valid(); bool programSetAfter = _lastCompiledProgram.valid();
if (!programSetBefore && programSetAfter) if (!programSetBefore && programSetAfter)
@ -120,6 +109,11 @@ void GLObjectsVisitor::apply(osg::Drawable& drawable)
{ {
drawable.releaseGLObjects(_renderInfo.getState()); drawable.releaseGLObjects(_renderInfo.getState());
} }
if (drawable.getStateSet())
{
apply(*(drawable.getStateSet()));
}
} }
void GLObjectsVisitor::apply(osg::StateSet& stateset) void GLObjectsVisitor::apply(osg::StateSet& stateset)

View File

@ -70,27 +70,6 @@ void StateToCompile::apply(osg::Node& node)
traverse(node); traverse(node);
} }
void StateToCompile::apply(osg::Geode& node)
{
if (node.getStateSet())
{
apply(*(node.getStateSet()));
}
for(unsigned int i=0;i<node.getNumDrawables();++i)
{
osg::Drawable* drawable = node.getDrawable(i);
if (drawable)
{
apply(*drawable);
if (drawable->getStateSet())
{
apply(*(drawable->getStateSet()));
}
}
}
}
void StateToCompile::apply(osg::Drawable& drawable) void StateToCompile::apply(osg::Drawable& drawable)
{ {
if (_drawablesHandled.count(&drawable)!=0) return; if (_drawablesHandled.count(&drawable)!=0) return;
@ -122,6 +101,11 @@ void StateToCompile::apply(osg::Drawable& drawable)
{ {
_drawables.insert(&drawable); _drawables.insert(&drawable);
} }
if (drawable.getStateSet())
{
apply(*(drawable.getStateSet()));
}
} }
void StateToCompile::apply(osg::StateSet& stateset) void StateToCompile::apply(osg::StateSet& stateset)

View File

@ -251,11 +251,6 @@ void StatsVisitor::apply(osg::Geode& node)
++_numInstancedGeode; ++_numInstancedGeode;
_geodeSet.insert(&node); _geodeSet.insert(&node);
for(unsigned int i=0; i<node.getNumDrawables();++i)
{
apply(*node.getDrawable(i));
}
traverse(node); traverse(node);
} }