Hi Robert,

On Wednesday, June 22, 2011 17:17:26 Robert Osfield wrote:
> > At first it would probably help when the NodeVisitor is able to visit
> > Drawables using the usual accept mehtods or something like that. Then we
> > could probably just use the Geodes traverse method to walk the drawables.
> > One dfficulty in this approach is the Bilboard implementation that does
> > little more then just a traversal of all Drawables.
> 
> I don't see any problems with handling subclasses from Geode, it'd be
> bit like how
> LOD subclasses from Group - it add a per child property that the the
> traverse method
> handles in a special way.  A NodeCallback that overrides the traverse
> then would have
> to handle the special functionality of a Billboard.  In the case of a
> Billboard we'd
> probably want to have a special handling of cases when chidlren are
> Drawable rather
> than Node's, as Drawables you can just manage the modelview matrix
> directly and don't
> need to worry about the view frustum transformation, while normal Nodes you
> have to push/pop the view frustum as we do right now for the normal
> Transform nodes.

Hmm, I am not exactly sure I already see what you are thinking:

I have started playing with this approach at some time. Attached is the patch 
I had so far. The NodeVisitor is just extended by the Drawable. May be the 
other drawable derived classes could be put there too. The patch just factors 
out the loop body of the geode in the cull visitor and puts that into a new 
CullVisitor::apply(Drawable&) method.

That patch does not work for any billboard geode. This is just meant as a 
miminmal sketch implementation.

Now, If the billboard loop is implemented like the LOD nodes traversal method, 
we need virtual access to the modelview matrix in the NodeVisitor base class 
from the Billboard::traverse() method. Currently this is not available.

So, may be {push,pop}ModelViewMatrix as a virtual method in the NodeVisitor? 
Or do you already have a better idea to do that?

Greetings

Mathias
Index: include/osgUtil/CullVisitor
===================================================================
--- include/osgUtil/CullVisitor	(revision 12643)
+++ include/osgUtil/CullVisitor	(working copy)
@@ -105,6 +105,8 @@
         virtual void apply(osg::OccluderNode& node);
         virtual void apply(osg::OcclusionQueryNode& node);
 
+        virtual void apply(osg::Drawable& drawable);
+
         /** Push state set on the current state group.
           * If the state exists in a child state group of the current
           * state group then move the current state group to that child.
Index: include/osg/NodeVisitor
===================================================================
--- include/osg/NodeVisitor	(revision 12643)
+++ include/osg/NodeVisitor	(working copy)
@@ -271,6 +271,7 @@
         virtual void apply(OccluderNode& node);
         virtual void apply(OcclusionQueryNode& node);
 
+        virtual void apply(Drawable& drawable);
 
         /** Callback for managing database paging, such as generated by PagedLOD nodes.*/
         class DatabaseRequestHandler : public osg::Referenced
Index: include/osg/Geode
===================================================================
--- include/osg/Geode	(revision 12643)
+++ include/osg/Geode	(working copy)
@@ -41,6 +41,9 @@
         virtual Geode* asGeode() { return this; }
         virtual const Geode* asGeode() const { return this; }
         
+        /** Traverse downwards : calls children's accept method with NodeVisitor.*/
+        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
Index: include/osg/Drawable
===================================================================
--- include/osg/Drawable	(revision 12643)
+++ include/osg/Drawable	(working copy)
@@ -574,6 +574,10 @@
         virtual void accept(PrimitiveIndexFunctor&) const {}
 
 
+        /** Visitor Pattern : calls the apply method of a NodeVisitor with this node's type.*/
+        virtual void accept(NodeVisitor& nv) { nv.apply(*this); }
+
+
         /** Extensions class which encapsulates the querying of extensions and
         * associated function pointers, and provide convenience wrappers to
         * check for the extensions or use the associated functions.*/
Index: src/osgUtil/CullVisitor.cpp
===================================================================
--- src/osgUtil/CullVisitor.cpp	(revision 12643)
+++ src/osgUtil/CullVisitor.cpp	(working copy)
@@ -876,81 +876,6 @@
     // traverse any call callbacks and traverse any children.
     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.    
     if (node_state) popStateSet();
 
@@ -1646,3 +1571,70 @@
     popCurrentMask();
 }
 
+void CullVisitor::apply(Drawable& drawable)
+{
+    if( drawable.getCullCallback() )
+    {
+        if( drawable.getCullCallback()->cull( this, &drawable, &_renderInfo ) == true )
+            return;
+    }
+        
+    const BoundingBox &bb = drawable.getBound();
+    if (!getNodePath().empty() && getNodePath().back()->isCullingActive() && isCulled(bb)) return;
+
+    RefMatrix& matrix = *getModelViewMatrix();
+    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();
+    }
+}
Index: src/osg/NodeVisitor.cpp
===================================================================
--- src/osg/NodeVisitor.cpp	(revision 12643)
+++ src/osg/NodeVisitor.cpp	(working copy)
@@ -175,3 +175,7 @@
 { 
     apply(static_cast<Group&>(node));
 }
+
+void NodeVisitor::apply(Drawable& drawable)
+{
+}
Index: src/osg/Geode.cpp
===================================================================
--- src/osg/Geode.cpp	(revision 12643)
+++ src/osg/Geode.cpp	(working copy)
@@ -47,6 +47,16 @@
     }
 }
 
+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)*/)
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to