1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_NODEVISITOR
15#define OSG_NODEVISITOR 1
19#include <osg/FrameStamp>
21#include <osg/ValueMap>
22#include <osg/ValueStack>
25namespace osgUtil { class UpdateVisitor; class CullVisitor; class IntersectionVisitor; }
26namespace osgGA { class EventVisitor; }
33class CoordinateSystemNode;
40class OcclusionQueryNode;
42class PositionAttitudeTransform;
44class MultiViewAutoTransform;
61const unsigned int UNINITIALIZED_FRAME_NUMBER=0xffffffff;
63#define META_NodeVisitor(library, name) \
64 virtual const char* libraryName() const { return #library; }\
65 virtual const char* className() const { return #name; }
67/** Visitor for type safe operations on osg::Nodes.
68 Based on GOF's Visitor pattern. The NodeVisitor
69 is useful for developing type safe operations to nodes
70 in the scene graph (as per Visitor pattern), and adds to this
71 support for optional scene graph traversal to allow
72 operations to be applied to whole scenes at once. The Visitor
73 pattern uses a technique of double dispatch as a mechanism to
74 call the appropriate apply(..) method of the NodeVisitor. To
75 use this feature one must use the Node::accept(NodeVisitor) which
76 is extended in each Node subclass, rather than the NodeVisitor
77 apply directly. So use root->accept(myVisitor); instead of
78 myVisitor.apply(*root). The later method will bypass the double
79 dispatch and the appropriate NodeVisitor::apply(..) method will
81class OSG_EXPORT NodeVisitor : public virtual Object
89 TRAVERSE_ALL_CHILDREN,
90 TRAVERSE_ACTIVE_CHILDREN
98 COLLECT_OCCLUDER_VISITOR,
103 NodeVisitor(TraversalMode tm=TRAVERSE_NONE);
105 NodeVisitor(VisitorType type,TraversalMode tm=TRAVERSE_NONE);
107 NodeVisitor(const NodeVisitor& nv, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
109 virtual ~NodeVisitor();
111 META_Object(osg, NodeVisitor)
113 /** Convert 'this' into a NodeVisitor pointer if Object is a NodeVisitor, otherwise return 0.
114 * Equivalent to dynamic_cast<NodeVisitor*>(this).*/
115 virtual NodeVisitor* asNodeVisitor() { return this; }
117 /** convert 'const this' into a const NodeVisitor pointer if Object is a NodeVisitor, otherwise return 0.
118 * Equivalent to dynamic_cast<const NodeVisitor*>(this).*/
119 virtual const NodeVisitor* asNodeVisitor() const { return this; }
121 /** Convert 'this' into a osgUtil::UpdateVisitor pointer if Object is a osgUtil::UpdateVisitor, otherwise return 0.
122 * Equivalent to dynamic_cast<osgUtil::UpdateVisitor*>(this).*/
123 virtual osgUtil::UpdateVisitor* asUpdateVisitor() { return 0; }
125 /** convert 'const this' into a const osgUtil::UpdateVisitor pointer if Object is a osgUtil::UpdateVisitor, otherwise return 0.
126 * Equivalent to dynamic_cast<const osgUtil::UpdateVisitor*>(this).*/
127 virtual const osgUtil::UpdateVisitor* asUpdateVisitor() const { return 0; }
129 /** Convert 'this' into a osgUtil::CullVisitor pointer if Object is a osgUtil::CullVisitor, otherwise return 0.
130 * Equivalent to dynamic_cast<osgUtil::CullVisitor*>(this).*/
131 virtual osgUtil::CullVisitor* asCullVisitor() { return 0; }
133 /** convert 'const this' into a const osgUtil::CullVisitor pointer if Object is a osgUtil::CullVisitor, otherwise return 0.
134 * Equivalent to dynamic_cast<const osgUtil::CullVisitor*>(this).*/
135 virtual const osgUtil::CullVisitor* asCullVisitor() const { return 0; }
137 /** Convert 'this' into a osgGA::EventVisitor pointer if Object is a osgGA::EventVisitor, otherwise return 0.
138 * Equivalent to dynamic_cast<osgGA::EventVisitor*>(this).*/
139 virtual osgGA::EventVisitor* asEventVisitor() { return 0; }
141 /** convert 'const this' into a const osgGA::EventVisitor pointer if Object is a osgGA::EventVisitor, otherwise return 0.
142 * Equivalent to dynamic_cast<const osgGA::EventVisitor*>(this).*/
143 virtual const osgGA::EventVisitor* asEventVisitor() const { return 0; }
145 /** Convert 'this' into a osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
146 * Equivalent to dynamic_cast<osgUtil::IntersectionVisitor*>(this).*/
147 virtual osgUtil::IntersectionVisitor* asIntersectionVisitor() { return 0; }
149 /** convert 'const this' into a const osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
150 * Equivalent to dynamic_cast<const osgUtil::IntersectionVisitor*>(this).*/
151 virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return 0; }
153 /** Convert 'this' into a osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0.
154 * Equivalent to dynamic_cast<osg::CullStack*>(this).*/
155 virtual osg::CullStack* asCullStack() { return 0; }
157 /** convert 'const this' into a const osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0.
158 * Equivalent to dynamic_cast<const osg::CullStack*>(this).*/
159 virtual const osg::CullStack* asCullStack() const { return 0; }
163 /** Method to call to reset visitor. Useful if your visitor accumulates
164 state during a traversal, and you plan to reuse the visitor.
165 To flush that state for the next traversal: call reset() prior
167 virtual void reset() {}
170 /** Set the VisitorType, used to distinguish different visitors during
171 * traversal of the scene, typically used in the Node::traverse() method
172 * to select which behaviour to use for different types of traversal/visitors.*/
173 inline void setVisitorType(VisitorType type) { _visitorType = type; }
175 /** Get the VisitorType.*/
176 inline VisitorType getVisitorType() const { return _visitorType; }
178 /** Set the traversal number. Typically used to denote the frame count.*/
179 inline void setTraversalNumber(unsigned int fn) { _traversalNumber = fn; }
181 /** Get the traversal number. Typically used to denote the frame count.*/
182 inline unsigned int getTraversalNumber() const { return _traversalNumber; }
184 /** Set the FrameStamp that this traversal is associated with.*/
185 inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
187 /** Get the FrameStamp that this traversal is associated with.*/
188 inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
191 /** Set the TraversalMask of this NodeVisitor.
192 * The TraversalMask is used by the NodeVisitor::validNodeMask() method
193 * to determine whether to operate on a node and its subgraph.
194 * validNodeMask() is called automatically in the Node::accept() method before
195 * any call to NodeVisitor::apply(), apply() is only ever called if validNodeMask
196 * returns true. Note, if NodeVisitor::_traversalMask is 0 then all operations
197 * will be switched off for all nodes. Whereas setting both _traversalMask and
198 * _nodeMaskOverride to 0xffffffff will allow a visitor to work on all nodes
199 * regardless of their own Node::_nodeMask state.*/
200 inline void setTraversalMask(Node::NodeMask mask) { _traversalMask = mask; }
202 /** Get the TraversalMask.*/
203 inline Node::NodeMask getTraversalMask() const { return _traversalMask; }
205 /** Set the NodeMaskOverride mask.
206 * Used in validNodeMask() to determine whether to operate on a node or its
207 * subgraph, by OR'ing NodeVisitor::_nodeMaskOverride with the Node's own Node::_nodeMask.
208 * Typically used to force on nodes which may have
209 * been switched off by their own Node::_nodeMask.*/
210 inline void setNodeMaskOverride(Node::NodeMask mask) { _nodeMaskOverride = mask; }
212 /** Get the NodeMaskOverride mask.*/
213 inline Node::NodeMask getNodeMaskOverride() const { return _nodeMaskOverride; }
215 /** Method to called by Node and its subclass' Node::accept() method, if the result is true
216 * it is used to cull operations of nodes and their subgraphs.
217 * Return true if the result of a bit wise and of the NodeVisitor::_traversalMask
218 * with the bit or between NodeVistor::_nodeMaskOverride and the Node::_nodeMask.
219 * default values for _traversalMask is 0xffffffff, _nodeMaskOverride is 0x0,
220 * and osg::Node::_nodeMask is 0xffffffff. */
221 inline bool validNodeMask(const osg::Node& node) const
223 return (getTraversalMask() & (getNodeMaskOverride() | node.getNodeMask()))!=0;
226 /** Set the traversal mode for Node::traverse() to use when
227 deciding which children of a node to traverse. If a
228 NodeVisitor has been attached via setTraverseVisitor()
229 and the new mode is not TRAVERSE_VISITOR then the attached
230 visitor is detached. Default mode is TRAVERSE_NONE.*/
231 inline void setTraversalMode(TraversalMode mode) { _traversalMode = mode; }
233 /** Get the traversal mode.*/
234 inline TraversalMode getTraversalMode() const { return _traversalMode; }
237 /** Set the ValueMap used to store Values that can be reused over a series of traversals. */
238 inline void setValueMap(ValueMap* ps) { _valueMap = ps; }
240 /** Get the ValueMap. */
241 inline ValueMap* getValueMap() { return _valueMap.get(); }
243 /** Get the ValueMap. */
244 inline const ValueMap* getValueMap() const { return _valueMap.get(); }
246 /** Get the ValueMap. */
247 inline ValueMap* getOrCreateValueMap()
249 if (!_valueMap) _valueMap = new ValueMap;
250 return _valueMap.get();
253 /** Set the ValueStack used to stack Values during traversal. */
254 inline void setValueStack(ValueStack* ps) { _valueStack = ps; }
256 /** Get the ValueStack. */
257 inline ValueStack* getValueStack() { return _valueStack.get(); }
259 /** Get the const ValueStack. */
260 inline const ValueStack* getValueStack() const { return _valueStack.get(); }
262 /** Get the ValueStack. */
263 inline ValueStack* getOrCreateValueStack()
265 if (!_valueStack) _valueStack = new ValueStack;
266 return _valueStack.get();
270 /** Method for handling traversal of a nodes.
271 If you intend to use the visitor for actively traversing
272 the scene graph then make sure the accept() methods call
273 this method unless they handle traversal directly.*/
274 inline void traverse(Node& node)
276 if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this);
277 else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this);
280 /** Method called by osg::Node::accept() method before
281 * a call to the NodeVisitor::apply(..). The back of the list will,
282 * therefore, be the current node being visited inside the apply(..),
283 * and the rest of the list will be the parental sequence of nodes
284 * from the top most node applied down the graph to the current node.
285 * Note, the user does not typically call pushNodeOnPath() as it
286 * will be called automatically by the Node::accept() method.*/
287 inline void pushOntoNodePath(Node* node) { if (_traversalMode!=TRAVERSE_PARENTS) _nodePath.push_back(node); else _nodePath.insert(_nodePath.begin(),node); }
289 /** Method called by osg::Node::accept() method after
290 * a call to NodeVisitor::apply(..).
291 * Note, the user does not typically call popFromNodePath() as it
292 * will be called automatically by the Node::accept() method.*/
293 inline void popFromNodePath() { if (_traversalMode!=TRAVERSE_PARENTS) _nodePath.pop_back(); else _nodePath.erase(_nodePath.begin()); }
295 /** Get the non const NodePath from the top most node applied down
296 * to the current Node being visited.*/
297 NodePath& getNodePath() { return _nodePath; }
299 /** Get the const NodePath from the top most node applied down
300 * to the current Node being visited.*/
301 const NodePath& getNodePath() const { return _nodePath; }
303 /** Get the eye point in local coordinates.
304 * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.*/
305 virtual osg::Vec3 getEyePoint() const { return Vec3(0.0f,0.0f,0.0f); }
307 /** Get the view point in local coordinates.
308 * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.*/
309 virtual osg::Vec3 getViewPoint() const { return getEyePoint(); }
311 /** Get the distance from a point to the eye point, distance value in local coordinate system.
312 * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
313 * If the getDistanceFromEyePoint(pos) is not implemented then a default value of 0.0 is returned.*/
314 virtual float getDistanceToEyePoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
316 /** Get the distance of a point from the eye point, distance value in the eye coordinate system.
317 * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
318 * If the getDistanceFromEyePoint(pos) is not implemented than a default value of 0.0 is returned.*/
319 virtual float getDistanceFromEyePoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
321 /** Get the distance from a point to the view point, distance value in local coordinate system.
322 * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
323 * If the getDistanceToViewPoint(pos) is not implemented then a default value of 0.0 is returned.*/
324 virtual float getDistanceToViewPoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
326 virtual void apply(Drawable& drawable);
327 virtual void apply(Geometry& geometry);
329 virtual void apply(Node& node);
331 virtual void apply(Geode& node);
332 virtual void apply(Billboard& node);
334 virtual void apply(Group& node);
336 virtual void apply(ProxyNode& node);
338 virtual void apply(Projection& node);
340 virtual void apply(CoordinateSystemNode& node);
342 virtual void apply(ClipNode& node);
343 virtual void apply(TexGenNode& node);
344 virtual void apply(LightSource& node);
346 virtual void apply(Transform& node);
347 virtual void apply(Camera& node);
348 virtual void apply(CameraView& node);
349 virtual void apply(MatrixTransform& node);
350 virtual void apply(PositionAttitudeTransform& node);
351 virtual void apply(AutoTransform& node);
353 virtual void apply(Switch& node);
354 virtual void apply(Sequence& node);
355 virtual void apply(LOD& node);
356 virtual void apply(PagedLOD& node);
357 virtual void apply(ClearNode& node);
358 virtual void apply(OccluderNode& node);
359 virtual void apply(OcclusionQueryNode& node);
362 /** Callback for managing database paging, such as generated by PagedLOD nodes.*/
363 class DatabaseRequestHandler : public osg::Referenced
367 DatabaseRequestHandler():
370 virtual void requestNodeFile(const std::string& fileName, osg::NodePath& nodePath, float priority, const FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& databaseRequest, const osg::Referenced* options=0) = 0;
373 virtual ~DatabaseRequestHandler() {}
376 /** Set the handler for database requests.*/
377 void setDatabaseRequestHandler(DatabaseRequestHandler* handler) { _databaseRequestHandler = handler; }
379 /** Get the handler for database requests.*/
380 DatabaseRequestHandler* getDatabaseRequestHandler() { return _databaseRequestHandler.get(); }
382 /** Get the const handler for database requests.*/
383 const DatabaseRequestHandler* getDatabaseRequestHandler() const { return _databaseRequestHandler.get(); }
386 /** Callback for managing image paging, such as generated by PagedLOD nodes.*/
387 class ImageRequestHandler : public osg::Referenced
391 ImageRequestHandler():
394 virtual double getPreLoadTime() const = 0;
396 virtual osg::ref_ptr<osg::Image> readRefImageFile(const std::string& fileName, const osg::Referenced* options=0) = 0;
398 virtual void requestImageFile(const std::string& fileName,osg::Object* attachmentPoint, int attachmentIndex, double timeToMergeBy, const FrameStamp* framestamp, osg::ref_ptr<osg::Referenced>& imageRequest, const osg::Referenced* options=0) = 0;
401 virtual ~ImageRequestHandler() {}
404 /** Set the handler for image requests.*/
405 void setImageRequestHandler(ImageRequestHandler* handler) { _imageRequestHandler = handler; }
407 /** Get the handler for image requests.*/
408 ImageRequestHandler* getImageRequestHandler() { return _imageRequestHandler.get(); }
410 /** Get the const handler for image requests.*/
411 const ImageRequestHandler* getImageRequestHandler() const { return _imageRequestHandler.get(); }
417 VisitorType _visitorType;
418 unsigned int _traversalNumber;
420 ref_ptr<FrameStamp> _frameStamp;
422 TraversalMode _traversalMode;
423 Node::NodeMask _traversalMask;
424 Node::NodeMask _nodeMaskOverride;
428 ref_ptr<DatabaseRequestHandler> _databaseRequestHandler;
429 ref_ptr<ImageRequestHandler> _imageRequestHandler;
431 osg::ref_ptr<ValueMap> _valueMap;
432 osg::ref_ptr<ValueStack> _valueStack;
436/** Convenience functor for assisting visiting of arrays of osg::Node's.*/
441 NodeAcceptOp(NodeVisitor& nv):_nv(nv) {}
442 NodeAcceptOp(const NodeAcceptOp& naop):_nv(naop._nv) {}
444 void operator () (Node* node) { node->accept(_nv); }
445 void operator () (ref_ptr<Node> node) { node->accept(_nv); }
449 NodeAcceptOp& operator = (const NodeAcceptOp&) { return *this; }
460 PushPopObject(NodeVisitor* nv, const Referenced* key, Object* value):
466 _valueStack = nv->getOrCreateValueStack();
468 _valueStack->push(_key, value);
472 PushPopObject(ValueStack* valueStack, const Referenced* key, Object* value):
473 _valueStack(valueStack),
476 if (_valueStack && key)
479 _valueStack->push(_key, value);
483 inline ~PushPopObject()
485 if (_valueStack) _valueStack->pop(_key);
489 ValueStack* _valueStack;
490 const Referenced* _key;
499 PushPopValue(NodeVisitor* nv, const Referenced* key, const T& value):
505 _valueStack = nv->getOrCreateValueStack();
507 _valueStack->push(_key, value);
512 PushPopValue(ValueStack* valueStack, const Referenced* key, const T& value):
513 _valueStack(valueStack),
516 if (_valueStack && key)
519 _valueStack->push(_key, value);
523 inline ~PushPopValue()
525 if (_valueStack) _valueStack->pop(_key);
529 ValueStack* _valueStack;
530 const Referenced* _key;
534inline ValueStack* getOrCreateUserObjectOfType<NodeVisitor,ValueStack>(NodeVisitor* nv)
536 return nv->getOrCreateValueStack();
540inline ValueMap* getOrCreateUserObjectOfType<NodeVisitor,ValueMap>(NodeVisitor* nv)
542 return nv->getOrCreateValueMap();