OpenSceneGraph/src/osg/Group.cpp

290 lines
7.8 KiB
C++
Raw Normal View History

2001-01-11 00:32:10 +08:00
#include <stdio.h>
#include <math.h>
#include <osg/Group>
#include <osg/BoundingBox>
#include <osg/Transform>
#include <osg/OccluderNode>
2001-01-11 00:32:10 +08:00
#include <algorithm>
using namespace osg;
Group::Group()
{
}
Group::Group(const Group& group,const CopyOp& copyop):
Node(group,copyop)
{
for(ChildList::const_iterator itr=group._children.begin();
itr!=group._children.end();
++itr)
{
Node* child = copyop(itr->get());
if (child) addChild(child);
}
}
2001-01-11 00:32:10 +08:00
Group::~Group()
{
// remove reference to this from children's parent lists.
2001-01-11 00:32:10 +08:00
for(ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
2001-01-11 00:32:10 +08:00
{
(*itr)->removeParent(this);
2001-01-11 00:32:10 +08:00
}
}
void Group::traverse(NodeVisitor& nv)
{
for(ChildList::iterator itr=_children.begin();
itr!=_children.end();
++itr)
2001-01-11 00:32:10 +08:00
{
(*itr)->accept(nv);
}
}
bool Group::addChild( Node *child )
{
if (child && !containsNode(child))
{
// note ref_ptr<> automatically handles incrementing child's reference count.
_children.push_back(child);
// register as parent of child.
child->addParent(this);
2001-01-11 00:32:10 +08:00
dirtyBound();
2001-09-22 10:42:08 +08:00
// could now require app traversal thanks to the new subgraph,
// so need to check and update if required.
if (child->getNumChildrenRequiringAppTraversal()>0 ||
child->getAppCallback())
{
setNumChildrenRequiringAppTraversal(
getNumChildrenRequiringAppTraversal()+1
);
}
// could now require disabling of culling thanks to the new subgraph,
// so need to check and update if required.
if (child->getNumChildrenWithCullingDisabled()>0 ||
!child->getCullingActive())
{
setNumChildrenWithCullingDisabled(
getNumChildrenWithCullingDisabled()+1
);
}
if (child->getNumChildrenWithOccluderNodes()>0 ||
dynamic_cast<osg::OccluderNode*>(child))
{
setNumChildrenWithOccluderNodes(
getNumChildrenWithOccluderNodes()+1
);
}
2001-01-11 00:32:10 +08:00
return true;
}
else return false;
}
2001-01-11 00:32:10 +08:00
bool Group::removeChild( Node *child )
{
ChildList::iterator itr = findNode(child);
if (itr!=_children.end())
{
// remove this group from the child parent list.
child->removeParent(this);
2001-09-22 10:42:08 +08:00
// could now require app traversal thanks to the new subgraph,
// so need to check and update if required.
// note, need to do this checking before the erase of the child
// otherwise child will be invalid.
if (child->getNumChildrenRequiringAppTraversal()>0 ||
child->getAppCallback())
{
setNumChildrenRequiringAppTraversal(
getNumChildrenRequiringAppTraversal()-1
);
}
if (child->getNumChildrenWithCullingDisabled()>0 ||
!child->getCullingActive())
{
setNumChildrenWithCullingDisabled(
getNumChildrenWithCullingDisabled()-1
);
}
if (child->getNumChildrenWithOccluderNodes()>0 ||
dynamic_cast<osg::OccluderNode*>(child))
{
setNumChildrenWithOccluderNodes(
getNumChildrenWithOccluderNodes()-1
);
}
2001-01-11 00:32:10 +08:00
// note ref_ptr<> automatically handles decrementing child's reference count.
_children.erase(itr);
dirtyBound();
2001-09-22 10:42:08 +08:00
2001-01-11 00:32:10 +08:00
return true;
}
else return false;
}
2001-01-11 00:32:10 +08:00
bool Group::replaceChild( Node *origNode, Node *newNode )
{
if (newNode==NULL || origNode==newNode) return false;
unsigned int pos = getChildIndex(origNode);
if (pos<_children.size())
{
return setChild(pos,newNode);
}
return false;
}
bool Group::setChild( unsigned int i, Node* newNode )
{
if (i<_children.size() && newNode)
2001-01-11 00:32:10 +08:00
{
ref_ptr<Node> origNode = _children[i];
// first remove for origNode's parent list.
origNode->removeParent(this);
2001-01-11 00:32:10 +08:00
// note ref_ptr<> automatically handles decrementing origNode's reference count,
// and inccrementing newNode's reference count.
_children[i] = newNode;
2001-01-11 00:32:10 +08:00
// register as parent of child.
newNode->addParent(this);
2001-01-11 00:32:10 +08:00
dirtyBound();
// could now require app traversal thanks to the new subgraph,
// so need to check and update if required.
int delta_numChildrenRequiringAppTraversal = 0;
if (origNode->getNumChildrenRequiringAppTraversal()>0 ||
origNode->getAppCallback())
{
--delta_numChildrenRequiringAppTraversal;
}
if (newNode->getNumChildrenRequiringAppTraversal()>0 ||
newNode->getAppCallback())
{
++delta_numChildrenRequiringAppTraversal;
}
if (delta_numChildrenRequiringAppTraversal!=0)
{
setNumChildrenRequiringAppTraversal(
getNumChildrenRequiringAppTraversal()+delta_numChildrenRequiringAppTraversal
);
}
// could now require disabling of culling thanks to the new subgraph,
// so need to check and update if required.
int delta_numChildrenWithCullingDisabled = 0;
if (origNode->getNumChildrenWithCullingDisabled()>0 ||
!origNode->getCullingActive())
{
--delta_numChildrenWithCullingDisabled;
}
if (newNode->getNumChildrenWithCullingDisabled()>0 ||
!newNode->getCullingActive())
{
++delta_numChildrenWithCullingDisabled;
}
if (delta_numChildrenWithCullingDisabled!=0)
{
setNumChildrenWithCullingDisabled(
getNumChildrenWithCullingDisabled()+delta_numChildrenWithCullingDisabled
);
}
// could now require disabling of culling thanks to the new subgraph,
// so need to check and update if required.
int delta_numChildrenWithOccluderNodes = 0;
if (origNode->getNumChildrenWithOccluderNodes()>0 ||
!origNode->getCullingActive())
{
--delta_numChildrenWithOccluderNodes;
}
if (newNode->getNumChildrenWithOccluderNodes()>0 ||
!newNode->getCullingActive())
{
++delta_numChildrenWithOccluderNodes;
}
if (delta_numChildrenWithOccluderNodes!=0)
{
setNumChildrenWithOccluderNodes(
getNumChildrenWithOccluderNodes()+delta_numChildrenWithOccluderNodes
);
}
2001-01-11 00:32:10 +08:00
return true;
}
else return false;
}
bool Group::computeBound() const
2001-01-11 00:32:10 +08:00
{
_bsphere_computed = true;
_bsphere.init();
if (_children.empty()) return false;
// note, special handling of the case when a child is an Transform,
// such that only Transforms which are relative to their parents coordinates frame (i.e this group)
// are handled, Transform relative to and absolute reference frame are ignored.
2001-01-11 00:32:10 +08:00
BoundingBox bb;
bb.init();
ChildList::const_iterator itr;
2001-01-11 00:32:10 +08:00
for(itr=_children.begin();
itr!=_children.end();
++itr)
{
const osg::Transform* transform = (*itr)->asTransform();
if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_TO_PARENTS)
{
bb.expandBy((*itr)->getBound());
}
}
2001-01-11 00:32:10 +08:00
if (!bb.valid()) return false;
2001-01-11 00:32:10 +08:00
_bsphere._center = bb.center();
_bsphere._radius = 0.0f;
for(itr=_children.begin();
itr!=_children.end();
++itr)
{
const osg::Transform* transform = (*itr)->asTransform();
if (!transform || transform->getReferenceFrame()==osg::Transform::RELATIVE_TO_PARENTS)
{
_bsphere.expandRadiusBy((*itr)->getBound());
}
}
2001-01-11 00:32:10 +08:00
return true;
}