StateGraph
Go to the documentation of this file.
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGUTIL_STATEGRAPH
#define OSGUTIL_STATEGRAPH 1
#include <osg/Matrix>
#include <osg/Drawable>
#include <osg/StateSet>
#include <osg/State>
#include <osg/Light>
#include <osgUtil/RenderLeaf>
#include <set>
#include <vector>
#include <algorithm>
namespace osgUtil {
struct LessDepthSortFunctor
{
bool operator() (const osg::ref_ptr<RenderLeaf>& lhs,const osg::ref_ptr<RenderLeaf>& rhs)
{
return (lhs->_depth < rhs->_depth);
}
};
class OSGUTIL_EXPORT StateGraph : public osg::Object
{
public:
typedef std::map< const osg::StateSet*, osg::ref_ptr<StateGraph> > ChildList;
typedef std::vector< osg::ref_ptr<RenderLeaf> > LeafList;
StateGraph* _parent;
#ifdef OSGUTIL_RENDERBACKEND_USE_REF_PTR
osg::ref_ptr<const osg::StateSet> _stateset;
#else
const osg::StateSet* _stateset;
#endif
int _depth;
ChildList _children;
LeafList _leaves;
mutable float _averageDistance;
mutable float _minimumDistance;
osg::ref_ptr<osg::Referenced> _userData;
bool _dynamic;
StateGraph():
_parent(NULL),
_stateset(NULL),
_depth(0),
_averageDistance(0),
_minimumDistance(0),
_userData(NULL),
_dynamic(false)
{
}
StateGraph(StateGraph* parent,const osg::StateSet* stateset):
_parent(parent),
_stateset(stateset),
_depth(0),
_averageDistance(0),
_minimumDistance(0),
_userData(NULL),
_dynamic(false)
{
if (_parent) _depth = _parent->_depth + 1;
if (_parent && _parent->_dynamic) _dynamic = true;
else _dynamic = stateset->getDataVariance()==osg::Object::DYNAMIC;
}
~StateGraph() {}
virtual osg::Object* cloneType() const { return new StateGraph(); }
virtual StateGraph* cloneStateGraph() const { return new StateGraph(); }
virtual osg::Object* clone(const osg::CopyOp&) const { return new StateGraph(); }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const StateGraph*>(obj)!=0L; }
virtual const char* libraryName() const { return "osgUtil"; }
virtual const char* className() const { return "StateGraph"; }
void setUserData(osg::Referenced* obj) { _userData = obj; }
osg::Referenced* getUserData() { return _userData.get(); }
const osg::Referenced* getUserData() const { return _userData.get(); }
void setStateSet(const osg::StateSet* stateset) { _stateset = stateset; }
#ifdef OSGUTIL_RENDERBACKEND_USE_REF_PTR
const osg::StateSet* getStateSet() const { return _stateset.get(); }
#else
const osg::StateSet* getStateSet() const { return _stateset; }
#endif
inline bool empty() const
{
return _leaves.empty() && _children.empty();
}
inline bool leaves_empty() const
{
return _leaves.empty();
}
inline float getAverageDistance() const
{
if (_averageDistance==FLT_MAX && !_leaves.empty())
{
_averageDistance = 0.0f;
for(LeafList::const_iterator itr=_leaves.begin();
itr!=_leaves.end();
++itr)
{
_averageDistance += (*itr)->_depth;
}
_averageDistance /= (float)_leaves.size();
}
return _averageDistance;
}
inline float getMinimumDistance() const
{
if (_minimumDistance==FLT_MAX && !_leaves.empty())
{
LeafList::const_iterator itr=_leaves.begin();
_minimumDistance = (*itr)->_depth;
++itr;
for(;
itr!=_leaves.end();
++itr)
{
if ((*itr)->_depth<_minimumDistance) _minimumDistance=(*itr)->_depth;
}
}
return _minimumDistance;
}
inline void sortFrontToBack()
{
std::sort(_leaves.begin(),_leaves.end(),LessDepthSortFunctor());
}
void reset();
void clean();
void prune();
void resizeGLObjectBuffers(unsigned int maxSize)
{
for(ChildList::iterator itr = _children.begin();
itr != _children.end();
++itr)
{
(itr->second)->resizeGLObjectBuffers(maxSize);
}
for(LeafList::iterator itr = _leaves.begin();
itr != _leaves.end();
++itr)
{
(*itr)->resizeGLObjectBuffers(maxSize);
}
}
void releaseGLObjects(osg::State* state=0) const
{
if (_stateset) _stateset->releaseGLObjects(state);
for(ChildList::const_iterator itr = _children.begin();
itr != _children.end();
++itr)
{
(itr->second)->releaseGLObjects(state);
}
for(LeafList::const_iterator itr = _leaves.begin();
itr != _leaves.end();
++itr)
{
(*itr)->releaseGLObjects(state);
}
}
inline StateGraph* find_or_insert(const osg::StateSet* stateset)
{
// search for the appropriate state group, return it if found.
ChildList::iterator itr = _children.find(stateset);
if (itr!=_children.end()) return itr->second.get();
// create a state group and insert it into the children list
// then return the state group.
StateGraph* sg = new StateGraph(this,stateset);
_children[stateset] = sg;
return sg;
}
inline void addLeaf(RenderLeaf* leaf)
{
if (leaf)
{
_averageDistance = FLT_MAX; // signify dirty.
_minimumDistance = FLT_MAX; // signify dirty.
_leaves.push_back(leaf);
leaf->_parent = this;
if (_dynamic) leaf->_dynamic = true;
}
}
static inline void moveStateGraph(osg::State& state,StateGraph* sg_curr,StateGraph* sg_new)
{
if (sg_new==sg_curr || sg_new==NULL) return;
if (sg_curr==NULL)
{
// use return path to trace back steps to sg_new.
std::vector<StateGraph*> return_path;
return_path.reserve(sg_new->_depth+1);
// need to pop back root render graph.
do
{
return_path.push_back(sg_new);
sg_new = sg_new->_parent;
} while (sg_new);
for(std::vector<StateGraph*>::reverse_iterator itr=return_path.rbegin();
itr!=return_path.rend();
++itr)
{
StateGraph* rg = (*itr);
if (rg->getStateSet()) state.pushStateSet(rg->getStateSet());
}
return;
}
// first handle the typical case which is two state groups
// are neighbours.
if (sg_curr->_parent==sg_new->_parent)
{
// state has changed so need to pop old state.
if (sg_curr->getStateSet()) state.popStateSet();
// and push new state.
if (sg_new->getStateSet()) state.pushStateSet(sg_new->getStateSet());
return;
}
// need to pop back up to the same depth as the new state group.
while (sg_curr->_depth>sg_new->_depth)
{
if (sg_curr->getStateSet()) state.popStateSet();
sg_curr = sg_curr->_parent;
}
// use return path to trace back steps to sg_new.
std::vector<StateGraph*> return_path;
return_path.reserve(sg_new->_depth+1);
// need to pop back up to the same depth as the curr state group.
while (sg_new->_depth>sg_curr->_depth)
{
return_path.push_back(sg_new);
sg_new = sg_new->_parent;
}
// now pop back up both parent paths until they agree.
// DRT - 10/22/02
// should be this to conform with above case where two StateGraph
// nodes have the same parent
while (sg_curr != sg_new)
{
if (sg_curr->getStateSet()) state.popStateSet();
sg_curr = sg_curr->_parent;
return_path.push_back(sg_new);
sg_new = sg_new->_parent;
}
for(std::vector<StateGraph*>::reverse_iterator itr=return_path.rbegin();
itr!=return_path.rend();
++itr)
{
StateGraph* rg = (*itr);
if (rg->getStateSet()) state.pushStateSet(rg->getStateSet());
}
}
inline static void moveToRootStateGraph(osg::State& state,StateGraph* sg_curr)
{
// need to pop back all statesets and matrices.
while (sg_curr)
{
if (sg_curr->getStateSet()) state.popStateSet();
sg_curr = sg_curr->_parent;
}
}
inline static int numToPop(StateGraph* sg_curr)
{
int numToPop = 0;
// need to pop back all statesets and matrices.
while (sg_curr)
{
if (sg_curr->getStateSet()) ++numToPop;
sg_curr = sg_curr->_parent;
}
return numToPop;
}
private:
StateGraph(const StateGraph&) : osg::Object() {}
StateGraph& operator = (const StateGraph&) { return *this; }
};
}
#endif
Drawable
Light
Matrix
RenderLeaf
StateSet
State
osgUtil::RenderLeaf
Definition RenderLeaf:34
osgUtil::RenderLeaf::_parent
StateGraph * _parent
Definition RenderLeaf:92
osgUtil::RenderLeaf::_dynamic
bool _dynamic
Definition RenderLeaf:104
osgUtil::StateGraph
Definition StateGraph:42
osgUtil::StateGraph::className
virtual const char * className() const
Definition StateGraph:102
osgUtil::StateGraph::_userData
osg::ref_ptr< osg::Referenced > _userData
Definition StateGraph:64
osgUtil::StateGraph::_minimumDistance
float _minimumDistance
Definition StateGraph:62
osgUtil::StateGraph::_dynamic
bool _dynamic
Definition StateGraph:66
osgUtil::StateGraph::clean
void clean()
osgUtil::StateGraph::find_or_insert
StateGraph * find_or_insert(const osg::StateSet *stateset)
Definition StateGraph:215
osgUtil::StateGraph::_children
ChildList _children
Definition StateGraph:58
osgUtil::StateGraph::isSameKindAs
virtual bool isSameKindAs(const osg::Object *obj) const
Definition StateGraph:100
osgUtil::StateGraph::StateGraph
StateGraph(StateGraph *parent, const osg::StateSet *stateset)
Definition StateGraph:79
osgUtil::StateGraph::getUserData
osg::Referenced * getUserData()
Definition StateGraph:105
osgUtil::StateGraph::releaseGLObjects
void releaseGLObjects(osg::State *state=0) const
Definition StateGraph:196
osgUtil::StateGraph::_leaves
LeafList _leaves
Definition StateGraph:59
osgUtil::StateGraph::getAverageDistance
float getAverageDistance() const
Definition StateGraph:128
osgUtil::StateGraph::setStateSet
void setStateSet(const osg::StateSet *stateset)
Definition StateGraph:108
osgUtil::StateGraph::leaves_empty
bool leaves_empty() const
Definition StateGraph:122
osgUtil::StateGraph::cloneStateGraph
virtual StateGraph * cloneStateGraph() const
Definition StateGraph:98
osgUtil::StateGraph::numToPop
static int numToPop(StateGraph *sg_curr)
Definition StateGraph:336
osgUtil::StateGraph::cloneType
virtual osg::Object * cloneType() const
Definition StateGraph:97
osgUtil::StateGraph::_parent
StateGraph * _parent
Definition StateGraph:49
osgUtil::StateGraph::reset
void reset()
osgUtil::StateGraph::moveToRootStateGraph
static void moveToRootStateGraph(osg::State &state, StateGraph *sg_curr)
Definition StateGraph:325
osgUtil::StateGraph::StateGraph
StateGraph()
Definition StateGraph:68
osgUtil::StateGraph::addLeaf
void addLeaf(RenderLeaf *leaf)
Definition StateGraph:229
osgUtil::StateGraph::prune
void prune()
osgUtil::StateGraph::resizeGLObjectBuffers
void resizeGLObjectBuffers(unsigned int maxSize)
Definition StateGraph:179
osgUtil::StateGraph::setUserData
void setUserData(osg::Referenced *obj)
Definition StateGraph:104
osgUtil::StateGraph::ChildList
std::map< const osg::StateSet *, osg::ref_ptr< StateGraph > > ChildList
Definition StateGraph:46
osgUtil::StateGraph::getStateSet
const osg::StateSet * getStateSet() const
Definition StateGraph:113
osgUtil::StateGraph::getMinimumDistance
float getMinimumDistance() const
Definition StateGraph:145
osgUtil::StateGraph::libraryName
virtual const char * libraryName() const
Definition StateGraph:101
osgUtil::StateGraph::_averageDistance
float _averageDistance
Definition StateGraph:61
osgUtil::StateGraph::~StateGraph
~StateGraph()
Definition StateGraph:94
osgUtil::StateGraph::moveStateGraph
static void moveStateGraph(osg::State &state, StateGraph *sg_curr, StateGraph *sg_new)
Definition StateGraph:241
osgUtil::StateGraph::empty
bool empty() const
Definition StateGraph:117
osgUtil::StateGraph::_depth
int _depth
Definition StateGraph:57
osgUtil::StateGraph::sortFrontToBack
void sortFrontToBack()
Definition StateGraph:163
osgUtil::StateGraph::_stateset
const osg::StateSet * _stateset
Definition StateGraph:54
osgUtil::StateGraph::LeafList
std::vector< osg::ref_ptr< RenderLeaf > > LeafList
Definition StateGraph:47
osgUtil::StateGraph::clone
virtual osg::Object * clone(const osg::CopyOp &) const
Definition StateGraph:99
osgUtil::StateGraph::getUserData
const osg::Referenced * getUserData() const
Definition StateGraph:106
osg::CopyOp
Definition CopyOp:41
osg::Object
Definition Object:61
osg::Object::DYNAMIC
@ DYNAMIC
Definition Object:218
osg::Object::getDataVariance
DataVariance getDataVariance() const
Definition Object:231
osg::Referenced
Definition Referenced:44
osg::StateSet
Definition StateSet:46
osg::State
Definition State:80
osg::State::popStateSet
void popStateSet()
osg::State::pushStateSet
void pushStateSet(const StateSet *dstate)
osg::ref_ptr
Definition ref_ptr:32
osg::ref_ptr::get
T * get() const
Definition ref_ptr:117
osgUtil
Definition NodeVisitor:25
osg
Definition AlphaFunc:19
OSGUTIL_EXPORT
#define OSGUTIL_EXPORT
Definition osgUtil/Export:40
NULL
#define NULL
Definition osg/Export:55
osgUtil::LessDepthSortFunctor
Definition StateGraph:32
osgUtil::LessDepthSortFunctor::operator()
bool operator()(const osg::ref_ptr< RenderLeaf > &lhs, const osg::ref_ptr< RenderLeaf > &rhs)
Definition StateGraph:33