root/OpenSceneGraph/branches/OpenSceneGraph-2.8/src/osg/Node.cpp @ 11238

Revision 11238, 15.6 kB (checked in by paulmartz, 4 years ago)

2.8 branch: Minor bug fixes for ac and 3dc plugins. Merges these revisions from trunk: 10010, 10758, and 11175.

  • Property svn:mergeinfo set to
    /OpenSceneGraph/branches/OpenSceneGraph-2.8.2/src/osg/Node.cpp:10664
    /OpenSceneGraph/trunk/include/osg/src/osg/Node.cpp:9882
    /OpenSceneGraph/trunk/src/osg/Node.cpp:9769,9879-9880,9895,9897,9932,10010,10208,10340,10417,10456,10487,10622-10623,10625,10671-10672,10697,10722,10753,10758,10788,10818,10854-10855,10858,10887,10891,10923,10933,11019,11032,11034-11035,11111,11127,11131,11175
  • 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
21#include <algorithm>
22
23using namespace osg;
24
25namespace osg
26{
27    /// Helper class for generating NodePathList.
28    class CollectParentPaths : public NodeVisitor
29    {
30    public:
31        CollectParentPaths(const osg::Node* haltTraversalAtNode=0) :
32            osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_PARENTS),
33            _haltTraversalAtNode(haltTraversalAtNode)
34        {
35        }
36
37        virtual void apply(osg::Node& node)
38        {
39            if (node.getNumParents()==0 || &node==_haltTraversalAtNode)
40            {
41                _nodePaths.push_back(getNodePath());
42            }
43            else
44            {
45                traverse(node);
46            }
47       }
48
49        const Node*     _haltTraversalAtNode;
50        NodePath        _nodePath;
51        NodePathList    _nodePaths;
52    };
53}
54
55Node::Node()
56    :Object(true)
57{
58    _boundingSphereComputed = false;
59    _nodeMask = 0xffffffff;
60   
61    _numChildrenRequiringUpdateTraversal = 0;
62
63    _numChildrenRequiringEventTraversal = 0;
64
65    _cullingActive = true;
66    _numChildrenWithCullingDisabled = 0;
67
68    _numChildrenWithOccluderNodes = 0;
69}
70
71Node::Node(const Node& node,const CopyOp& copyop):
72        Object(node,copyop),
73        _initialBound(node._initialBound),
74        _boundingSphere(node._boundingSphere),
75        _boundingSphereComputed(node._boundingSphereComputed),
76        _parents(), // leave empty as parentList is managed by Group.
77        _updateCallback(node._updateCallback),
78        _numChildrenRequiringUpdateTraversal(0), // assume no children yet.
79        _numChildrenRequiringEventTraversal(0), // assume no children yet.
80        _cullCallback(node._cullCallback),
81        _cullingActive(node._cullingActive),
82        _numChildrenWithCullingDisabled(0), // assume no children yet.
83        _numChildrenWithOccluderNodes(0),
84        _nodeMask(node._nodeMask),
85        _descriptions(node._descriptions)
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
476BoundingSphere Node::computeBound() const
477{
478    return BoundingSphere();
479}
480
481
482void Node::dirtyBound()
483{
484    if (_boundingSphereComputed)
485    {
486        _boundingSphereComputed = false;
487
488        // dirty parent bounding sphere's to ensure that all are valid.
489        for(ParentList::iterator itr=_parents.begin();
490            itr!=_parents.end();
491            ++itr)
492        {
493            (*itr)->dirtyBound();
494        }
495
496    }
497}
498
499void Node::setThreadSafeRefUnref(bool threadSafe)
500{
501    Object::setThreadSafeRefUnref(threadSafe);
502   
503    if (_stateset.valid()) _stateset->setThreadSafeRefUnref(threadSafe);
504
505    if (_updateCallback.valid()) _updateCallback->setThreadSafeRefUnref(threadSafe);
506    if (_eventCallback.valid()) _eventCallback->setThreadSafeRefUnref(threadSafe);
507    if (_cullCallback.valid()) _cullCallback->setThreadSafeRefUnref(threadSafe);
508
509    if (_userData.valid()) _userData->setThreadSafeRefUnref(threadSafe);
510}
511
512void Node::resizeGLObjectBuffers(unsigned int maxSize)
513{
514    if (_stateset.valid()) _stateset->resizeGLObjectBuffers(maxSize);
515    if (_updateCallback.valid()) _updateCallback->resizeGLObjectBuffers(maxSize);
516    if (_eventCallback.valid()) _eventCallback->resizeGLObjectBuffers(maxSize);
517    if (_cullCallback.valid()) _cullCallback->resizeGLObjectBuffers(maxSize);
518}
519
520void Node::releaseGLObjects(osg::State* state) const
521{
522    if (_stateset.valid()) _stateset->releaseGLObjects(state);
523    if (_updateCallback.valid()) _updateCallback->releaseGLObjects(state);
524    if (_eventCallback.valid()) _eventCallback->releaseGLObjects(state);
525    if (_cullCallback.valid()) _cullCallback->releaseGLObjects(state);
526}
527
528
Note: See TracBrowser for help on using the browser.