| 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 | |
|---|
| 15 | #ifndef OSG_NODE |
|---|
| 16 | #define OSG_NODE 1 |
|---|
| 17 | |
|---|
| 18 | #include <osg/Object> |
|---|
| 19 | #include <osg/StateSet> |
|---|
| 20 | #include <osg/BoundingSphere> |
|---|
| 21 | #include <osg/NodeCallback> |
|---|
| 22 | |
|---|
| 23 | #include <string> |
|---|
| 24 | #include <vector> |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | // forward declare osgTerrrain::Terrain to enable declaration of asTerrain() method. |
|---|
| 28 | namespace osgTerrain { |
|---|
| 29 | class Terrain; |
|---|
| 30 | } |
|---|
| 31 | |
|---|
| 32 | namespace osg { |
|---|
| 33 | |
|---|
| 34 | // forcing declare classes to enable declaration of as*() methods. |
|---|
| 35 | class NodeVisitor; |
|---|
| 36 | class Group; |
|---|
| 37 | class Transform; |
|---|
| 38 | class Node; |
|---|
| 39 | class Switch; |
|---|
| 40 | class Geode; |
|---|
| 41 | class Camera; |
|---|
| 42 | |
|---|
| 43 | /** A vector of Nodes pointers which is used to describe the path from a root node to a descendant.*/ |
|---|
| 44 | typedef std::vector< Node* > NodePath; |
|---|
| 45 | |
|---|
| 46 | /** A vector of NodePath, typically used to describe all the paths from a node to the potential root nodes it has.*/ |
|---|
| 47 | typedef std::vector< NodePath > NodePathList; |
|---|
| 48 | |
|---|
| 49 | /** A vector of NodePath, typically used to describe all the paths from a node to the potential root nodes it has.*/ |
|---|
| 50 | typedef std::vector< Matrix > MatrixList; |
|---|
| 51 | |
|---|
| 52 | /** META_Node macro define the standard clone, isSameKindAs, className |
|---|
| 53 | * and accept methods. Use when subclassing from Node to make it |
|---|
| 54 | * more convenient to define the required pure virtual methods.*/ |
|---|
| 55 | #define META_Node(library,name) \ |
|---|
| 56 | virtual osg::Object* cloneType() const { return new name (); } \ |
|---|
| 57 | virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \ |
|---|
| 58 | virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \ |
|---|
| 59 | virtual const char* className() const { return #name; } \ |
|---|
| 60 | virtual const char* libraryName() const { return #library; } \ |
|---|
| 61 | virtual void accept(osg::NodeVisitor& nv) { if (nv.validNodeMask(*this)) { nv.pushOntoNodePath(this); nv.apply(*this); nv.popFromNodePath(); } } \ |
|---|
| 62 | |
|---|
| 63 | |
|---|
| 64 | /** Base class for all internal nodes in the scene graph. |
|---|
| 65 | Provides interface for most common node operations (Composite Pattern). |
|---|
| 66 | */ |
|---|
| 67 | class OSG_EXPORT Node : public Object |
|---|
| 68 | { |
|---|
| 69 | public: |
|---|
| 70 | |
|---|
| 71 | /** Construct a node. |
|---|
| 72 | Initialize the parent list to empty, node name to "" and |
|---|
| 73 | bounding sphere dirty flag to true.*/ |
|---|
| 74 | Node(); |
|---|
| 75 | |
|---|
| 76 | /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|---|
| 77 | Node(const Node&,const CopyOp& copyop=CopyOp::SHALLOW_COPY); |
|---|
| 78 | |
|---|
| 79 | /** clone an object of the same type as the node.*/ |
|---|
| 80 | virtual Object* cloneType() const { return new Node(); } |
|---|
| 81 | |
|---|
| 82 | /** return a clone of a node, with Object* return type.*/ |
|---|
| 83 | virtual Object* clone(const CopyOp& copyop) const { return new Node(*this,copyop); } |
|---|
| 84 | |
|---|
| 85 | /** return true if this and obj are of the same kind of object.*/ |
|---|
| 86 | virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Node*>(obj)!=NULL; } |
|---|
| 87 | |
|---|
| 88 | /** return the name of the node's library.*/ |
|---|
| 89 | virtual const char* libraryName() const { return "osg"; } |
|---|
| 90 | |
|---|
| 91 | /** return the name of the node's class type.*/ |
|---|
| 92 | virtual const char* className() const { return "Node"; } |
|---|
| 93 | |
|---|
| 94 | /** convert 'this' into a Group pointer if Node is a Group, otherwise return 0. |
|---|
| 95 | * Equivalent to dynamic_cast<Group*>(this).*/ |
|---|
| 96 | virtual Group* asGroup() { return 0; } |
|---|
| 97 | /** convert 'const this' into a const Group pointer if Node is a Group, otherwise return 0. |
|---|
| 98 | * Equivalent to dynamic_cast<const Group*>(this).*/ |
|---|
| 99 | virtual const Group* asGroup() const { return 0; } |
|---|
| 100 | |
|---|
| 101 | /** Convert 'this' into a Transform pointer if Node is a Transform, otherwise return 0. |
|---|
| 102 | * Equivalent to dynamic_cast<Transform*>(this).*/ |
|---|
| 103 | virtual Transform* asTransform() { return 0; } |
|---|
| 104 | |
|---|
| 105 | /** convert 'const this' into a const Transform pointer if Node is a Transform, otherwise return 0. |
|---|
| 106 | * Equivalent to dynamic_cast<const Transform*>(this).*/ |
|---|
| 107 | virtual const Transform* asTransform() const { return 0; } |
|---|
| 108 | |
|---|
| 109 | |
|---|
| 110 | /** Convert 'this' into a Camera pointer if Node is a Camera, otherwise return 0. |
|---|
| 111 | * Equivalent to dynamic_cast<Camera*>(this).*/ |
|---|
| 112 | virtual Camera* asCamera() { return 0; } |
|---|
| 113 | /** convert 'const this' into a const Camera pointer if Node is a Camera, otherwise return 0. |
|---|
| 114 | * Equivalent to dynamic_cast<const Camera*>(this).*/ |
|---|
| 115 | virtual const Camera* asCamera() const { return 0; } |
|---|
| 116 | |
|---|
| 117 | |
|---|
| 118 | /** Convert 'this' into a Switch pointer if Node is a Switch, otherwise return 0. |
|---|
| 119 | * Equivalent to dynamic_cast<Switch*>(this).*/ |
|---|
| 120 | virtual Switch* asSwitch() { return 0; } |
|---|
| 121 | |
|---|
| 122 | /** convert 'const this' into a const Switch pointer if Node is a Switch, otherwise return 0. |
|---|
| 123 | * Equivalent to dynamic_cast<const Switch*>(this).*/ |
|---|
| 124 | virtual const Switch* asSwitch() const { return 0; } |
|---|
| 125 | |
|---|
| 126 | /** Convert 'this' into a Geode pointer if Node is a Geode, otherwise return 0. |
|---|
| 127 | * Equivalent to dynamic_cast<Geode*>(this).*/ |
|---|
| 128 | virtual Geode* asGeode() { return 0; } |
|---|
| 129 | |
|---|
| 130 | /** convert 'const this' into a const Geode pointer if Node is a Geode, otherwise return 0. |
|---|
| 131 | * Equivalent to dynamic_cast<const Geode*>(this).*/ |
|---|
| 132 | virtual const Geode* asGeode() const { return 0; } |
|---|
| 133 | |
|---|
| 134 | /** Convert 'this' into a Transform pointer if Node is a Terrain, otherwise return 0. |
|---|
| 135 | * Equivalent to dynamic_cast<Terrrain*>(this).*/ |
|---|
| 136 | virtual osgTerrain::Terrain* asTerrain() { return 0; } |
|---|
| 137 | |
|---|
| 138 | /** convert 'const this' into a const Terrain pointer if Node is a Terrain, otherwise return 0. |
|---|
| 139 | * Equivalent to dynamic_cast<const Terrain*>(this).*/ |
|---|
| 140 | virtual const osgTerrain::Terrain* asTerrain() const { return 0; } |
|---|
| 141 | |
|---|
| 142 | |
|---|
| 143 | /** Visitor Pattern : calls the apply method of a NodeVisitor with this node's type.*/ |
|---|
| 144 | virtual void accept(NodeVisitor& nv); |
|---|
| 145 | /** Traverse upwards : calls parents' accept method with NodeVisitor.*/ |
|---|
| 146 | virtual void ascend(NodeVisitor& nv); |
|---|
| 147 | /** Traverse downwards : calls children's accept method with NodeVisitor.*/ |
|---|
| 148 | virtual void traverse(NodeVisitor& /*nv*/) {} |
|---|
| 149 | |
|---|
| 150 | /** A vector of osg::Group pointers which is used to store the parent(s) of node.*/ |
|---|
| 151 | typedef std::vector<Group*> ParentList; |
|---|
| 152 | |
|---|
| 153 | /** Get the parent list of node. */ |
|---|
| 154 | inline const ParentList& getParents() const { return _parents; } |
|---|
| 155 | |
|---|
| 156 | /** Get the a copy of parent list of node. A copy is returned to |
|---|
| 157 | * prevent modification of the parent list.*/ |
|---|
| 158 | inline ParentList getParents() { return _parents; } |
|---|
| 159 | |
|---|
| 160 | inline Group* getParent(unsigned int i) { return _parents[i]; } |
|---|
| 161 | |
|---|
| 162 | /** |
|---|
| 163 | * Get a single const parent of node. |
|---|
| 164 | * @param i index of the parent to get. |
|---|
| 165 | * @return the parent i. |
|---|
| 166 | */ |
|---|
| 167 | inline const Group* getParent(unsigned int i) const { return _parents[i]; } |
|---|
| 168 | |
|---|
| 169 | /** |
|---|
| 170 | * Get the number of parents of node. |
|---|
| 171 | * @return the number of parents of this node. |
|---|
| 172 | */ |
|---|
| 173 | inline unsigned int getNumParents() const { return static_cast<unsigned int>(_parents.size()); } |
|---|
| 174 | |
|---|
| 175 | /** Get the list of node paths parent paths. |
|---|
| 176 | * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specifed node. */ |
|---|
| 177 | NodePathList getParentalNodePaths(osg::Node* haltTraversalAtNode=0) const; |
|---|
| 178 | |
|---|
| 179 | /** Get the list of matrices that transform this node from local coordinates to world coordinates. |
|---|
| 180 | * The optional Node* haltTraversalAtNode allows the user to prevent traversal beyond a specifed node. */ |
|---|
| 181 | MatrixList getWorldMatrices(const osg::Node* haltTraversalAtNode=0) const; |
|---|
| 182 | |
|---|
| 183 | |
|---|
| 184 | /** Set update node callback, called during update traversal. */ |
|---|
| 185 | void setUpdateCallback(NodeCallback* nc); |
|---|
| 186 | |
|---|
| 187 | /** Get update node callback, called during update traversal. */ |
|---|
| 188 | inline NodeCallback* getUpdateCallback() { return _updateCallback.get(); } |
|---|
| 189 | |
|---|
| 190 | /** Get const update node callback, called during update traversal. */ |
|---|
| 191 | inline const NodeCallback* getUpdateCallback() const { return _updateCallback.get(); } |
|---|
| 192 | |
|---|
| 193 | /** Convenience method that sets the update callback of the node if it doesn't exist, or nest it into the existing one. */ |
|---|
| 194 | inline void addUpdateCallback(NodeCallback* nc) { |
|---|
| 195 | if (nc != NULL) { |
|---|
| 196 | if (_updateCallback.valid()) _updateCallback->addNestedCallback(nc); |
|---|
| 197 | else setUpdateCallback(nc); |
|---|
| 198 | } |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | /** Convenience method that removes a given callback from a node, even if that callback is nested. There is no error return in case the given callback is not found. */ |
|---|
| 202 | inline void removeUpdateCallback(NodeCallback* nc) { |
|---|
| 203 | if (nc != NULL && _updateCallback.valid()) { |
|---|
| 204 | if (_updateCallback == nc) setUpdateCallback(nc->getNestedCallback()); // replace the callback by the nested one |
|---|
| 205 | else _updateCallback->removeNestedCallback(nc); |
|---|
| 206 | } |
|---|
| 207 | } |
|---|
| 208 | |
|---|
| 209 | /** Get the number of Children of this node which require Update traversal, |
|---|
| 210 | * since they have an Update Callback attached to them or their children.*/ |
|---|
| 211 | inline unsigned int getNumChildrenRequiringUpdateTraversal() const { return _numChildrenRequiringUpdateTraversal; } |
|---|
| 212 | |
|---|
| 213 | |
|---|
| 214 | /** Set event node callback, called during event traversal. */ |
|---|
| 215 | void setEventCallback(NodeCallback* nc); |
|---|
| 216 | |
|---|
| 217 | /** Get event node callback, called during event traversal. */ |
|---|
| 218 | inline NodeCallback* getEventCallback() { return _eventCallback.get(); } |
|---|
| 219 | |
|---|
| 220 | /** Get const event node callback, called during event traversal. */ |
|---|
| 221 | inline const NodeCallback* getEventCallback() const { return _eventCallback.get(); } |
|---|
| 222 | |
|---|
| 223 | /** Convenience method that sets the event callback of the node if it doesn't exist, or nest it into the existing one. */ |
|---|
| 224 | inline void addEventCallback(NodeCallback* nc) { |
|---|
| 225 | if (nc != NULL) { |
|---|
| 226 | if (_eventCallback.valid()) _eventCallback->addNestedCallback(nc); |
|---|
| 227 | else setEventCallback(nc); |
|---|
| 228 | } |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | /** Convenience method that removes a given callback from a node, even if that callback is nested. There is no error return in case the given callback is not found. */ |
|---|
| 232 | inline void removeEventCallback(NodeCallback* nc) { |
|---|
| 233 | if (nc != NULL && _eventCallback.valid()) { |
|---|
| 234 | if (_eventCallback == nc) setEventCallback(nc->getNestedCallback()); // replace the callback by the nested one |
|---|
| 235 | else _eventCallback->removeNestedCallback(nc); |
|---|
| 236 | } |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | /** Get the number of Children of this node which require Event traversal, |
|---|
| 240 | * since they have an Event Callback attached to them or their children.*/ |
|---|
| 241 | inline unsigned int getNumChildrenRequiringEventTraversal() const { return _numChildrenRequiringEventTraversal; } |
|---|
| 242 | |
|---|
| 243 | |
|---|
| 244 | /** Set cull node callback, called during cull traversal. */ |
|---|
| 245 | void setCullCallback(NodeCallback* nc) { _cullCallback = nc; } |
|---|
| 246 | |
|---|
| 247 | /** Get cull node callback, called during cull traversal. */ |
|---|
| 248 | inline NodeCallback* getCullCallback() { return _cullCallback.get(); } |
|---|
| 249 | |
|---|
| 250 | /** Get const cull node callback, called during cull traversal. */ |
|---|
| 251 | inline const NodeCallback* getCullCallback() const { return _cullCallback.get(); } |
|---|
| 252 | |
|---|
| 253 | /** Convenience method that sets the cull callback of the node if it doesn't exist, or nest it into the existing one. */ |
|---|
| 254 | inline void addCullCallback(NodeCallback* nc) { |
|---|
| 255 | if (nc != NULL) { |
|---|
| 256 | if (_cullCallback.valid()) _cullCallback->addNestedCallback(nc); |
|---|
| 257 | else setCullCallback(nc); |
|---|
| 258 | } |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | /** Convenience method that removes a given callback from a node, even if that callback is nested. There is no error return in case the given callback is not found. */ |
|---|
| 262 | inline void removeCullCallback(NodeCallback* nc) { |
|---|
| 263 | if (nc != NULL && _cullCallback.valid()) { |
|---|
| 264 | if (_cullCallback == nc) setCullCallback(nc->getNestedCallback()); // replace the callback by the nested one |
|---|
| 265 | else _cullCallback->removeNestedCallback(nc); |
|---|
| 266 | } |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | /** Set the view frustum/small feature culling of this node to be active or inactive. |
|---|
| 270 | * The default value is true for _cullingActive. Used as a guide |
|---|
| 271 | * to the cull traversal.*/ |
|---|
| 272 | void setCullingActive(bool active); |
|---|
| 273 | |
|---|
| 274 | /** Get the view frustum/small feature _cullingActive flag for this node. Used as a guide |
|---|
| 275 | * to the cull traversal.*/ |
|---|
| 276 | inline bool getCullingActive() const { return _cullingActive; } |
|---|
| 277 | |
|---|
| 278 | /** Get the number of Children of this node which have culling disabled.*/ |
|---|
| 279 | inline unsigned int getNumChildrenWithCullingDisabled() const { return _numChildrenWithCullingDisabled; } |
|---|
| 280 | |
|---|
| 281 | /** Return true if this node can be culled by view frustum, occlusion or small feature culling during the cull traversal. |
|---|
| 282 | * Note, returns true only if no children have culling disabled, and the local _cullingActive flag is true.*/ |
|---|
| 283 | inline bool isCullingActive() const { return _numChildrenWithCullingDisabled==0 && _cullingActive && getBound().valid(); } |
|---|
| 284 | |
|---|
| 285 | /** Get the number of Children of this node which are or have OccluderNode's.*/ |
|---|
| 286 | inline unsigned int getNumChildrenWithOccluderNodes() const { return _numChildrenWithOccluderNodes; } |
|---|
| 287 | |
|---|
| 288 | |
|---|
| 289 | /** return true if this node is an OccluderNode or the subgraph below this node are OccluderNodes.*/ |
|---|
| 290 | bool containsOccluderNodes() const; |
|---|
| 291 | |
|---|
| 292 | |
|---|
| 293 | /** |
|---|
| 294 | * This is a set of bits (flags) that represent the Node. |
|---|
| 295 | * The default value is 0xffffffff (all bits set). |
|---|
| 296 | * |
|---|
| 297 | * The most common use of these is during traversal of the scene graph. |
|---|
| 298 | * For instance, when traversing the scene graph the osg::NodeVisitor does a bitwise |
|---|
| 299 | * AND of its TraversalMask with the Node's NodeMask to |
|---|
| 300 | * determine if the Node should be processed/traversed. |
|---|
| 301 | * |
|---|
| 302 | * For example, if a Node has a NodeMask value of 0x02 (only 2nd bit set) |
|---|
| 303 | * and the osg::Camera has a CullMask of 0x4 (2nd bit not set) then during cull traversal, |
|---|
| 304 | * which takes it's TraversalMask from the Camera's CullMask, the node and any children |
|---|
| 305 | * would be ignored and thereby treated as "culled" and thus not rendered. |
|---|
| 306 | * Conversely, if the osg::Camera CullMask were 0x3 (2nd bit set) then the node |
|---|
| 307 | * would be processed and child Nodes would be examined. |
|---|
| 308 | */ |
|---|
| 309 | typedef unsigned int NodeMask; |
|---|
| 310 | /** Set the node mask.*/ |
|---|
| 311 | inline void setNodeMask(NodeMask nm) { _nodeMask = nm; } |
|---|
| 312 | /** Get the node Mask.*/ |
|---|
| 313 | inline NodeMask getNodeMask() const { return _nodeMask; } |
|---|
| 314 | |
|---|
| 315 | |
|---|
| 316 | |
|---|
| 317 | /** Set the node's StateSet.*/ |
|---|
| 318 | void setStateSet(osg::StateSet* stateset); |
|---|
| 319 | |
|---|
| 320 | /** return the node's StateSet, if one does not already exist create it |
|---|
| 321 | * set the node and return the newly created StateSet. This ensures |
|---|
| 322 | * that a valid StateSet is always returned and can be used directly.*/ |
|---|
| 323 | osg::StateSet* getOrCreateStateSet(); |
|---|
| 324 | |
|---|
| 325 | /** Return the node's StateSet. returns NULL if a stateset is not attached.*/ |
|---|
| 326 | inline osg::StateSet* getStateSet() { return _stateset.get(); } |
|---|
| 327 | |
|---|
| 328 | /** Return the node's const StateSet. Returns NULL if a stateset is not attached.*/ |
|---|
| 329 | inline const osg::StateSet* getStateSet() const { return _stateset.get(); } |
|---|
| 330 | |
|---|
| 331 | |
|---|
| 332 | /** A vector of std::string's which are used to describe the object.*/ |
|---|
| 333 | typedef std::vector<std::string> DescriptionList; |
|---|
| 334 | |
|---|
| 335 | /** Set the list of string descriptions.*/ |
|---|
| 336 | void setDescriptions(const DescriptionList& descriptions); |
|---|
| 337 | |
|---|
| 338 | /** Get the description list of the node.*/ |
|---|
| 339 | DescriptionList& getDescriptions(); |
|---|
| 340 | |
|---|
| 341 | /** Get the const description list of the const node.*/ |
|---|
| 342 | const DescriptionList& getDescriptions() const; |
|---|
| 343 | |
|---|
| 344 | |
|---|
| 345 | /** Get a single const description of the const node.*/ |
|---|
| 346 | const std::string& getDescription(unsigned int i) const; |
|---|
| 347 | |
|---|
| 348 | /** Get a single description of the node.*/ |
|---|
| 349 | std::string& getDescription(unsigned int i); |
|---|
| 350 | |
|---|
| 351 | /** Get the number of descriptions of the node.*/ |
|---|
| 352 | unsigned int getNumDescriptions() const; |
|---|
| 353 | |
|---|
| 354 | /** Add a description string to the node.*/ |
|---|
| 355 | void addDescription(const std::string& desc); |
|---|
| 356 | |
|---|
| 357 | |
|---|
| 358 | /** Set the initial bounding volume to use when computing the overall bounding volume.*/ |
|---|
| 359 | void setInitialBound(const osg::BoundingSphere& bsphere) { _initialBound = bsphere; dirtyBound(); } |
|---|
| 360 | |
|---|
| 361 | /** Set the initial bounding volume to use when computing the overall bounding volume.*/ |
|---|
| 362 | const BoundingSphere& getInitialBound() const { return _initialBound; } |
|---|
| 363 | |
|---|
| 364 | /** Mark this node's bounding sphere dirty. |
|---|
| 365 | Forcing it to be computed on the next call to getBound().*/ |
|---|
| 366 | void dirtyBound(); |
|---|
| 367 | |
|---|
| 368 | /** Get the bounding sphere of node. |
|---|
| 369 | Using lazy evaluation computes the bounding sphere if it is 'dirty'.*/ |
|---|
| 370 | inline const BoundingSphere& getBound() const |
|---|
| 371 | { |
|---|
| 372 | if(!_boundingSphereComputed) |
|---|
| 373 | { |
|---|
| 374 | _boundingSphere = _initialBound; |
|---|
| 375 | if (_computeBoundCallback.valid()) |
|---|
| 376 | _boundingSphere.expandBy(_computeBoundCallback->computeBound(*this)); |
|---|
| 377 | else |
|---|
| 378 | _boundingSphere.expandBy(computeBound()); |
|---|
| 379 | |
|---|
| 380 | _boundingSphereComputed = true; |
|---|
| 381 | } |
|---|
| 382 | return _boundingSphere; |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | |
|---|
| 386 | /** Compute the bounding sphere around Node's geometry or children. |
|---|
| 387 | This method is automatically called by getBound() when the bounding |
|---|
| 388 | sphere has been marked dirty via dirtyBound().*/ |
|---|
| 389 | virtual BoundingSphere computeBound() const; |
|---|
| 390 | |
|---|
| 391 | /** Callback to allow users to override the default computation of bounding volume.*/ |
|---|
| 392 | struct ComputeBoundingSphereCallback : public osg::Object |
|---|
| 393 | { |
|---|
| 394 | ComputeBoundingSphereCallback() {} |
|---|
| 395 | |
|---|
| 396 | ComputeBoundingSphereCallback(const ComputeBoundingSphereCallback&,const CopyOp&) {} |
|---|
| 397 | |
|---|
| 398 | META_Object(osg,ComputeBoundingSphereCallback); |
|---|
| 399 | |
|---|
| 400 | virtual BoundingSphere computeBound(const osg::Node&) const { return BoundingSphere(); } |
|---|
| 401 | }; |
|---|
| 402 | |
|---|
| 403 | /** Set the compute bound callback to override the default computeBound.*/ |
|---|
| 404 | void setComputeBoundingSphereCallback(ComputeBoundingSphereCallback* callback) { _computeBoundCallback = callback; } |
|---|
| 405 | |
|---|
| 406 | /** Get the compute bound callback.*/ |
|---|
| 407 | ComputeBoundingSphereCallback* getComputeBoundingSphereCallback() { return _computeBoundCallback.get(); } |
|---|
| 408 | |
|---|
| 409 | /** Get the const compute bound callback.*/ |
|---|
| 410 | const ComputeBoundingSphereCallback* getComputeBoundingSphereCallback() const { return _computeBoundCallback.get(); } |
|---|
| 411 | |
|---|
| 412 | /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/ |
|---|
| 413 | virtual void setThreadSafeRefUnref(bool threadSafe); |
|---|
| 414 | |
|---|
| 415 | /** Resize any per context GLObject buffers to specified size. */ |
|---|
| 416 | virtual void resizeGLObjectBuffers(unsigned int /*maxSize*/); |
|---|
| 417 | |
|---|
| 418 | /** If State is non-zero, this function releases any associated OpenGL objects for |
|---|
| 419 | * the specified graphics context. Otherwise, releases OpenGL objects |
|---|
| 420 | * for all graphics contexts. */ |
|---|
| 421 | virtual void releaseGLObjects(osg::State* = 0) const; |
|---|
| 422 | |
|---|
| 423 | |
|---|
| 424 | protected: |
|---|
| 425 | |
|---|
| 426 | /** Node destructor. Note, is protected so that Nodes cannot |
|---|
| 427 | be deleted other than by being dereferenced and the reference |
|---|
| 428 | count being zero (see osg::Referenced), preventing the deletion |
|---|
| 429 | of nodes which are still in use. This also means that |
|---|
| 430 | Nodes cannot be created on stack i.e Node node will not compile, |
|---|
| 431 | forcing all nodes to be created on the heap i.e Node* node |
|---|
| 432 | = new Node().*/ |
|---|
| 433 | virtual ~Node(); |
|---|
| 434 | |
|---|
| 435 | |
|---|
| 436 | |
|---|
| 437 | BoundingSphere _initialBound; |
|---|
| 438 | ref_ptr<ComputeBoundingSphereCallback> _computeBoundCallback; |
|---|
| 439 | mutable BoundingSphere _boundingSphere; |
|---|
| 440 | mutable bool _boundingSphereComputed; |
|---|
| 441 | |
|---|
| 442 | void addParent(osg::Group* node); |
|---|
| 443 | void removeParent(osg::Group* node); |
|---|
| 444 | |
|---|
| 445 | ParentList _parents; |
|---|
| 446 | friend class osg::Group; |
|---|
| 447 | friend class osg::Drawable; |
|---|
| 448 | friend class osg::StateSet; |
|---|
| 449 | |
|---|
| 450 | ref_ptr<NodeCallback> _updateCallback; |
|---|
| 451 | unsigned int _numChildrenRequiringUpdateTraversal; |
|---|
| 452 | void setNumChildrenRequiringUpdateTraversal(unsigned int num); |
|---|
| 453 | |
|---|
| 454 | ref_ptr<NodeCallback> _eventCallback; |
|---|
| 455 | unsigned int _numChildrenRequiringEventTraversal; |
|---|
| 456 | void setNumChildrenRequiringEventTraversal(unsigned int num); |
|---|
| 457 | |
|---|
| 458 | ref_ptr<NodeCallback> _cullCallback; |
|---|
| 459 | |
|---|
| 460 | bool _cullingActive; |
|---|
| 461 | unsigned int _numChildrenWithCullingDisabled; |
|---|
| 462 | void setNumChildrenWithCullingDisabled(unsigned int num); |
|---|
| 463 | |
|---|
| 464 | unsigned int _numChildrenWithOccluderNodes; |
|---|
| 465 | void setNumChildrenWithOccluderNodes(unsigned int num); |
|---|
| 466 | |
|---|
| 467 | NodeMask _nodeMask; |
|---|
| 468 | |
|---|
| 469 | ref_ptr<StateSet> _stateset; |
|---|
| 470 | |
|---|
| 471 | }; |
|---|
| 472 | |
|---|
| 473 | } |
|---|
| 474 | |
|---|
| 475 | #endif |
|---|