123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
- *
- * This library is open source and may be redistributed and/or modified under
- * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
- * (at your option) any later version. The full license is in LICENSE file
- * included with this distribution, and on the openscenegraph.org website.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * OpenSceneGraph Public License for more details.
- */
- #ifndef OSG_NODEVISITOR
- #define OSG_NODEVISITOR 1
- #include <osg/Node>
- #include <osg/Matrix>
- #include <osg/FrameStamp>
- #include <osg/ValueMap>
- #include <osg/ValueStack>
- namespace osgUtil { class UpdateVisitor; class CullVisitor; class IntersectionVisitor; }
- namespace osgGA { class EventVisitor; }
- namespace osg {
- class Billboard;
- class ClearNode;
- class ClipNode;
- class CoordinateSystemNode;
- class Geode;
- class Group;
- class LightSource;
- class LOD;
- class MatrixTransform;
- class OccluderNode;
- class OcclusionQueryNode;
- class PagedLOD;
- class PositionAttitudeTransform;
- class AutoTransform;
- class MultiViewAutoTransform;
- class Projection;
- class ProxyNode;
- class Sequence;
- class Switch;
- class TexGenNode;
- class Transform;
- class Camera;
- class CameraView;
- class Drawable;
- class Geometry;
- class CullStack;
- const unsigned int UNINITIALIZED_FRAME_NUMBER=0xffffffff;
- #define META_NodeVisitor(library, name) \
- virtual const char* libraryName() const { return #library; }\
- virtual const char* className() const { return #name; }
- /** Visitor for type safe operations on osg::Nodes.
- Based on GOF's Visitor pattern. The NodeVisitor
- is useful for developing type safe operations to nodes
- in the scene graph (as per Visitor pattern), and adds to this
- support for optional scene graph traversal to allow
- operations to be applied to whole scenes at once. The Visitor
- pattern uses a technique of double dispatch as a mechanism to
- call the appropriate apply(..) method of the NodeVisitor. To
- use this feature one must use the Node::accept(NodeVisitor) which
- is extended in each Node subclass, rather than the NodeVisitor
- apply directly. So use root->accept(myVisitor); instead of
- myVisitor.apply(*root). The later method will bypass the double
- dispatch and the appropriate NodeVisitor::apply(..) method will
- not be called. */
- class OSG_EXPORT NodeVisitor : public virtual Object
- {
- public:
- enum TraversalMode
- {
- TRAVERSE_NONE,
- TRAVERSE_PARENTS,
- TRAVERSE_ALL_CHILDREN,
- TRAVERSE_ACTIVE_CHILDREN
- };
- enum VisitorType
- {
- NODE_VISITOR = 0,
- UPDATE_VISITOR,
- EVENT_VISITOR,
- COLLECT_OCCLUDER_VISITOR,
- CULL_VISITOR,
- INTERSECTION_VISITOR
- };
- NodeVisitor(TraversalMode tm=TRAVERSE_NONE);
- NodeVisitor(VisitorType type,TraversalMode tm=TRAVERSE_NONE);
- NodeVisitor(const NodeVisitor& nv, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
- virtual ~NodeVisitor();
- META_Object(osg, NodeVisitor)
- /** Convert 'this' into a NodeVisitor pointer if Object is a NodeVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<NodeVisitor*>(this).*/
- virtual NodeVisitor* asNodeVisitor() { return this; }
- /** convert 'const this' into a const NodeVisitor pointer if Object is a NodeVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const NodeVisitor*>(this).*/
- virtual const NodeVisitor* asNodeVisitor() const { return this; }
- /** Convert 'this' into a osgUtil::UpdateVisitor pointer if Object is a osgUtil::UpdateVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<osgUtil::UpdateVisitor*>(this).*/
- virtual osgUtil::UpdateVisitor* asUpdateVisitor() { return 0; }
- /** convert 'const this' into a const osgUtil::UpdateVisitor pointer if Object is a osgUtil::UpdateVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const osgUtil::UpdateVisitor*>(this).*/
- virtual const osgUtil::UpdateVisitor* asUpdateVisitor() const { return 0; }
- /** Convert 'this' into a osgUtil::CullVisitor pointer if Object is a osgUtil::CullVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<osgUtil::CullVisitor*>(this).*/
- virtual osgUtil::CullVisitor* asCullVisitor() { return 0; }
- /** convert 'const this' into a const osgUtil::CullVisitor pointer if Object is a osgUtil::CullVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const osgUtil::CullVisitor*>(this).*/
- virtual const osgUtil::CullVisitor* asCullVisitor() const { return 0; }
- /** Convert 'this' into a osgGA::EventVisitor pointer if Object is a osgGA::EventVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<osgGA::EventVisitor*>(this).*/
- virtual osgGA::EventVisitor* asEventVisitor() { return 0; }
- /** convert 'const this' into a const osgGA::EventVisitor pointer if Object is a osgGA::EventVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const osgGA::EventVisitor*>(this).*/
- virtual const osgGA::EventVisitor* asEventVisitor() const { return 0; }
- /** Convert 'this' into a osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<osgUtil::IntersectionVisitor*>(this).*/
- virtual osgUtil::IntersectionVisitor* asIntersectionVisitor() { return 0; }
- /** convert 'const this' into a const osgUtil::IntersectionVisitor pointer if Object is a IntersectionVisitor, otherwise return 0.
- * Equivalent to dynamic_cast<const osgUtil::IntersectionVisitor*>(this).*/
- virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return 0; }
- /** Convert 'this' into a osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0.
- * Equivalent to dynamic_cast<osg::CullStack*>(this).*/
- virtual osg::CullStack* asCullStack() { return 0; }
- /** convert 'const this' into a const osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0.
- * Equivalent to dynamic_cast<const osg::CullStack*>(this).*/
- virtual const osg::CullStack* asCullStack() const { return 0; }
- /** Method to call to reset visitor. Useful if your visitor accumulates
- state during a traversal, and you plan to reuse the visitor.
- To flush that state for the next traversal: call reset() prior
- to each traversal.*/
- virtual void reset() {}
- /** Set the VisitorType, used to distinguish different visitors during
- * traversal of the scene, typically used in the Node::traverse() method
- * to select which behaviour to use for different types of traversal/visitors.*/
- inline void setVisitorType(VisitorType type) { _visitorType = type; }
- /** Get the VisitorType.*/
- inline VisitorType getVisitorType() const { return _visitorType; }
- /** Set the traversal number. Typically used to denote the frame count.*/
- inline void setTraversalNumber(unsigned int fn) { _traversalNumber = fn; }
- /** Get the traversal number. Typically used to denote the frame count.*/
- inline unsigned int getTraversalNumber() const { return _traversalNumber; }
- /** Set the FrameStamp that this traversal is associated with.*/
- inline void setFrameStamp(FrameStamp* fs) { _frameStamp = fs; }
- /** Get the FrameStamp that this traversal is associated with.*/
- inline const FrameStamp* getFrameStamp() const { return _frameStamp.get(); }
- /** Set the TraversalMask of this NodeVisitor.
- * The TraversalMask is used by the NodeVisitor::validNodeMask() method
- * to determine whether to operate on a node and its subgraph.
- * validNodeMask() is called automatically in the Node::accept() method before
- * any call to NodeVisitor::apply(), apply() is only ever called if validNodeMask
- * returns true. Note, if NodeVisitor::_traversalMask is 0 then all operations
- * will be switched off for all nodes. Whereas setting both _traversalMask and
- * _nodeMaskOverride to 0xffffffff will allow a visitor to work on all nodes
- * regardless of their own Node::_nodeMask state.*/
- inline void setTraversalMask(Node::NodeMask mask) { _traversalMask = mask; }
- /** Get the TraversalMask.*/
- inline Node::NodeMask getTraversalMask() const { return _traversalMask; }
- /** Set the NodeMaskOverride mask.
- * Used in validNodeMask() to determine whether to operate on a node or its
- * subgraph, by OR'ing NodeVisitor::_nodeMaskOverride with the Node's own Node::_nodeMask.
- * Typically used to force on nodes which may have
- * been switched off by their own Node::_nodeMask.*/
- inline void setNodeMaskOverride(Node::NodeMask mask) { _nodeMaskOverride = mask; }
- /** Get the NodeMaskOverride mask.*/
- inline Node::NodeMask getNodeMaskOverride() const { return _nodeMaskOverride; }
- /** Method to called by Node and its subclass' Node::accept() method, if the result is true
- * it is used to cull operations of nodes and their subgraphs.
- * Return true if the result of a bit wise and of the NodeVisitor::_traversalMask
- * with the bit or between NodeVistor::_nodeMaskOverride and the Node::_nodeMask.
- * default values for _traversalMask is 0xffffffff, _nodeMaskOverride is 0x0,
- * and osg::Node::_nodeMask is 0xffffffff. */
- inline bool validNodeMask(const osg::Node& node) const
- {
- return (getTraversalMask() & (getNodeMaskOverride() | node.getNodeMask()))!=0;
- }
- /** Set the traversal mode for Node::traverse() to use when
- deciding which children of a node to traverse. If a
- NodeVisitor has been attached via setTraverseVisitor()
- and the new mode is not TRAVERSE_VISITOR then the attached
- visitor is detached. Default mode is TRAVERSE_NONE.*/
- inline void setTraversalMode(TraversalMode mode) { _traversalMode = mode; }
- /** Get the traversal mode.*/
- inline TraversalMode getTraversalMode() const { return _traversalMode; }
- /** Set the ValueMap used to store Values that can be reused over a series of traversals. */
- inline void setValueMap(ValueMap* ps) { _valueMap = ps; }
- /** Get the ValueMap. */
- inline ValueMap* getValueMap() { return _valueMap.get(); }
- /** Get the ValueMap. */
- inline const ValueMap* getValueMap() const { return _valueMap.get(); }
- /** Get the ValueMap. */
- inline ValueMap* getOrCreateValueMap()
- {
- if (!_valueMap) _valueMap = new ValueMap;
- return _valueMap.get();
- }
- /** Set the ValueStack used to stack Values during traversal. */
- inline void setValueStack(ValueStack* ps) { _valueStack = ps; }
- /** Get the ValueStack. */
- inline ValueStack* getValueStack() { return _valueStack.get(); }
- /** Get the const ValueStack. */
- inline const ValueStack* getValueStack() const { return _valueStack.get(); }
- /** Get the ValueStack. */
- inline ValueStack* getOrCreateValueStack()
- {
- if (!_valueStack) _valueStack = new ValueStack;
- return _valueStack.get();
- }
- /** Method for handling traversal of a nodes.
- If you intend to use the visitor for actively traversing
- the scene graph then make sure the accept() methods call
- this method unless they handle traversal directly.*/
- inline void traverse(Node& node)
- {
- if (_traversalMode==TRAVERSE_PARENTS) node.ascend(*this);
- else if (_traversalMode!=TRAVERSE_NONE) node.traverse(*this);
- }
- /** Method called by osg::Node::accept() method before
- * a call to the NodeVisitor::apply(..). The back of the list will,
- * therefore, be the current node being visited inside the apply(..),
- * and the rest of the list will be the parental sequence of nodes
- * from the top most node applied down the graph to the current node.
- * Note, the user does not typically call pushNodeOnPath() as it
- * will be called automatically by the Node::accept() method.*/
- inline void pushOntoNodePath(Node* node) { if (_traversalMode!=TRAVERSE_PARENTS) _nodePath.push_back(node); else _nodePath.insert(_nodePath.begin(),node); }
- /** Method called by osg::Node::accept() method after
- * a call to NodeVisitor::apply(..).
- * Note, the user does not typically call popFromNodePath() as it
- * will be called automatically by the Node::accept() method.*/
- inline void popFromNodePath() { if (_traversalMode!=TRAVERSE_PARENTS) _nodePath.pop_back(); else _nodePath.erase(_nodePath.begin()); }
- /** Get the non const NodePath from the top most node applied down
- * to the current Node being visited.*/
- NodePath& getNodePath() { return _nodePath; }
- /** Get the const NodePath from the top most node applied down
- * to the current Node being visited.*/
- const NodePath& getNodePath() const { return _nodePath; }
- /** Get the eye point in local coordinates.
- * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.*/
- virtual osg::Vec3 getEyePoint() const { return Vec3(0.0f,0.0f,0.0f); }
- /** Get the view point in local coordinates.
- * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.*/
- virtual osg::Vec3 getViewPoint() const { return getEyePoint(); }
- /** Get the distance from a point to the eye point, distance value in local coordinate system.
- * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
- * If the getDistanceFromEyePoint(pos) is not implemented then a default value of 0.0 is returned.*/
- virtual float getDistanceToEyePoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
- /** Get the distance of a point from the eye point, distance value in the eye coordinate system.
- * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
- * If the getDistanceFromEyePoint(pos) is not implemented than a default value of 0.0 is returned.*/
- virtual float getDistanceFromEyePoint(const Vec3& /*pos*/, bool /*useLODScale*/) const { return 0.0f; }
- /** Get the distance from a point to the view point, distance value in local coordinate system.
- * Note, not all NodeVisitor implement this method, it is mainly cull visitors which will implement.
- * 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& geometry);
- virtual void apply(Node& node);
- virtual void apply(Geode& node);
- virtual void apply(Billboard& node);
- virtual void apply(Group& node);
- virtual void apply(ProxyNode& node);
- virtual void apply(Projection& node);
- virtual void apply(CoordinateSystemNode& node);
- virtual void apply(ClipNode& node);
- virtual void apply(TexGenNode& node);
- virtual void apply(LightSource& node);
- virtual void apply(Transform& node);
- virtual void apply(Camera& node);
- virtual void apply(CameraView& node);
- virtual void apply(MatrixTransform& node);
- virtual void apply(PositionAttitudeTransform& node);
- virtual void apply(AutoTransform& node);
- virtual void apply(Switch& node);
- virtual void apply(Sequence& node);
- virtual void apply(LOD& node);
- virtual void apply(PagedLOD& node);
- virtual void apply(ClearNode& node);
- virtual void apply(OccluderNode& node);
- virtual void apply(OcclusionQueryNode& node);
- /** Callback for managing database paging, such as generated by PagedLOD nodes.*/
- class DatabaseRequestHandler : public osg::Referenced
- {
- public:
- DatabaseRequestHandler():
- Referenced(true) {}
- 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;
- protected:
- virtual ~DatabaseRequestHandler() {}
- };
- /** Set the handler for database requests.*/
- void setDatabaseRequestHandler(DatabaseRequestHandler* handler) { _databaseRequestHandler = handler; }
- /** Get the handler for database requests.*/
- DatabaseRequestHandler* getDatabaseRequestHandler() { return _databaseRequestHandler.get(); }
- /** Get the const handler for database requests.*/
- const DatabaseRequestHandler* getDatabaseRequestHandler() const { return _databaseRequestHandler.get(); }
- /** Callback for managing image paging, such as generated by PagedLOD nodes.*/
- class ImageRequestHandler : public osg::Referenced
- {
- public:
- ImageRequestHandler():
- Referenced(true) {}
- virtual double getPreLoadTime() const = 0;
- virtual osg::ref_ptr<osg::Image> readRefImageFile(const std::string& fileName, const osg::Referenced* options=0) = 0;
- 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;
- protected:
- virtual ~ImageRequestHandler() {}
- };
- /** Set the handler for image requests.*/
- void setImageRequestHandler(ImageRequestHandler* handler) { _imageRequestHandler = handler; }
- /** Get the handler for image requests.*/
- ImageRequestHandler* getImageRequestHandler() { return _imageRequestHandler.get(); }
- /** Get the const handler for image requests.*/
- const ImageRequestHandler* getImageRequestHandler() const { return _imageRequestHandler.get(); }
- protected:
- VisitorType _visitorType;
- unsigned int _traversalNumber;
- ref_ptr<FrameStamp> _frameStamp;
- TraversalMode _traversalMode;
- Node::NodeMask _traversalMask;
- Node::NodeMask _nodeMaskOverride;
- NodePath _nodePath;
- ref_ptr<DatabaseRequestHandler> _databaseRequestHandler;
- ref_ptr<ImageRequestHandler> _imageRequestHandler;
- osg::ref_ptr<ValueMap> _valueMap;
- osg::ref_ptr<ValueStack> _valueStack;
- };
- /** Convenience functor for assisting visiting of arrays of osg::Node's.*/
- class NodeAcceptOp
- {
- public:
- NodeAcceptOp(NodeVisitor& nv):_nv(nv) {}
- NodeAcceptOp(const NodeAcceptOp& naop):_nv(naop._nv) {}
- void operator () (Node* node) { node->accept(_nv); }
- void operator () (ref_ptr<Node> node) { node->accept(_nv); }
- protected:
- NodeAcceptOp& operator = (const NodeAcceptOp&) { return *this; }
- NodeVisitor& _nv;
- };
- class PushPopObject
- {
- public:
- PushPopObject(NodeVisitor* nv, const Referenced* key, Object* value):
- _valueStack(0),
- _key(0)
- {
- if (key)
- {
- _valueStack = nv->getOrCreateValueStack();
- _key = key;
- _valueStack->push(_key, value);
- }
- }
- PushPopObject(ValueStack* valueStack, const Referenced* key, Object* value):
- _valueStack(valueStack),
- _key(0)
- {
- if (_valueStack && key)
- {
- _key = key;
- _valueStack->push(_key, value);
- }
- }
- inline ~PushPopObject()
- {
- if (_valueStack) _valueStack->pop(_key);
- }
- protected:
- ValueStack* _valueStack;
- const Referenced* _key;
- };
- class PushPopValue
- {
- public:
- template<typename T>
- PushPopValue(NodeVisitor* nv, const Referenced* key, const T& value):
- _valueStack(0),
- _key(0)
- {
- if (key)
- {
- _valueStack = nv->getOrCreateValueStack();
- _key = key;
- _valueStack->push(_key, value);
- }
- }
- template<typename T>
- PushPopValue(ValueStack* valueStack, const Referenced* key, const T& value):
- _valueStack(valueStack),
- _key(0)
- {
- if (_valueStack && key)
- {
- _key = key;
- _valueStack->push(_key, value);
- }
- }
- inline ~PushPopValue()
- {
- if (_valueStack) _valueStack->pop(_key);
- }
- protected:
- ValueStack* _valueStack;
- const Referenced* _key;
- };
- template<>
- inline ValueStack* getOrCreateUserObjectOfType<NodeVisitor,ValueStack>(NodeVisitor* nv)
- {
- return nv->getOrCreateValueStack();
- }
- template<>
- inline ValueMap* getOrCreateUserObjectOfType<NodeVisitor,ValueMap>(NodeVisitor* nv)
- {
- return nv->getOrCreateValueMap();
- }
- }
- #endif
|