OpenSceneGraph/src/osg/Node.cpp

297 lines
8.2 KiB
C++
Raw Normal View History

#include <osg/Node>
#include <osg/Group>
#include <osg/NodeVisitor>
#include <osg/Notify>
#include <osg/OccluderNode>
2001-01-11 00:32:10 +08:00
#include <algorithm>
using namespace osg;
Node::Node()
{
_bsphere_computed = false;
_nodeMask = 0xffffffff;
2001-09-22 10:42:08 +08:00
_numChildrenRequiringAppTraversal = 0;
_cullingActive = true;
_numChildrenWithCullingDisabled = 0;
_numChildrenWithOccluderNodes = 0;
2001-01-11 00:32:10 +08:00
}
Node::Node(const Node& node,const CopyOp& copyop):
Object(node,copyop),
_bsphere(_bsphere),
_bsphere_computed(node._bsphere_computed),
_name(node._name),
_parents(), // leave empty as parentList is managed by Group.
_appCallback(node._appCallback),
_numChildrenRequiringAppTraversal(0), // assume no children yet.
_cullCallback(node._cullCallback),
_cullingActive(node._cullingActive),
_numChildrenWithCullingDisabled(0), // assume no children yet.
_numChildrenWithOccluderNodes(0),
_nodeMask(node._nodeMask),
_descriptions(node._descriptions),
_dstate(copyop(node._dstate.get()))
{
}
2001-01-11 00:32:10 +08:00
Node::~Node()
{
}
void Node::addParent(osg::Group* node)
{
_parents.push_back(node);
}
void Node::removeParent(osg::Group* node)
{
ParentList::iterator pitr = std::find(_parents.begin(),_parents.end(),node);
if (pitr!=_parents.end()) _parents.erase(pitr);
}
2001-01-11 00:32:10 +08:00
void Node::accept(NodeVisitor& nv)
{
if (nv.validNodeMask(*this))
{
nv.pushOntoNodePath(this);
nv.apply(*this);
nv.popFromNodePath();
}
2001-01-11 00:32:10 +08:00
}
2001-01-11 00:32:10 +08:00
void Node::ascend(NodeVisitor& nv)
{
std::for_each(_parents.begin(),_parents.end(),NodeAcceptOp(nv));
}
2002-05-04 06:47:57 +08:00
osg::StateSet* Node::getValidStateSet()
{
if (!_dstate) _dstate = osgNew StateSet;
return _dstate.get();
}
2001-09-22 10:42:08 +08:00
void Node::setAppCallback(NodeCallback* nc)
{
// if no changes just return.
if (_appCallback==nc) return;
// app callback has been changed, will need to update
// both _appCallback and possibly the numChildrenRequiringAppTraversal
// if the number of callbacks changes.
// update the parents numChildrenRequiringAppTraversal
// note, if _numChildrenRequiringAppTraversal!=0 then the
// parents won't be affected by any app callback change,
// so no need to inform them.
if (_numChildrenRequiringAppTraversal==0 && !_parents.empty())
{
int delta = 0;
if (_appCallback.valid()) --delta;
if (nc) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// reqired on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenRequiringAppTraversal(
(*itr)->getNumChildrenRequiringAppTraversal()+delta );
}
}
}
// set the app callback itself.
_appCallback = nc;
}
void Node::setNumChildrenRequiringAppTraversal(const int num)
{
// if no changes just return.
if (_numChildrenRequiringAppTraversal==num) return;
// note, if _appCallback is set then the
// parents won't be affected by any changes to
// _numChildrenRequiringAppTraversal so no need to inform them.
if (!_appCallback && !_parents.empty())
{
// need to pass on changes to parents.
int delta = 0;
if (_numChildrenRequiringAppTraversal>0) --delta;
if (num>0) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// reqired on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenRequiringAppTraversal(
(*itr)->getNumChildrenRequiringAppTraversal()+delta
);
}
}
}
// finally update this objects value.
_numChildrenRequiringAppTraversal=num;
}
void Node::setCullingActive(const bool active)
{
// if no changes just return.
if (_cullingActive == active) return;
// culling active has been changed, will need to update
// both _cullActive and possibly the parents numChildrenWithCullingDisabled
// if culling disabled changes.
// update the parents _numChildrenWithCullingDisabled
// note, if _numChildrenWithCullingDisabled!=0 then the
// parents won't be affected by any app callback change,
// so no need to inform them.
if (_numChildrenWithCullingDisabled==0 && !_parents.empty())
{
int delta = 0;
if (!_cullingActive) --delta;
if (!active) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// reqired on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenWithCullingDisabled(
(*itr)->getNumChildrenWithCullingDisabled()+delta );
}
}
}
// set the cullingActive itself.
_cullingActive = active;
}
void Node::setNumChildrenWithCullingDisabled(const int num)
{
// if no changes just return.
if (_numChildrenWithCullingDisabled==num) return;
// note, if _cullingActive is false then the
// parents won't be affected by any changes to
// _numChildrenWithCullingDisabled so no need to inform them.
if (_cullingActive && !_parents.empty())
{
// need to pass on changes to parents.
int delta = 0;
if (_numChildrenWithCullingDisabled>0) --delta;
if (num>0) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// reqired on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenWithCullingDisabled(
(*itr)->getNumChildrenWithCullingDisabled()+delta
);
}
}
}
// finally update this objects value.
_numChildrenWithCullingDisabled=num;
}
void Node::setNumChildrenWithOccluderNodes(const int num)
{
// if no changes just return.
if (_numChildrenWithOccluderNodes==num) return;
// note, if this node is a OccluderNode then the
// parents won't be affected by any changes to
// _numChildrenWithOccluderNodes so no need to inform them.
if (!dynamic_cast<OccluderNode*>(this) && !_parents.empty())
{
// need to pass on changes to parents.
int delta = 0;
if (_numChildrenWithOccluderNodes>0) --delta;
if (num>0) ++delta;
if (delta!=0)
{
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// reqired on this subgraph.
for(ParentList::iterator itr =_parents.begin();
itr != _parents.end();
++itr)
{
(*itr)->setNumChildrenWithOccluderNodes(
(*itr)->getNumChildrenWithOccluderNodes()+delta
);
}
}
}
// finally update this objects value.
_numChildrenWithOccluderNodes=num;
}
const bool Node::containsOccluderNodes() const
{
return _numChildrenWithOccluderNodes>0 || dynamic_cast<const OccluderNode*>(this);
}
const bool Node::computeBound() const
2001-01-11 00:32:10 +08:00
{
_bsphere.init();
return false;
}
void Node::dirtyBound()
{
if (_bsphere_computed)
{
_bsphere_computed = false;
// dirty parent bounding sphere's to ensure that all are valid.
for(ParentList::iterator itr=_parents.begin();
itr!=_parents.end();
++itr)
2001-01-11 00:32:10 +08:00
{
(*itr)->dirtyBound();
}
}
}