root/OpenSceneGraph/trunk/src/osg/Node.cpp @ 13041

Revision 13041, 16.7 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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#include <osg/Node>
15#include <osg/Group>
16#include <osg/NodeVisitor>
17#include <osg/Notify>
18#include <osg/OccluderNode>
19#include <osg/Transform>
20#include <osg/UserDataContainer>
21
22#include <algorithm>
23
24using namespace osg;
25
26namespace osg
27{
28    /// Helper class for generating NodePathList.
29    class CollectParentPaths : public NodeVisitor
30    {
31    public:
32        CollectParentPaths(const osg::Node* haltTraversalAtNode=0) :
33            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS),
34            _haltTraversalAtNode(haltTraversalAtNode)
35        {
36        }
37
38        virtual void apply(osg::Node& node)
39        {
40            if (node.getNumParents()==0 || &node==_haltTraversalAtNode)
41            {
42                _nodePaths.push_back(getNodePath());
43            }
44            else
45            {
46                traverse(node);
47            }
48       }
49
50        const Node*     _haltTraversalAtNode;
51        NodePath        _nodePath;
52        NodePathList    _nodePaths;
53    };
54}
55
56Node::Node()
57    :Object(true)
58{
59    _boundingSphereComputed = false;
60    _nodeMask = 0xffffffff;
61
62    _numChildrenRequiringUpdateTraversal = 0;
63
64    _numChildrenRequiringEventTraversal = 0;
65
66    _cullingActive = true;
67    _numChildrenWithCullingDisabled = 0;
68
69    _numChildrenWithOccluderNodes = 0;
70}
71
72Node::Node(const Node& node,const CopyOp& copyop):
73        Object(node,copyop),
74        _initialBound(node._initialBound),
75        _boundingSphere(node._boundingSphere),
76        _boundingSphereComputed(node._boundingSphereComputed),
77        _parents(), // leave empty as parentList is managed by Group.
78        _updateCallback(copyop(node._updateCallback.get())),
79        _numChildrenRequiringUpdateTraversal(0), // assume no children yet.
80        _numChildrenRequiringEventTraversal(0), // assume no children yet.
81        _cullCallback(copyop(node._cullCallback.get())),
82        _cullingActive(node._cullingActive),
83        _numChildrenWithCullingDisabled(0), // assume no children yet.
84        _numChildrenWithOccluderNodes(0),
85        _nodeMask(node._nodeMask)
86{
87    setStateSet(copyop(node._stateset.get()));
88}
89
90Node::~Node()
91{
92    // cleanly detatch any associated stateset (include remove parent links)
93    setStateSet(0);
94}
95
96void Node::addParent(osg::Group* node)
97{
98    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
99
100    _parents.push_back(node);
101}
102
103void Node::removeParent(osg::Group* node)
104{
105    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
106
107    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
108    if (pitr!=_parents.end()) _parents.erase(pitr);
109}
110
111void Node::accept(NodeVisitor& nv)
112{
113    if (nv.validNodeMask(*this))
114    {
115        nv.pushOntoNodePath(this);
116        nv.apply(*this);
117        nv.popFromNodePath();
118    }
119}
120
121
122void Node::ascend(NodeVisitor& nv)
123{
124    std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv));
125}
126
127void Node::setStateSet(osg::StateSet* stateset)
128{
129    // do nothing if nothing changed.
130    if (_stateset==stateset) return;
131
132    // track whether we need to account for the need to do a update or event traversal.
133    int delta_update = 0;
134    int delta_event = 0;
135
136    // remove this node from the current statesets parent list
137    if (_stateset.valid())
138    {
139        _stateset->removeParent(this);
140        if (_stateset->requiresUpdateTraversal()) --delta_update;
141        if (_stateset->requiresEventTraversal()) --delta_event;
142    }
143
144    // set the stateset.
145    _stateset = stateset;
146
147    // add this node to the new stateset to the parent list.
148    if (_stateset.valid())
149    {
150        _stateset->addParent(this);
151        if (_stateset->requiresUpdateTraversal()) ++delta_update;
152        if (_stateset->requiresEventTraversal()) ++delta_event;
153    }
154
155    if (delta_update!=0)
156    {
157        setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+delta_update);
158    }
159
160    if (delta_event!=0)
161    {
162        setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+delta_event);
163    }
164}
165
166osg::StateSet* Node::getOrCreateStateSet()
167{
168    if (!_stateset) setStateSet(new StateSet);
169    return _stateset.get();
170}
171
172NodePathList Node::getParentalNodePaths(osg::Node* haltTraversalAtNode) const
173{
174    CollectParentPaths cpp(haltTraversalAtNode);
175    const_cast<Node*>(this)->accept(cpp);
176    return cpp._nodePaths;
177}
178
179MatrixList Node::getWorldMatrices(const osg::Node* haltTraversalAtNode) const
180{
181    CollectParentPaths cpp(haltTraversalAtNode);
182    const_cast<Node*>(this)->accept(cpp);
183
184    MatrixList matrices;
185
186    for(NodePathList::iterator itr = cpp._nodePaths.begin();
187        itr != cpp._nodePaths.end();
188        ++itr)
189    {
190        NodePath& nodePath = *itr;
191        if (nodePath.empty())
192        {
193            matrices.push_back(osg::Matrix::identity());
194        }
195        else
196        {
197            matrices.push_back(osg::computeLocalToWorld(nodePath));
198        }
199    }
200
201    return matrices;
202}
203
204void Node::setUpdateCallback(NodeCallback* nc)
205{
206    // if no changes just return.
207    if (_updateCallback==nc) return;
208
209    // updated callback has been changed, will need to update
210    // both _updateCallback and possibly the numChildrenRequiringAppTraversal
211    // if the number of callbacks changes.
212
213
214    // update the parents numChildrenRequiringAppTraversal
215    // note, if _numChildrenRequiringUpdateTraversal!=0 then the
216    // parents won't be affected by any app callback change,
217    // so no need to inform them.
218    if (_numChildrenRequiringUpdateTraversal==0 && !_parents.empty())
219    {
220        int delta = 0;
221        if (_updateCallback.valid()) --delta;
222        if (nc) ++delta;
223        if (delta!=0)
224        {
225            // the number of callbacks has changed, need to pass this
226            // on to parents so they know whether app traversal is
227            // required on this subgraph.
228            for(ParentList::iterator itr =_parents.begin();
229                itr != _parents.end();
230                ++itr)
231            {
232                (*itr)->setNumChildrenRequiringUpdateTraversal(
233                        (*itr)->getNumChildrenRequiringUpdateTraversal()+delta );
234            }
235
236        }
237    }
238
239    // set the app callback itself.
240    _updateCallback = nc;
241
242}
243
244void Node::setNumChildrenRequiringUpdateTraversal(unsigned int num)
245{
246    // if no changes just return.
247    if (_numChildrenRequiringUpdateTraversal==num) return;
248
249    // note, if _updateCallback is set then the
250    // parents won't be affected by any changes to
251    // _numChildrenRequiringUpdateTraversal so no need to inform them.
252    if (!_updateCallback && !_parents.empty())
253    {
254
255        // need to pass on changes to parents.
256        int delta = 0;
257        if (_numChildrenRequiringUpdateTraversal>0) --delta;
258        if (num>0) ++delta;
259        if (delta!=0)
260        {
261            // the number of callbacks has changed, need to pass this
262            // on to parents so they know whether app traversal is
263            // required on this subgraph.
264            for(ParentList::iterator itr =_parents.begin();
265                itr != _parents.end();
266                ++itr)
267            {
268                (*itr)->setNumChildrenRequiringUpdateTraversal(
269                    (*itr)->getNumChildrenRequiringUpdateTraversal()+delta
270                    );
271            }
272
273        }
274    }
275
276    // finally update this objects value.
277    _numChildrenRequiringUpdateTraversal=num;
278
279}
280
281
282void Node::setEventCallback(NodeCallback* nc)
283{
284    // if no changes just return.
285    if (_eventCallback==nc) return;
286
287    // event callback has been changed, will need to Event
288    // both _EventCallback and possibly the numChildrenRequiringAppTraversal
289    // if the number of callbacks changes.
290
291
292    // Event the parents numChildrenRequiringAppTraversal
293    // note, if _numChildrenRequiringEventTraversal!=0 then the
294    // parents won't be affected by any app callback change,
295    // so no need to inform them.
296    if (_numChildrenRequiringEventTraversal==0 && !_parents.empty())
297    {
298        int delta = 0;
299        if (_eventCallback.valid()) --delta;
300        if (nc) ++delta;
301        if (delta!=0)
302        {
303            // the number of callbacks has changed, need to pass this
304            // on to parents so they know whether app traversal is
305            // required on this subgraph.
306            for(ParentList::iterator itr =_parents.begin();
307                itr != _parents.end();
308                ++itr)
309            {
310                (*itr)->setNumChildrenRequiringEventTraversal(
311                        (*itr)->getNumChildrenRequiringEventTraversal()+delta );
312            }
313
314        }
315    }
316
317    // set the app callback itself.
318    _eventCallback = nc;
319
320}
321
322void Node::setNumChildrenRequiringEventTraversal(unsigned int num)
323{
324    // if no changes just return.
325    if (_numChildrenRequiringEventTraversal==num) return;
326
327    // note, if _EventCallback is set then the
328    // parents won't be affected by any changes to
329    // _numChildrenRequiringEventTraversal so no need to inform them.
330    if (!_eventCallback && !_parents.empty())
331    {
332
333        // need to pass on changes to parents.
334        int delta = 0;
335        if (_numChildrenRequiringEventTraversal>0) --delta;
336        if (num>0) ++delta;
337        if (delta!=0)
338        {
339            // the number of callbacks has changed, need to pass this
340            // on to parents so they know whether app traversal is
341            // required on this subgraph.
342            for(ParentList::iterator itr =_parents.begin();
343                itr != _parents.end();
344                ++itr)
345            {
346                (*itr)->setNumChildrenRequiringEventTraversal(
347                    (*itr)->getNumChildrenRequiringEventTraversal()+delta
348                    );
349            }
350
351        }
352    }
353
354    // finally Event this objects value.
355    _numChildrenRequiringEventTraversal=num;
356
357}
358
359void Node::setCullingActive(bool active)
360{
361    // if no changes just return.
362    if (_cullingActive == active) return;
363
364    // culling active has been changed, will need to update
365    // both _cullActive and possibly the parents numChildrenWithCullingDisabled
366    // if culling disabled changes.
367
368    // update the parents _numChildrenWithCullingDisabled
369    // note, if _numChildrenWithCullingDisabled!=0 then the
370    // parents won't be affected by any app callback change,
371    // so no need to inform them.
372    if (_numChildrenWithCullingDisabled==0 && !_parents.empty())
373    {
374        int delta = 0;
375        if (!_cullingActive) --delta;
376        if (!active) ++delta;
377        if (delta!=0)
378        {
379            // the number of callbacks has changed, need to pass this
380            // on to parents so they know whether app traversal is
381            // required on this subgraph.
382            for(ParentList::iterator itr =_parents.begin();
383                itr != _parents.end();
384                ++itr)
385            {
386                (*itr)->setNumChildrenWithCullingDisabled(
387                        (*itr)->getNumChildrenWithCullingDisabled()+delta );
388            }
389
390        }
391    }
392
393    // set the cullingActive itself.
394    _cullingActive = active;
395}
396
397void Node::setNumChildrenWithCullingDisabled(unsigned int num)
398{
399    // if no changes just return.
400    if (_numChildrenWithCullingDisabled==num) return;
401
402    // note, if _cullingActive is false then the
403    // parents won't be affected by any changes to
404    // _numChildrenWithCullingDisabled so no need to inform them.
405    if (_cullingActive && !_parents.empty())
406    {
407
408        // need to pass on changes to parents.
409        int delta = 0;
410        if (_numChildrenWithCullingDisabled>0) --delta;
411        if (num>0) ++delta;
412        if (delta!=0)
413        {
414            // the number of callbacks has changed, need to pass this
415            // on to parents so they know whether app traversal is
416            // required on this subgraph.
417            for(ParentList::iterator itr =_parents.begin();
418                itr != _parents.end();
419                ++itr)
420            {
421                (*itr)->setNumChildrenWithCullingDisabled(
422                    (*itr)->getNumChildrenWithCullingDisabled()+delta
423                    );
424            }
425
426        }
427    }
428
429    // finally update this objects value.
430    _numChildrenWithCullingDisabled=num;
431}
432
433
434void Node::setNumChildrenWithOccluderNodes(unsigned int num)
435{
436    // if no changes just return.
437    if (_numChildrenWithOccluderNodes==num) return;
438
439    // note, if this node is a OccluderNode then the
440    // parents won't be affected by any changes to
441    // _numChildrenWithOccluderNodes so no need to inform them.
442    if (!dynamic_cast<OccluderNode*>(this) && !_parents.empty())
443    {
444
445        // need to pass on changes to parents.
446        int delta = 0;
447        if (_numChildrenWithOccluderNodes>0) --delta;
448        if (num>0) ++delta;
449        if (delta!=0)
450        {
451            // the number of callbacks has changed, need to pass this
452            // on to parents so they know whether app traversal is
453            // required on this subgraph.
454            for(ParentList::iterator itr =_parents.begin();
455                itr != _parents.end();
456                ++itr)
457            {
458                (*itr)->setNumChildrenWithOccluderNodes(
459                    (*itr)->getNumChildrenWithOccluderNodes()+delta
460                    );
461            }
462
463        }
464    }
465
466    // finally update this objects value.
467    _numChildrenWithOccluderNodes=num;
468
469}
470
471bool Node::containsOccluderNodes() const
472{
473    return _numChildrenWithOccluderNodes>0 || dynamic_cast<const OccluderNode*>(this);
474}
475
476void Node::setDescriptions(const DescriptionList& descriptions)
477{
478    getOrCreateUserDataContainer()->setDescriptions(descriptions);
479}
480
481Node::DescriptionList& Node::getDescriptions()
482{
483    return getOrCreateUserDataContainer()->getDescriptions();
484}
485
486static OpenThreads::Mutex s_mutex_StaticDescriptionList;
487static const Node::DescriptionList& getStaticDescriptionList()
488{
489    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_StaticDescriptionList);
490    static Node::DescriptionList s_descriptionList;
491    return s_descriptionList;
492}
493
494const Node::DescriptionList& Node::getDescriptions() const
495{
496    if (_userDataContainer) return _userDataContainer->getDescriptions();
497    else return getStaticDescriptionList();
498}
499
500std::string& Node::getDescription(unsigned int i)
501{
502    return getOrCreateUserDataContainer()->getDescriptions()[i];
503}
504
505const std::string& Node::getDescription(unsigned int i) const
506{
507    if (_userDataContainer) return _userDataContainer->getDescriptions()[i];
508    else return getStaticDescriptionList()[i];
509}
510
511unsigned int Node::getNumDescriptions() const
512{
513    return _userDataContainer ? _userDataContainer->getDescriptions().size() : 0;
514}
515
516void Node::addDescription(const std::string& desc)
517{
518    getOrCreateUserDataContainer()->getDescriptions().push_back(desc);
519}
520
521BoundingSphere Node::computeBound() const
522{
523    return BoundingSphere();
524}
525
526
527void Node::dirtyBound()
528{
529    if (_boundingSphereComputed)
530    {
531        _boundingSphereComputed = false;
532
533        // dirty parent bounding sphere's to ensure that all are valid.
534        for(ParentList::iterator itr=_parents.begin();
535            itr!=_parents.end();
536            ++itr)
537        {
538            (*itr)->dirtyBound();
539        }
540
541    }
542}
543
544void Node::setThreadSafeRefUnref(bool threadSafe)
545{
546    Object::setThreadSafeRefUnref(threadSafe);
547
548    if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
549    if (_updateCallback.valid()) _updateCallback->setThreadSafeRefUnref(threadSafe);
550    if (_eventCallback.valid()) _eventCallback->setThreadSafeRefUnref(threadSafe);
551    if (_cullCallback.valid()) _cullCallback->setThreadSafeRefUnref(threadSafe);
552}
553
554void Node::resizeGLObjectBuffers(unsigned int maxSize)
555{
556    if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize);
557    if (_updateCallback.valid()) _updateCallback->resizeGLObjectBuffers(maxSize);
558    if (_eventCallback.valid()) _eventCallback->resizeGLObjectBuffers(maxSize);
559    if (_cullCallback.valid()) _cullCallback->resizeGLObjectBuffers(maxSize);
560}
561
562void Node::releaseGLObjects(osg::State* state) const
563{
564    if (_stateset.valid()) _stateset->releaseGLObjects(state);
565    if (_updateCallback.valid()) _updateCallback->releaseGLObjects(state);
566    if (_eventCallback.valid()) _eventCallback->releaseGLObjects(state);
567    if (_cullCallback.valid()) _cullCallback->releaseGLObjects(state);
568}
569
570
Note: See TracBrowser for help on using the browser.