openscenegraph
NodeVisitor
Go to the documentation of this file.
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
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.
7 *
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.
12*/
13
14#ifndef OSG_NODEVISITOR
15#define OSG_NODEVISITOR 1
16
17#include <osg/Node>
18#include <osg/Matrix>
19#include <osg/FrameStamp>
20
21#include <osg/ValueMap>
22#include <osg/ValueStack>
23
24
25namespace osgUtil { class UpdateVisitor; class CullVisitor; class IntersectionVisitor; }
26namespace osgGA { class EventVisitor; }
27
28namespace osg {
29
30class Billboard;
31class ClearNode;
32class ClipNode;
33class CoordinateSystemNode;
34class Geode;
35class Group;
36class LightSource;
37class LOD;
38class MatrixTransform;
39class OccluderNode;
40class OcclusionQueryNode;
41class PagedLOD;
42class PositionAttitudeTransform;
43class AutoTransform;
44class MultiViewAutoTransform;
45class Projection;
46class ProxyNode;
47class Sequence;
48class Switch;
49class TexGenNode;
50class Transform;
51class Camera;
52class CameraView;
53class Drawable;
54class Geometry;
55class CullStack;
56
57
58
59
60
61const unsigned int UNINITIALIZED_FRAME_NUMBER=0xffffffff;
62
63#define META_NodeVisitor(library, name) \
64 virtual const char* libraryName() const { return #library; }\
65 virtual const char* className() const { return #name; }
66
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
80 not be called. */
81class OSG_EXPORT NodeVisitor : public virtual Object
82{
83 public:
84
85 enum TraversalMode
86 {
87 TRAVERSE_NONE,
88 TRAVERSE_PARENTS,
89 TRAVERSE_ALL_CHILDREN,
90 TRAVERSE_ACTIVE_CHILDREN
91 };
92
93 enum VisitorType
94 {
95 NODE_VISITOR = 0,
96 UPDATE_VISITOR,
97 EVENT_VISITOR,
98 COLLECT_OCCLUDER_VISITOR,
99 CULL_VISITOR,
100 INTERSECTION_VISITOR
101 };
102
103 NodeVisitor(TraversalMode tm=TRAVERSE_NONE);
104
105 NodeVisitor(VisitorType type,TraversalMode tm=TRAVERSE_NONE);
106
107 NodeVisitor(const NodeVisitor& nv, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
108
109 virtual ~NodeVisitor();
110
111 META_Object(osg, NodeVisitor)
112
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; }
116
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; }
120
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; }
124
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; }
128
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; }
132
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; }
136
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; }
140
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; }
144
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; }
148
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; }
152
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; }
156
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; }
160
161
162
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
166 to each traversal.*/
167 virtual void reset() {}
168
169
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; }
174
175 /** Get the VisitorType.*/
176 inline VisitorType getVisitorType() const { return _visitorType; }
177
178 /** Set the traversal number. Typically used to denote the frame count.*/
179 inline void setTraversalNumber(unsigned int fn) { _traversalNumber = fn; }
180
181 /** Get the traversal number. Typically used to denote the frame count.*/
182 inline unsigned int getTraversalNumber() const { return _traversalNumber; }
183
184 /** Set the FrameStamp that this traversal is associated with.*/
185 inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
186
187 /** Get the FrameStamp that this traversal is associated with.*/
188 inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
189
190
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; }
201
202 /** Get the TraversalMask.*/
203 inline Node::NodeMask getTraversalMask() const { return _traversalMask; }
204
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; }
211
212 /** Get the NodeMaskOverride mask.*/
213 inline Node::NodeMask getNodeMaskOverride() const { return _nodeMaskOverride; }
214
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
222 {
223 return (getTraversalMask() & (getNodeMaskOverride() | node.getNodeMask()))!=0;
224 }
225
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; }
232
233 /** Get the traversal mode.*/
234 inline TraversalMode getTraversalMode() const { return _traversalMode; }
235
236
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; }
239
240 /** Get the ValueMap. */
241 inline ValueMap* getValueMap() { return _valueMap.get(); }
242
243 /** Get the ValueMap. */
244 inline const ValueMap* getValueMap() const { return _valueMap.get(); }
245
246 /** Get the ValueMap. */
247 inline ValueMap* getOrCreateValueMap()
248 {
249 if (!_valueMap) _valueMap = new ValueMap;
250 return _valueMap.get();
251 }
252
253 /** Set the ValueStack used to stack Values during traversal. */
254 inline void setValueStack(ValueStack* ps) { _valueStack = ps; }
255
256 /** Get the ValueStack. */
257 inline ValueStack* getValueStack() { return _valueStack.get(); }
258
259 /** Get the const ValueStack. */
260 inline const ValueStack* getValueStack() const { return _valueStack.get(); }
261
262 /** Get the ValueStack. */
263 inline ValueStack* getOrCreateValueStack()
264 {
265 if (!_valueStack) _valueStack = new ValueStack;
266 return _valueStack.get();
267 }
268
269
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)
275 {
276 if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this);
277 else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this);
278 }
279
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); }
288
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()); }
294
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; }
298
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; }
302
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); }
306
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(); }
310
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; }
315
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; }
320
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; }
325
326 virtual void apply(Drawable& drawable);
327 virtual void apply(Geometry& geometry);
328
329 virtual void apply(Node& node);
330
331 virtual void apply(Geode& node);
332 virtual void apply(Billboard& node);
333
334 virtual void apply(Group& node);
335
336 virtual void apply(ProxyNode& node);
337
338 virtual void apply(Projection& node);
339
340 virtual void apply(CoordinateSystemNode& node);
341
342 virtual void apply(ClipNode& node);
343 virtual void apply(TexGenNode& node);
344 virtual void apply(LightSource& node);
345
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);
352
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);
360
361
362 /** Callback for managing database paging, such as generated by PagedLOD nodes.*/
363 class DatabaseRequestHandler : public osg::Referenced
364 {
365 public:
366
367 DatabaseRequestHandler():
368 Referenced(true) {}
369
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;
371
372 protected:
373 virtual ~DatabaseRequestHandler() {}
374 };
375
376 /** Set the handler for database requests.*/
377 void setDatabaseRequestHandler(DatabaseRequestHandler* handler) { _databaseRequestHandler = handler; }
378
379 /** Get the handler for database requests.*/
380 DatabaseRequestHandler* getDatabaseRequestHandler() { return _databaseRequestHandler.get(); }
381
382 /** Get the const handler for database requests.*/
383 const DatabaseRequestHandler* getDatabaseRequestHandler() const { return _databaseRequestHandler.get(); }
384
385
386 /** Callback for managing image paging, such as generated by PagedLOD nodes.*/
387 class ImageRequestHandler : public osg::Referenced
388 {
389 public:
390
391 ImageRequestHandler():
392 Referenced(true) {}
393
394 virtual double getPreLoadTime() const = 0;
395
396 virtual osg::ref_ptr<osg::Image> readRefImageFile(const std::string& fileName, const osg::Referenced* options=0) = 0;
397
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;
399
400 protected:
401 virtual ~ImageRequestHandler() {}
402 };
403
404 /** Set the handler for image requests.*/
405 void setImageRequestHandler(ImageRequestHandler* handler) { _imageRequestHandler = handler; }
406
407 /** Get the handler for image requests.*/
408 ImageRequestHandler* getImageRequestHandler() { return _imageRequestHandler.get(); }
409
410 /** Get the const handler for image requests.*/
411 const ImageRequestHandler* getImageRequestHandler() const { return _imageRequestHandler.get(); }
412
413
414
415 protected:
416
417 VisitorType _visitorType;
418 unsigned int _traversalNumber;
419
420 ref_ptr<FrameStamp> _frameStamp;
421
422 TraversalMode _traversalMode;
423 Node::NodeMask _traversalMask;
424 Node::NodeMask _nodeMaskOverride;
425
426 NodePath _nodePath;
427
428 ref_ptr<DatabaseRequestHandler> _databaseRequestHandler;
429 ref_ptr<ImageRequestHandler> _imageRequestHandler;
430
431 osg::ref_ptr<ValueMap> _valueMap;
432 osg::ref_ptr<ValueStack> _valueStack;
433};
434
435
436/** Convenience functor for assisting visiting of arrays of osg::Node's.*/
437class NodeAcceptOp
438{
439 public:
440
441 NodeAcceptOp(NodeVisitor& nv):_nv(nv) {}
442 NodeAcceptOp(const NodeAcceptOp& naop):_nv(naop._nv) {}
443
444 void operator () (Node* node) { node->accept(_nv); }
445 void operator () (ref_ptr<Node> node) { node->accept(_nv); }
446
447 protected:
448
449 NodeAcceptOp& operator = (const NodeAcceptOp&) { return *this; }
450
451 NodeVisitor& _nv;
452};
453
454
455class PushPopObject
456{
457public:
458
459
460 PushPopObject(NodeVisitor* nv, const Referenced* key, Object* value):
461 _valueStack(0),
462 _key(0)
463 {
464 if (key)
465 {
466 _valueStack = nv->getOrCreateValueStack();
467 _key = key;
468 _valueStack->push(_key, value);
469 }
470 }
471
472 PushPopObject(ValueStack* valueStack, const Referenced* key, Object* value):
473 _valueStack(valueStack),
474 _key(0)
475 {
476 if (_valueStack && key)
477 {
478 _key = key;
479 _valueStack->push(_key, value);
480 }
481 }
482
483 inline ~PushPopObject()
484 {
485 if (_valueStack) _valueStack->pop(_key);
486 }
487
488protected:
489 ValueStack* _valueStack;
490 const Referenced* _key;
491};
492
493class PushPopValue
494{
495public:
496
497
498 template<typename T>
499 PushPopValue(NodeVisitor* nv, const Referenced* key, const T& value):
500 _valueStack(0),
501 _key(0)
502 {
503 if (key)
504 {
505 _valueStack = nv->getOrCreateValueStack();
506 _key = key;
507 _valueStack->push(_key, value);
508 }
509 }
510
511 template<typename T>
512 PushPopValue(ValueStack* valueStack, const Referenced* key, const T& value):
513 _valueStack(valueStack),
514 _key(0)
515 {
516 if (_valueStack && key)
517 {
518 _key = key;
519 _valueStack->push(_key, value);
520 }
521 }
522
523 inline ~PushPopValue()
524 {
525 if (_valueStack) _valueStack->pop(_key);
526 }
527
528protected:
529 ValueStack* _valueStack;
530 const Referenced* _key;
531};
532
533template<>
534inline ValueStack* getOrCreateUserObjectOfType<NodeVisitor,ValueStack>(NodeVisitor* nv)
535{
536 return nv->getOrCreateValueStack();
537}
538
539template<>
540inline ValueMap* getOrCreateUserObjectOfType<NodeVisitor,ValueMap>(NodeVisitor* nv)
541{
542 return nv->getOrCreateValueMap();
543}
544
545
546}
547
548#endif