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

Revision 10362, 15.6 kB (checked in by robert, 6 years ago)

From Cedric Pinson and Robert Osfield, addition of NodeCallbacks? to osg::CopyOp? and osg::Node copy constructor.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[1529]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
[120]14#include <osg/Node>
15#include <osg/Group>
16#include <osg/NodeVisitor>
17#include <osg/Notify>
[750]18#include <osg/OccluderNode>
[5757]19#include <osg/Transform>
[2]20
21#include <algorithm>
22
23using namespace osg;
24
[4896]25namespace osg
26{
27    /// Helper class for generating NodePathList.
28    class CollectParentPaths : public NodeVisitor
29    {
30    public:
[8880]31        CollectParentPaths(const osg::Node* haltTraversalAtNode=0) :
[4896]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
[8880]49        const Node*     _haltTraversalAtNode;
[4896]50        NodePath        _nodePath;
51        NodePathList    _nodePaths;
52    };
53}
54
[2]55Node::Node()
[7263]56    :Object(true)
[2]57{
[4202]58    _boundingSphereComputed = false;
[2]59    _nodeMask = 0xffffffff;
[26]60   
[1435]61    _numChildrenRequiringUpdateTraversal = 0;
[114]62
[3520]63    _numChildrenRequiringEventTraversal = 0;
64
[114]65    _cullingActive = true;
66    _numChildrenWithCullingDisabled = 0;
67
[750]68    _numChildrenWithOccluderNodes = 0;
[2]69}
70
[331]71Node::Node(const Node& node,const CopyOp& copyop):
72        Object(node,copyop),
[4202]73        _initialBound(node._initialBound),
74        _boundingSphere(node._boundingSphere),
75        _boundingSphereComputed(node._boundingSphereComputed),
[327]76        _parents(), // leave empty as parentList is managed by Group.
[10362]77        _updateCallback(copyop(node._updateCallback.get())),
[1435]78        _numChildrenRequiringUpdateTraversal(0), // assume no children yet.
[3520]79        _numChildrenRequiringEventTraversal(0), // assume no children yet.
[10362]80        _cullCallback(copyop(node._cullCallback.get())),
[327]81        _cullingActive(node._cullingActive),
[329]82        _numChildrenWithCullingDisabled(0), // assume no children yet.
[750]83        _numChildrenWithOccluderNodes(0),
[327]84        _nodeMask(node._nodeMask),
[9897]85        _descriptions(node._descriptions)
[327]86{
[9897]87    setStateSet(copyop(node._stateset.get()));
[327]88}
[2]89
90Node::~Node()
91{
[4424]92    // cleanly detatch any associated stateset (include remove parent links)
93    setStateSet(0);   
[2]94}
95
[365]96void Node::addParent(osg::Group* node)
97{
[9023]98    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
[7332]99
[9023]100    _parents.push_back(node);
[365]101}
[2]102
[365]103void Node::removeParent(osg::Group* node)
104{
[9023]105    OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(getRefMutex());
[7332]106
[9023]107    ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
108    if (pitr!=_parents.end()) _parents.erase(pitr);
[365]109}
110
[2]111void Node::accept(NodeVisitor& nv)
112{
[355]113    if (nv.validNodeMask(*this))
114    {
115        nv.pushOntoNodePath(this);
116        nv.apply(*this);
117        nv.popFromNodePath();
118    }
[2]119}
120
[8]121
[2]122void Node::ascend(NodeVisitor& nv)
123{
124    std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv));
125}
126
[4091]127void Node::setStateSet(osg::StateSet* stateset)
128{
129    // do nothing if nothing changed.
130    if (_stateset==stateset) return;
131   
[4092]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
[4091]136    // remove this node from the current statesets parent list
[4092]137    if (_stateset.valid())
138    {
139        _stateset->removeParent(this);
140        if (_stateset->requiresUpdateTraversal()) --delta_update;
141        if (_stateset->requiresEventTraversal()) --delta_event;
142    }
[4091]143   
144    // set the stateset.
145    _stateset = stateset;
146   
147    // add this node to the new stateset to the parent list.
[4092]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    }
[4091]164}
165
[1133]166osg::StateSet* Node::getOrCreateStateSet()
[676]167{
[4094]168    if (!_stateset) setStateSet(new StateSet);
[1133]169    return _stateset.get();
[676]170}
171
[4896]172NodePathList Node::getParentalNodePaths(osg::Node* haltTraversalAtNode) const
173{
174    CollectParentPaths cpp(haltTraversalAtNode);
175    const_cast<Node*>(this)->accept(cpp);
176    return cpp._nodePaths;
177}
[676]178
[8880]179MatrixList Node::getWorldMatrices(const osg::Node* haltTraversalAtNode) const
[5015]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
[1435]204void Node::setUpdateCallback(NodeCallback* nc)
[26]205{
206    // if no changes just return.
[1435]207    if (_updateCallback==nc) return;
[26]208   
[4092]209    // updated callback has been changed, will need to update
[1435]210    // both _updateCallback and possibly the numChildrenRequiringAppTraversal
[26]211    // if the number of callbacks changes.
212
213
214    // update the parents numChildrenRequiringAppTraversal
[1435]215    // note, if _numChildrenRequiringUpdateTraversal!=0 then the
[26]216    // parents won't be affected by any app callback change,
217    // so no need to inform them.
[1435]218    if (_numChildrenRequiringUpdateTraversal==0 && !_parents.empty())
[26]219    {
220        int delta = 0;
[1435]221        if (_updateCallback.valid()) --delta;
[26]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
[7648]227            // required on this subgraph.
[26]228            for(ParentList::iterator itr =_parents.begin();
229                itr != _parents.end();
230                ++itr)
231            {   
[1435]232                (*itr)->setNumChildrenRequiringUpdateTraversal(
233                        (*itr)->getNumChildrenRequiringUpdateTraversal()+delta );
[26]234            }
235
236        }
237    }
238
239    // set the app callback itself.
[1435]240    _updateCallback = nc;
[26]241
242}
243
[1435]244void Node::setNumChildrenRequiringUpdateTraversal(unsigned int num)
[26]245{
246    // if no changes just return.
[1435]247    if (_numChildrenRequiringUpdateTraversal==num) return;
[26]248
[1435]249    // note, if _updateCallback is set then the
[26]250    // parents won't be affected by any changes to
[1435]251    // _numChildrenRequiringUpdateTraversal so no need to inform them.
252    if (!_updateCallback && !_parents.empty())
[26]253    {
254   
255        // need to pass on changes to parents.       
256        int delta = 0;
[1435]257        if (_numChildrenRequiringUpdateTraversal>0) --delta;
[26]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
[7648]263            // required on this subgraph.
[26]264            for(ParentList::iterator itr =_parents.begin();
265                itr != _parents.end();
266                ++itr)
267            {   
[1435]268                (*itr)->setNumChildrenRequiringUpdateTraversal(
269                    (*itr)->getNumChildrenRequiringUpdateTraversal()+delta
[26]270                    );
271            }
272
273        }
274    }
275   
276    // finally update this objects value.
[1435]277    _numChildrenRequiringUpdateTraversal=num;
[26]278   
279}
280
[3520]281
282void Node::setEventCallback(NodeCallback* nc)
283{
284    // if no changes just return.
285    if (_eventCallback==nc) return;
286   
[4092]287    // event callback has been changed, will need to Event
[3520]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
[7648]305            // required on this subgraph.
[3520]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
[7648]341            // required on this subgraph.
[3520]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
[1133]359void Node::setCullingActive(bool active)
[114]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
[7648]381            // required on this subgraph.
[114]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
[1133]397void Node::setNumChildrenWithCullingDisabled(unsigned int num)
[114]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
[7648]416            // required on this subgraph.
[114]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
[1133]434void Node::setNumChildrenWithOccluderNodes(unsigned int num)
[750]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
[7648]453            // required on this subgraph.
[750]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
[1133]471bool Node::containsOccluderNodes() const
[750]472{
473    return _numChildrenWithOccluderNodes>0 || dynamic_cast<const OccluderNode*>(this);
474}
475
[4202]476BoundingSphere Node::computeBound() const
[2]477{
[4202]478    return BoundingSphere();
[2]479}
480
481
482void Node::dirtyBound()
483{
[4202]484    if (_boundingSphereComputed)
[2]485    {
[4202]486        _boundingSphereComputed = false;
[2]487
488        // dirty parent bounding sphere's to ensure that all are valid.
489        for(ParentList::iterator itr=_parents.begin();
[8]490            itr!=_parents.end();
491            ++itr)
[2]492        {
493            (*itr)->dirtyBound();
494        }
495
496    }
497}
[4170]498
[5885]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
[5882]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
[4170]520void Node::releaseGLObjects(osg::State* state) const
521{
522    if (_stateset.valid()) _stateset->releaseGLObjects(state);
[5622]523    if (_updateCallback.valid()) _updateCallback->releaseGLObjects(state);
524    if (_eventCallback.valid()) _eventCallback->releaseGLObjects(state);
525    if (_cullCallback.valid()) _cullCallback->releaseGLObjects(state);
[4170]526}
527
528
Note: See TracBrowser for help on using the browser.