From b2c7bacfe9a7480be4325b5644fde8ee5d883a87 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 12 May 2014 12:10:35 +0000 Subject: [PATCH] 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. " --- include/osg/Drawable | 2 + include/osg/Geode | 2 + include/osg/Geometry | 2 + include/osg/NodeVisitor | 6 +- include/osgUtil/CullVisitor | 1 + include/osgUtil/IncrementalCompileOperation | 1 - src/osg/Drawable.cpp | 5 + src/osg/Geode.cpp | 10 ++ src/osg/NodeVisitor.cpp | 11 ++ src/osgUtil/CullVisitor.cpp | 159 ++++++++++---------- src/osgUtil/GLObjectsVisitor.cpp | 18 +-- src/osgUtil/IncrementalCompileOperation.cpp | 26 +--- src/osgUtil/Statistics.cpp | 5 - 13 files changed, 130 insertions(+), 118 deletions(-) diff --git a/include/osg/Drawable b/include/osg/Drawable index fcb131ce8..beb9f2602 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -115,6 +115,8 @@ class OSG_EXPORT Drawable : public Object * Equivalent to dynamic_cast(this).*/ 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.*/ virtual void computeDataVariance(); diff --git a/include/osg/Geode b/include/osg/Geode index 66bb1543e..0da365b8f 100644 --- a/include/osg/Geode +++ b/include/osg/Geode @@ -41,6 +41,8 @@ class OSG_EXPORT Geode : public Node virtual Geode* asGeode() { return this; } virtual const Geode* asGeode() const { return this; } + virtual void traverse(NodeVisitor& nv); + /** Add a \c Drawable to 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 diff --git a/include/osg/Geometry b/include/osg/Geometry index 1020076d3..384ac6b6d 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -44,6 +44,8 @@ class OSG_EXPORT Geometry : public Drawable virtual Geometry* asGeometry() { return this; } virtual const Geometry* asGeometry() const { return this; } + virtual void accept(NodeVisitor& nv) { nv.apply(*this); } + bool empty() const; typedef std::vector< osg::ref_ptr > ArrayList; diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index 85db4181f..9f6e91237 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -41,6 +41,8 @@ class TexGenNode; class Transform; class Camera; class CameraView; +class Drawable; +class Geometry; 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); - virtual ~NodeVisitor(); + virtual ~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.*/ 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); diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 4530d37d3..93fd8a28f 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -90,6 +90,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac virtual void apply(osg::Node&); virtual void apply(osg::Geode& node); + virtual void apply(osg::Drawable& drawable); virtual void apply(osg::Billboard& node); virtual void apply(osg::LightSource& node); virtual void apply(osg::ClipNode& node); diff --git a/include/osgUtil/IncrementalCompileOperation b/include/osgUtil/IncrementalCompileOperation index 8c38371bb..cdd42800c 100644 --- a/include/osgUtil/IncrementalCompileOperation +++ b/include/osgUtil/IncrementalCompileOperation @@ -44,7 +44,6 @@ class OSGUTIL_EXPORT StateToCompile : public osg::NodeVisitor bool empty() const { return _textures.empty() && _programs.empty() && _drawables.empty(); } virtual void apply(osg::Node& node); - virtual void apply(osg::Geode& node); virtual void apply(osg::Drawable& drawable); virtual void apply(osg::StateSet& stateset); diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 085aa30fa..8e1d2cbcd 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -272,6 +272,11 @@ Drawable::~Drawable() dirtyDisplayList(); } +void Drawable::accept(NodeVisitor& nv) +{ + nv.apply(*this); +} + osg::MatrixList Drawable::getWorldMatrices(const osg::Node* haltTraversalAtNode) const { osg::MatrixList matrices; diff --git a/src/osg/Geode.cpp b/src/osg/Geode.cpp index 97ac74e56..56cb7554d 100644 --- a/src/osg/Geode.cpp +++ b/src/osg/Geode.cpp @@ -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 ) { if (drawable /* && !containsDrawable(drawable)*/) diff --git a/src/osg/NodeVisitor.cpp b/src/osg/NodeVisitor.cpp index 850820bdf..5797b48db 100644 --- a/src/osg/NodeVisitor.cpp +++ b/src/osg/NodeVisitor.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -75,6 +76,16 @@ NodeVisitor::~NodeVisitor() // if (_traversalVisitor) detach from _traversalVisitor; } +void NodeVisitor::apply(Drawable& drawable) +{ + // It all ends here... +} + +void NodeVisitor::apply(Geometry& drawable) +{ + apply(static_cast(drawable)); +} + void NodeVisitor::apply(Node& node) { traverse(node); diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 907e73125..c7b80853c 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -961,91 +961,94 @@ void CullVisitor::apply(Geode& node) { if (isCulled(node)) return; + // push the culling mode. + pushCurrentMask(); + // push the node's state. StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - // traverse any call callbacks and traverse any children. handle_cull_callbacks_and_traverse(node); - RefMatrix& matrix = *getModelViewMatrix(); - for(unsigned int i=0;igetBound(); - - 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,"<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. 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,"<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(); if (node_state) pushStateSet(node_state); - // traverse any call callbacks and traverse any children. - handle_cull_callbacks_and_traverse(node); + // Don't traverse billboard, since drawables are handled manually below + //handle_cull_callbacks_and_traverse(node); const Vec3& eye_local = getEyeLocal(); const RefMatrix& modelview = *getModelViewMatrix(); diff --git a/src/osgUtil/GLObjectsVisitor.cpp b/src/osgUtil/GLObjectsVisitor.cpp index 88b566673..02c3cca56 100644 --- a/src/osgUtil/GLObjectsVisitor.cpp +++ b/src/osgUtil/GLObjectsVisitor.cpp @@ -61,18 +61,7 @@ void GLObjectsVisitor::apply(osg::Geode& node) apply(*(node.getStateSet())); } - for(unsigned int i=0;igetStateSet()) - { - apply(*(drawable->getStateSet())); - } - } - } + traverse(node); bool programSetAfter = _lastCompiledProgram.valid(); if (!programSetBefore && programSetAfter) @@ -120,6 +109,11 @@ void GLObjectsVisitor::apply(osg::Drawable& drawable) { drawable.releaseGLObjects(_renderInfo.getState()); } + + if (drawable.getStateSet()) + { + apply(*(drawable.getStateSet())); + } } void GLObjectsVisitor::apply(osg::StateSet& stateset) diff --git a/src/osgUtil/IncrementalCompileOperation.cpp b/src/osgUtil/IncrementalCompileOperation.cpp index 0725f0575..520f4dbbd 100644 --- a/src/osgUtil/IncrementalCompileOperation.cpp +++ b/src/osgUtil/IncrementalCompileOperation.cpp @@ -70,27 +70,6 @@ void StateToCompile::apply(osg::Node& node) traverse(node); } -void StateToCompile::apply(osg::Geode& node) -{ - if (node.getStateSet()) - { - apply(*(node.getStateSet())); - } - - for(unsigned int i=0;igetStateSet()) - { - apply(*(drawable->getStateSet())); - } - } - } -} - void StateToCompile::apply(osg::Drawable& drawable) { if (_drawablesHandled.count(&drawable)!=0) return; @@ -122,6 +101,11 @@ void StateToCompile::apply(osg::Drawable& drawable) { _drawables.insert(&drawable); } + + if (drawable.getStateSet()) + { + apply(*(drawable.getStateSet())); + } } void StateToCompile::apply(osg::StateSet& stateset) diff --git a/src/osgUtil/Statistics.cpp b/src/osgUtil/Statistics.cpp index 5fa832b88..d04cea8b4 100644 --- a/src/osgUtil/Statistics.cpp +++ b/src/osgUtil/Statistics.cpp @@ -251,11 +251,6 @@ void StatsVisitor::apply(osg::Geode& node) ++_numInstancedGeode; _geodeSet.insert(&node); - for(unsigned int i=0; i