Renamed osgUtil::RenderGraph to osgUtil::StateGraph
This commit is contained in:
285
include/osgUtil/StateGraph
Normal file
285
include/osgUtil/StateGraph
Normal file
@@ -0,0 +1,285 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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 LeafDepthSortFunctor
|
||||
{
|
||||
bool operator() (const osg::ref_ptr<RenderLeaf>& lhs,const osg::ref_ptr<RenderLeaf>& rhs)
|
||||
{
|
||||
return (lhs->_depth>rhs->_depth);
|
||||
}
|
||||
};
|
||||
|
||||
/** StateGraph - contained in a renderBin, defines the scene to be drawn.
|
||||
*/
|
||||
class OSGUTIL_EXPORT StateGraph : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
typedef std::map< const osg::StateSet*, osg::ref_ptr<StateGraph> > ChildList;
|
||||
typedef std::vector< osg::ref_ptr<RenderLeaf> > LeafList;
|
||||
|
||||
StateGraph* _parent;
|
||||
const osg::StateSet* _stateset;
|
||||
|
||||
int _depth;
|
||||
ChildList _children;
|
||||
LeafList _leaves;
|
||||
|
||||
mutable float _averageDistance;
|
||||
mutable float _minimumDistance;
|
||||
|
||||
osg::ref_ptr<osg::Referenced> _userData;
|
||||
|
||||
|
||||
StateGraph():
|
||||
_parent(NULL),
|
||||
_stateset(NULL),
|
||||
_depth(0),
|
||||
_averageDistance(0),
|
||||
_minimumDistance(0),
|
||||
_userData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
StateGraph(StateGraph* parent,const osg::StateSet* stateset):
|
||||
_parent(parent),
|
||||
_stateset(stateset),
|
||||
_depth(0),
|
||||
_averageDistance(0),
|
||||
_minimumDistance(0),
|
||||
_userData(NULL)
|
||||
{
|
||||
if (_parent) _depth = _parent->_depth + 1;
|
||||
}
|
||||
|
||||
~StateGraph() {}
|
||||
|
||||
StateGraph* cloneType() const { return new StateGraph; }
|
||||
|
||||
void setUserData(osg::Referenced* obj) { _userData = obj; }
|
||||
osg::Referenced* getUserData() { return _userData.get(); }
|
||||
const osg::Referenced* getUserData() const { return _userData.get(); }
|
||||
|
||||
|
||||
/** return true if all of drawables, lights and children are empty.*/
|
||||
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(),LeafDepthSortFunctor());
|
||||
}
|
||||
|
||||
/** Reset the internal contents of a StateGraph, including deleting all children.*/
|
||||
void reset();
|
||||
|
||||
/** Recursively clean the StateGraph of all its drawables, lights and depths.
|
||||
* Leaves children intact, and ready to be populated again.*/
|
||||
void clean();
|
||||
|
||||
/** Recursively prune the StateGraph of empty children.*/
|
||||
void prune();
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** add a render leaf.*/
|
||||
inline void addLeaf(RenderLeaf* leaf)
|
||||
{
|
||||
if (leaf)
|
||||
{
|
||||
_averageDistance = FLT_MAX; // signify dirty.
|
||||
_minimumDistance = FLT_MAX; // signify dirty.
|
||||
_leaves.push_back(leaf);
|
||||
leaf->_parent = this;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// 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->_stateset) state.pushStateSet(rg->_stateset);
|
||||
}
|
||||
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->_stateset) state.popStateSet();
|
||||
// and push new state.
|
||||
if (sg_new->_stateset) state.pushStateSet(sg_new->_stateset);
|
||||
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->_stateset) state.popStateSet();
|
||||
sg_curr = sg_curr->_parent;
|
||||
}
|
||||
|
||||
// use return path to trace back steps to sg_new.
|
||||
std::vector<StateGraph*> return_path;
|
||||
|
||||
// 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->_stateset) 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->_stateset) state.pushStateSet(rg->_stateset);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline static void moveToRootStateGraph(osg::State& state,StateGraph* sg_curr)
|
||||
{
|
||||
// need to pop back all statesets and matrices.
|
||||
while (sg_curr)
|
||||
{
|
||||
if (sg_curr->_stateset) state.popStateSet();
|
||||
sg_curr = sg_curr->_parent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// disallow copy construction.
|
||||
StateGraph(const StateGraph&):osg::Referenced() {}
|
||||
/// disallow copy operator.
|
||||
StateGraph& operator = (const StateGraph&) { return *this; }
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user