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

Revision 13041, 12.0 kB (checked in by robert, 2 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/Group>
15#include <osg/BoundingBox>
16#include <osg/Transform>
17#include <osg/OccluderNode>
18#include <osg/Notify>
19
20#include <stdio.h>
21#include <math.h>
22
23#include <algorithm>
24
25using namespace osg;
26
27Group::Group()
28{
29}
30
31Group::Group(const Group& group,const CopyOp& copyop):
32    Node(group,copyop)
33{
34    for(NodeList::const_iterator itr=group._children.begin();
35        itr!=group._children.end();
36        ++itr)
37    {
38        Node* child = copyop(itr->get());
39        if (child) addChild(child);
40    }
41}
42
43Group::~Group()
44{
45    // remove reference to this from children's parent lists.
46    for(NodeList::iterator itr=_children.begin();
47        itr!=_children.end();
48        ++itr)
49    {
50        (*itr)->removeParent(this);
51    }
52
53}
54
55
56void Group::traverse(NodeVisitor& nv)
57{
58    for(NodeList::iterator itr=_children.begin();
59        itr!=_children.end();
60        ++itr)
61    {
62        (*itr)->accept(nv);
63    }
64}
65
66
67bool Group::addChild( Node *child )
68{
69    return Group::insertChild( _children.size(), child );
70}
71
72bool Group::insertChild( unsigned int index, Node *child )
73{
74    if (!child) return false;
75
76#if ENSURE_CHILD_IS_UNIQUE
77    if (containsNode(child))
78    {
79        OSG_WARN<<"Adding non unique child to osg::Group, ignoring call"<<std::endl;
80        return false;
81    }
82#endif
83
84    if (child)
85    {
86        // note ref_ptr<> automatically handles incrementing child's reference count.
87        if (index >= _children.size())
88        {
89            _children.push_back(child);
90        }
91        else
92        {
93            _children.insert(_children.begin()+index, child);
94        }
95
96        // register as parent of child.
97        child->addParent(this);
98
99        // tell any subclasses that a child has been inserted so that they can update themselves.
100        childInserted(index);
101
102        dirtyBound();
103
104        // could now require app traversal thanks to the new subgraph,
105        // so need to check and update if required.
106        if (child->getNumChildrenRequiringUpdateTraversal()>0 ||
107            child->getUpdateCallback())
108        {
109            setNumChildrenRequiringUpdateTraversal(
110                getNumChildrenRequiringUpdateTraversal()+1
111                );
112        }
113
114        // could now require app traversal thanks to the new subgraph,
115        // so need to check and update if required.
116        if (child->getNumChildrenRequiringEventTraversal()>0 ||
117            child->getEventCallback())
118        {
119            setNumChildrenRequiringEventTraversal(
120                getNumChildrenRequiringEventTraversal()+1
121                );
122        }
123
124        // could now require disabling of culling thanks to the new subgraph,
125        // so need to check and update if required.
126        if (child->getNumChildrenWithCullingDisabled()>0 ||
127            !child->getCullingActive())
128        {
129            setNumChildrenWithCullingDisabled(
130                getNumChildrenWithCullingDisabled()+1
131                );
132        }
133
134        if (child->getNumChildrenWithOccluderNodes()>0 ||
135            dynamic_cast<osg::OccluderNode*>(child))
136        {
137            setNumChildrenWithOccluderNodes(
138                getNumChildrenWithOccluderNodes()+1
139                );
140        }
141
142        return true;
143    }
144    else return false;
145}
146
147bool Group::removeChildren(unsigned int pos,unsigned int numChildrenToRemove)
148{
149    if (pos<_children.size() && numChildrenToRemove>0)
150    {
151        unsigned int endOfRemoveRange = pos+numChildrenToRemove;
152        if (endOfRemoveRange>_children.size())
153        {
154            OSG_DEBUG<<"Warning: Group::removeChild(i,numChildrenToRemove) has been passed an excessive number"<<std::endl;
155            OSG_DEBUG<<"         of chilren to remove, trimming just to end of child list."<<std::endl;
156            endOfRemoveRange=_children.size();
157        }
158
159        unsigned int updateCallbackRemoved = 0;
160        unsigned int eventCallbackRemoved = 0;
161        unsigned int numChildrenWithCullingDisabledRemoved = 0;
162        unsigned int numChildrenWithOccludersRemoved = 0;
163
164        for(unsigned i=pos;i<endOfRemoveRange;++i)
165        {
166            osg::Node* child = _children[i].get();
167            // remove this Geode from the child parent list.
168            child->removeParent(this);
169
170            if (child->getNumChildrenRequiringUpdateTraversal()>0 || child->getUpdateCallback()) ++updateCallbackRemoved;
171
172            if (child->getNumChildrenRequiringEventTraversal()>0 || child->getEventCallback()) ++eventCallbackRemoved;
173
174            if (child->getNumChildrenWithCullingDisabled()>0 || !child->getCullingActive()) ++numChildrenWithCullingDisabledRemoved;
175
176            if (child->getNumChildrenWithOccluderNodes()>0 || dynamic_cast<osg::OccluderNode*>(child)) ++numChildrenWithOccludersRemoved;
177
178        }
179
180        childRemoved(pos,endOfRemoveRange-pos);
181
182        _children.erase(_children.begin()+pos,_children.begin()+endOfRemoveRange);
183
184        if (updateCallbackRemoved)
185        {
186            setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-updateCallbackRemoved);
187        }
188
189        if (eventCallbackRemoved)
190        {
191            setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-eventCallbackRemoved);
192        }
193
194        if (numChildrenWithCullingDisabledRemoved)
195        {
196            setNumChildrenWithCullingDisabled(getNumChildrenWithCullingDisabled()-numChildrenWithCullingDisabledRemoved);
197        }
198
199        if (numChildrenWithOccludersRemoved)
200        {
201            setNumChildrenWithOccluderNodes(getNumChildrenWithOccluderNodes()-numChildrenWithOccludersRemoved);
202        }
203
204        dirtyBound();
205
206        return true;
207    }
208    else return false;
209}
210
211
212bool Group::replaceChild( Node *origNode, Node *newNode )
213{
214    if (newNode==NULL || origNode==newNode) return false;
215
216    unsigned int pos = getChildIndex(origNode);
217    if (pos<_children.size())
218    {
219        return setChild(pos,newNode);
220    }
221    return false;
222}
223
224
225bool Group::setChild( unsigned  int i, Node* newNode )
226{
227    if (i<_children.size() && newNode)
228    {
229
230        ref_ptr<Node> origNode = _children[i];
231
232        // first remove for origNode's parent list.
233        origNode->removeParent(this);
234
235        // note ref_ptr<> automatically handles decrementing origNode's reference count,
236        // and inccrementing newNode's reference count.
237        _children[i] = newNode;
238
239        // register as parent of child.
240        newNode->addParent(this);
241
242        dirtyBound();
243
244
245        // could now require update traversal thanks to the new subgraph,
246        // so need to check and update if required.
247        int delta_numChildrenRequiringUpdateTraversal = 0;
248        if (origNode->getNumChildrenRequiringUpdateTraversal()>0 ||
249            origNode->getUpdateCallback())
250        {
251            --delta_numChildrenRequiringUpdateTraversal;
252        }
253        if (newNode->getNumChildrenRequiringUpdateTraversal()>0 ||
254            newNode->getUpdateCallback())
255        {
256            ++delta_numChildrenRequiringUpdateTraversal;
257        }
258
259        if (delta_numChildrenRequiringUpdateTraversal!=0)
260        {
261            setNumChildrenRequiringUpdateTraversal(
262                getNumChildrenRequiringUpdateTraversal()+delta_numChildrenRequiringUpdateTraversal
263                );
264        }
265
266        // could now require event traversal thanks to the new subgraph,
267        // so need to check and Event if required.
268        int delta_numChildrenRequiringEventTraversal = 0;
269        if (origNode->getNumChildrenRequiringEventTraversal()>0 ||
270            origNode->getEventCallback())
271        {
272            --delta_numChildrenRequiringEventTraversal;
273        }
274        if (newNode->getNumChildrenRequiringEventTraversal()>0 ||
275            newNode->getEventCallback())
276        {
277            ++delta_numChildrenRequiringEventTraversal;
278        }
279
280        if (delta_numChildrenRequiringEventTraversal!=0)
281        {
282            setNumChildrenRequiringEventTraversal(
283                getNumChildrenRequiringEventTraversal()+delta_numChildrenRequiringEventTraversal
284                );
285        }
286
287        // could now require disabling of culling thanks to the new subgraph,
288        // so need to check and update if required.
289        int delta_numChildrenWithCullingDisabled = 0;
290        if (origNode->getNumChildrenWithCullingDisabled()>0 ||
291            !origNode->getCullingActive())
292        {
293            --delta_numChildrenWithCullingDisabled;
294        }
295        if (newNode->getNumChildrenWithCullingDisabled()>0 ||
296            !newNode->getCullingActive())
297        {
298            ++delta_numChildrenWithCullingDisabled;
299        }
300
301        if (delta_numChildrenWithCullingDisabled!=0)
302        {
303            setNumChildrenWithCullingDisabled(
304                getNumChildrenWithCullingDisabled()+delta_numChildrenWithCullingDisabled
305                );
306        }
307
308        // could now require disabling of culling thanks to the new subgraph,
309        // so need to check and update if required.
310        int delta_numChildrenWithOccluderNodes = 0;
311        if (origNode->getNumChildrenWithOccluderNodes()>0 ||
312            dynamic_cast<osg::OccluderNode*>(origNode.get()))
313        {
314            --delta_numChildrenWithOccluderNodes;
315        }
316        if (newNode->getNumChildrenWithOccluderNodes()>0 ||
317            dynamic_cast<osg::OccluderNode*>(newNode))
318        {
319            ++delta_numChildrenWithOccluderNodes;
320        }
321
322        if (delta_numChildrenWithOccluderNodes!=0)
323        {
324            setNumChildrenWithOccluderNodes(
325                getNumChildrenWithOccluderNodes()+delta_numChildrenWithOccluderNodes
326                );
327        }
328
329        return true;
330    }
331    else return false;
332
333}
334
335BoundingSphere Group::computeBound() const
336{
337    BoundingSphere bsphere;
338    if (_children.empty())
339    {
340        return bsphere;
341    }
342
343    // note, special handling of the case when a child is an Transform,
344    // such that only Transforms which are relative to their parents coordinates frame (i.e this group)
345    // are handled, Transform relative to and absolute reference frame are ignored.
346
347    BoundingBox bb;
348    bb.init();
349    NodeList::const_iterator itr;
350    for(itr=_children.begin();
351        itr!=_children.end();
352        ++itr)
353    {
354        const osg::Transform* transform = (*itr)->asTransform();
355        if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_RF)
356        {
357            bb.expandBy((*itr)->getBound());
358        }
359    }
360
361    if (!bb.valid())
362    {
363        return bsphere;
364    }
365
366    bsphere._center = bb.center();
367    bsphere._radius = 0.0f;
368    for(itr=_children.begin();
369        itr!=_children.end();
370        ++itr)
371    {
372        const osg::Transform* transform = (*itr)->asTransform();
373        if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_RF)
374        {
375            bsphere.expandRadiusBy((*itr)->getBound());
376        }
377    }
378
379    return bsphere;
380}
381
382void Group::setThreadSafeRefUnref(bool threadSafe)
383{
384    Node::setThreadSafeRefUnref(threadSafe);
385
386    for(NodeList::const_iterator itr=_children.begin();
387        itr!=_children.end();
388        ++itr)
389    {
390        (*itr)->setThreadSafeRefUnref(threadSafe);
391    }
392}
393
394void Group::resizeGLObjectBuffers(unsigned int maxSize)
395{
396    Node::resizeGLObjectBuffers(maxSize);
397
398    for(NodeList::const_iterator itr=_children.begin();
399        itr!=_children.end();
400        ++itr)
401    {
402        (*itr)->resizeGLObjectBuffers(maxSize);
403    }
404}
405
406void Group::releaseGLObjects(osg::State* state) const
407{
408    Node::releaseGLObjects(state);
409
410    for(NodeList::const_iterator itr=_children.begin();
411        itr!=_children.end();
412        ++itr)
413    {
414        (*itr)->releaseGLObjects(state);
415    }
416}
Note: See TracBrowser for help on using the browser.