diff --git a/include/osg/Node b/include/osg/Node index 38e46b390..0cdff6fae 100644 --- a/include/osg/Node +++ b/include/osg/Node @@ -112,6 +112,15 @@ class SG_EXPORT Node : public Object inline const int getNumChildrenRequiringAppTraversal() const { return _numChildrenRequiringAppTraversal; } + /** Set cull node callback, called during cull traversal. */ + void setCullCallback(NodeCallback* nc) { _cullCallback = nc; } + + /** Get app node callback, called during app traversal. */ + inline NodeCallback* getCullCallback() { return _cullCallback.get(); } + + /** Get const app node callback, called during app traversal. */ + inline const NodeCallback* getCullCallback() const { return _cullCallback.get(); } + /** Set the view frustum/small feature culling of this node to be active or inactive. * The default value to true for _cullingActive. Used a guide * to the cull traversal.*/ @@ -220,6 +229,8 @@ class SG_EXPORT Node : public Object int _numChildrenRequiringAppTraversal; void setNumChildrenRequiringAppTraversal(const int num); + ref_ptr _cullCallback; + bool _cullingActive; int _numChildrenWithCullingDisabled; void setNumChildrenWithCullingDisabled(const int num); diff --git a/include/osg/NodeCallback b/include/osg/NodeCallback index d9a2719e1..d8fe51f8d 100644 --- a/include/osg/NodeCallback +++ b/include/osg/NodeCallback @@ -22,7 +22,13 @@ class SG_EXPORT NodeCallback : public Referenced { /** Callback method call by the NodeVisitor when visiting a node.*/ - virtual void operator()(Node*, NodeVisitor*) {} + virtual void operator()(Node* node, NodeVisitor* nv) + { + // note, callback is repsonsible for scenegraph traversal so + // should always include call the traverse(node,nv) to ensure + // that the rest of cullbacks and the scene graph are traversed. + traverse(node,nv); + } /** Call any nested callbacks and then traverse the scene graph. */ void traverse(Node* node,NodeVisitor* nv); diff --git a/include/osgUtil/AppVisitor b/include/osgUtil/AppVisitor index e229568b7..58559f798 100644 --- a/include/osgUtil/AppVisitor +++ b/include/osgUtil/AppVisitor @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -33,17 +34,18 @@ class OSGUTIL_EXPORT AppVisitor : public osg::NodeVisitor virtual void reset(); - virtual void apply(osg::Node& node) { handle_callbacks(node); } + virtual void apply(osg::Node& node) { handle_callbacks_and_traverse(node); } - virtual void apply(osg::Geode& node) { handle_callbacks(node); } - virtual void apply(osg::Billboard& node) { handle_callbacks(node); } - virtual void apply(osg::LightSource& node){ handle_callbacks(node); } + virtual void apply(osg::Geode& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::Billboard& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::LightSource& node){ handle_callbacks_and_traverse(node); } - virtual void apply(osg::Group& node) { handle_callbacks(node); } - virtual void apply(osg::Transform& node) { handle_callbacks(node); } - virtual void apply(osg::Switch& node) { handle_callbacks(node); } - virtual void apply(osg::LOD& node) { handle_callbacks(node); } - virtual void apply(osg::Impostor& node) { handle_callbacks(node); } + virtual void apply(osg::Group& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::Transform& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::Projection& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::Switch& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::LOD& node) { handle_callbacks_and_traverse(node); } + virtual void apply(osg::Impostor& node) { handle_callbacks_and_traverse(node); } protected: @@ -54,7 +56,7 @@ class OSGUTIL_EXPORT AppVisitor : public osg::NodeVisitor /** prevent unwanted copy operator.*/ AppVisitor& operator = (const AppVisitor&) { return *this; } - inline void handle_callbacks(osg::Node& node) + inline void handle_callbacks_and_traverse(osg::Node& node) { osg::NodeCallback* callback = node.getAppCallback(); if (callback) (*callback)(&node,this); diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 3b23e7593..f508710a4 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -183,6 +183,20 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor /** prevent unwanted copy operator.*/ CullVisitor& operator = (const CullVisitor&) { return *this; } + inline void handle_cull_callbacks_and_traverse(osg::Node& node) + { + osg::NodeCallback* callback = node.getCullCallback(); + if (callback) (*callback)(&node,this); + else traverse(node); + } + + inline void handle_cull_callbacks_and_accept(osg::Node& node,osg::Node* acceptNode) + { + osg::NodeCallback* callback = node.getCullCallback(); + if (callback) (*callback)(&node,this); + else acceptNode->accept(*this); + } + inline osg::Matrix* getCurrentMatrix() { return _modelviewStack.back().get(); diff --git a/src/Demos/osghud/osghud.cpp b/src/Demos/osghud/osghud.cpp index 3d6d8ca12..7b8320363 100644 --- a/src/Demos/osghud/osghud.cpp +++ b/src/Demos/osghud/osghud.cpp @@ -261,7 +261,19 @@ void set2dScene(osg::Group* rootNode) } +struct MyCallback : public osg::NodeCallback +{ + MyCallback(const std::string& str):_message(str) {} + + virtual void operator() (osg::Node* node,osg::NodeVisitor* nv) + { + std::cout<<"In my callback '"<<_message<<"'"<addChild(modelview_abs); + projection->setAppCallback(osgNew MyCallback("App callback")); + projection->setCullCallback(osgNew MyCallback("Cull callback")); group->addChild(projection); diff --git a/src/osg/Node.cpp b/src/osg/Node.cpp index b3a189df4..fa40fc6a8 100644 --- a/src/osg/Node.cpp +++ b/src/osg/Node.cpp @@ -27,6 +27,7 @@ Node::Node(const Node& node,const CopyOp& copyop): _parents(), // leave empty as parentList is managed by Group. _appCallback(node._appCallback), _numChildrenRequiringAppTraversal(0), // assume no children yet. + _cullCallback(node._cullCallback), _cullingActive(node._cullingActive), _numChildrenWithCullingDisabled(0), // assume no children yet. _userData(copyop(node._userData.get())), diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index d5d1da1e6..017fa3384 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -350,7 +350,7 @@ void CullVisitor::apply(Node& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - traverse(node); + handle_cull_callbacks_and_traverse(node); // pop the node's state off the geostate stack. if (node_state) popStateSet(); @@ -551,7 +551,7 @@ void CullVisitor::apply(Group& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - traverse(node); + handle_cull_callbacks_and_traverse(node); // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -581,7 +581,7 @@ void CullVisitor::apply(Transform& node) node.getLocalToWorldMatrix(*matrix,this); pushModelViewMatrix(matrix.get()); - traverse(node); + handle_cull_callbacks_and_traverse(node); popModelViewMatrix(); @@ -612,7 +612,7 @@ void CullVisitor::apply(Projection& node) *matrix = node.getMatrix(); pushProjectionMatrix(matrix.get()); - traverse(node); + handle_cull_callbacks_and_traverse(node); popProjectionMatrix(); @@ -649,7 +649,7 @@ void CullVisitor::apply(LOD& node) if (node_state) pushStateSet(node_state); //notify(INFO) << "selecting child "<accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -667,7 +667,7 @@ void CullVisitor::apply(osg::EarthSky& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - traverse(node); + handle_cull_callbacks_and_traverse(node); // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -708,13 +708,13 @@ void CullVisitor::apply(Impostor& node) { // outwith the impostor distance threshold therefore simple // traverse the appropriate child of the LOD. - node.getChild(eval)->accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); } else if (_viewportStack.empty()) { // need to use impostor but no valid viewport is defined to simply // default to using the LOD child as above. - node.getChild(eval)->accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); } else { @@ -799,7 +799,7 @@ void CullVisitor::apply(Impostor& node) { // no impostor has been selected or created so default to // traversing the usual LOD selected child. - node.getChild(eval)->accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); } } @@ -973,7 +973,7 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) { // traversing the usual LOD selected child. - node.getChild(eval)->accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); }