OSG  3.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StateGraph.h
Go to the documentation of this file.
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 #ifndef OSGUTIL_STATEGRAPH
15 #define OSGUTIL_STATEGRAPH 1
16 
17 #include <osg/Matrix>
18 #include <osg/Drawable>
19 #include <osg/StateSet>
20 #include <osg/State>
21 #include <osg/Light>
22 
23 #include <osgUtil/RenderLeaf>
24 
25 #include <set>
26 #include <vector>
27 #include <algorithm>
28 
29 namespace osgUtil {
30 
32 {
34  {
35  return (lhs->_depth < rhs->_depth);
36  }
37 };
38 
42 {
43  public:
44 
45 
46  typedef std::map< const osg::StateSet*, osg::ref_ptr<StateGraph> > ChildList;
47  typedef std::vector< osg::ref_ptr<RenderLeaf> > LeafList;
48 
50 
51 #ifdef OSGUTIL_RENDERBACKEND_USE_REF_PTR
53 #else
55 #endif
56 
57  int _depth;
58  ChildList _children;
59  LeafList _leaves;
60 
61  mutable float _averageDistance;
62  mutable float _minimumDistance;
63 
65 
66  bool _dynamic;
67 
69  osg::Referenced(false),
70  _parent(NULL),
71  _stateset(NULL),
72  _depth(0),
73  _averageDistance(0),
74  _minimumDistance(0),
75  _userData(NULL),
76  _dynamic(false)
77  {
78  }
79 
80  StateGraph(StateGraph* parent,const osg::StateSet* stateset):
81  osg::Referenced(false),
82  _parent(parent),
83  _stateset(stateset),
84  _depth(0),
85  _averageDistance(0),
86  _minimumDistance(0),
87  _userData(NULL),
88  _dynamic(false)
89  {
90  if (_parent) _depth = _parent->_depth + 1;
91 
92  if (_parent && _parent->_dynamic) _dynamic = true;
93  else _dynamic = stateset->getDataVariance()==osg::Object::DYNAMIC;
94  }
95 
97 
98  StateGraph* cloneType() const { return new StateGraph; }
99 
100  void setUserData(osg::Referenced* obj) { _userData = obj; }
101  osg::Referenced* getUserData() { return _userData.get(); }
102  const osg::Referenced* getUserData() const { return _userData.get(); }
103 
104  void setStateSet(const osg::StateSet* stateset) { _stateset = stateset; }
105 
106 #ifdef OSGUTIL_RENDERBACKEND_USE_REF_PTR
107  const osg::StateSet* getStateSet() const { return _stateset.get(); }
108 #else
109  const osg::StateSet* getStateSet() const { return _stateset; }
110 #endif
111 
113  inline bool empty() const
114  {
115  return _leaves.empty() && _children.empty();
116  }
117 
118  inline bool leaves_empty() const
119  {
120  return _leaves.empty();
121  }
122 
123 
124  inline float getAverageDistance() const
125  {
126  if (_averageDistance==FLT_MAX && !_leaves.empty())
127  {
128  _averageDistance = 0.0f;
129  for(LeafList::const_iterator itr=_leaves.begin();
130  itr!=_leaves.end();
131  ++itr)
132  {
133  _averageDistance += (*itr)->_depth;
134  }
135  _averageDistance /= (float)_leaves.size();
136 
137  }
138  return _averageDistance;
139  }
140 
141  inline float getMinimumDistance() const
142  {
143  if (_minimumDistance==FLT_MAX && !_leaves.empty())
144  {
145  LeafList::const_iterator itr=_leaves.begin();
146  _minimumDistance = (*itr)->_depth;
147  ++itr;
148  for(;
149  itr!=_leaves.end();
150  ++itr)
151  {
152  if ((*itr)->_depth<_minimumDistance) _minimumDistance=(*itr)->_depth;
153  }
154 
155  }
156  return _minimumDistance;
157  }
158 
159  inline void sortFrontToBack()
160  {
161  std::sort(_leaves.begin(),_leaves.end(),LessDepthSortFunctor());
162  }
163 
165  void reset();
166 
169  void clean();
170 
172  void prune();
173 
174 
175  inline StateGraph* find_or_insert(const osg::StateSet* stateset)
176  {
177  // search for the appropriate state group, return it if found.
178  ChildList::iterator itr = _children.find(stateset);
179  if (itr!=_children.end()) return itr->second.get();
180 
181  // create a state group and insert it into the children list
182  // then return the state group.
183  StateGraph* sg = new StateGraph(this,stateset);
184  _children[stateset] = sg;
185  return sg;
186  }
187 
189  inline void addLeaf(RenderLeaf* leaf)
190  {
191  if (leaf)
192  {
193  _averageDistance = FLT_MAX; // signify dirty.
194  _minimumDistance = FLT_MAX; // signify dirty.
195  _leaves.push_back(leaf);
196  leaf->_parent = this;
197  if (_dynamic) leaf->_dynamic = true;
198  }
199  }
200 
201  static inline void moveStateGraph(osg::State& state,StateGraph* sg_curr,StateGraph* sg_new)
202  {
203  if (sg_new==sg_curr || sg_new==NULL) return;
204 
205  if (sg_curr==NULL)
206  {
207 
208  // use return path to trace back steps to sg_new.
209  std::vector<StateGraph*> return_path;
210  return_path.reserve(sg_new->_depth+1);
211 
212  // need to pop back root render graph.
213  do
214  {
215  return_path.push_back(sg_new);
216  sg_new = sg_new->_parent;
217  } while (sg_new);
218 
219  for(std::vector<StateGraph*>::reverse_iterator itr=return_path.rbegin();
220  itr!=return_path.rend();
221  ++itr)
222  {
223  StateGraph* rg = (*itr);
224  if (rg->getStateSet()) state.pushStateSet(rg->getStateSet());
225  }
226  return;
227  }
228 
229 
230  // first handle the typical case which is two state groups
231  // are neighbours.
232  if (sg_curr->_parent==sg_new->_parent)
233  {
234 
235  // state has changed so need to pop old state.
236  if (sg_curr->getStateSet()) state.popStateSet();
237  // and push new state.
238  if (sg_new->getStateSet()) state.pushStateSet(sg_new->getStateSet());
239  return;
240  }
241 
242 
243  // need to pop back up to the same depth as the new state group.
244  while (sg_curr->_depth>sg_new->_depth)
245  {
246  if (sg_curr->getStateSet()) state.popStateSet();
247  sg_curr = sg_curr->_parent;
248  }
249 
250  // use return path to trace back steps to sg_new.
251  std::vector<StateGraph*> return_path;
252  return_path.reserve(sg_new->_depth+1);
253 
254  // need to pop back up to the same depth as the curr state group.
255  while (sg_new->_depth>sg_curr->_depth)
256  {
257  return_path.push_back(sg_new);
258  sg_new = sg_new->_parent;
259  }
260 
261  // now pop back up both parent paths until they agree.
262 
263  // DRT - 10/22/02
264  // should be this to conform with above case where two StateGraph
265  // nodes have the same parent
266  while (sg_curr != sg_new)
267  {
268  if (sg_curr->getStateSet()) state.popStateSet();
269  sg_curr = sg_curr->_parent;
270 
271  return_path.push_back(sg_new);
272  sg_new = sg_new->_parent;
273  }
274 
275  for(std::vector<StateGraph*>::reverse_iterator itr=return_path.rbegin();
276  itr!=return_path.rend();
277  ++itr)
278  {
279  StateGraph* rg = (*itr);
280  if (rg->getStateSet()) state.pushStateSet(rg->getStateSet());
281  }
282 
283  }
284 
285  inline static void moveToRootStateGraph(osg::State& state,StateGraph* sg_curr)
286  {
287  // need to pop back all statesets and matrices.
288  while (sg_curr)
289  {
290  if (sg_curr->getStateSet()) state.popStateSet();
291  sg_curr = sg_curr->_parent;
292  }
293 
294  }
295 
296  inline static int numToPop(StateGraph* sg_curr)
297  {
298  int numToPop = 0;
299  // need to pop back all statesets and matrices.
300  while (sg_curr)
301  {
302  if (sg_curr->getStateSet()) ++numToPop;
303  sg_curr = sg_curr->_parent;
304  }
305 
306  return numToPop;
307  }
308 
309  private:
310 
312  StateGraph(const StateGraph&):osg::Referenced() {}
314  StateGraph& operator = (const StateGraph&) { return *this; }
315 
316 };
317 
318 }
319 
320 #endif
321 
ChildList _children
Definition: StateGraph.h:58
void setUserData(osg::Referenced *obj)
Definition: StateGraph.h:100
bool empty() const
Definition: StateGraph.h:113
osg::Referenced * getUserData()
Definition: StateGraph.h:101
StateGraph(StateGraph *parent, const osg::StateSet *stateset)
Definition: StateGraph.h:80
#define NULL
Definition: Export.h:59
StateGraph * _parent
Definition: RenderLeaf.h:82
const osg::StateSet * _stateset
Definition: StateGraph.h:54
float getAverageDistance() const
Definition: StateGraph.h:124
const osg::StateSet * getStateSet() const
Definition: StateGraph.h:109
StateGraph * find_or_insert(const osg::StateSet *stateset)
Definition: StateGraph.h:175
void setStateSet(const osg::StateSet *stateset)
Definition: StateGraph.h:104
StateGraph * cloneType() const
Definition: StateGraph.h:98
osg::ref_ptr< osg::Referenced > _userData
Definition: StateGraph.h:64
DataVariance getDataVariance() const
Definition: Object.h:162
static void moveStateGraph(osg::State &state, StateGraph *sg_curr, StateGraph *sg_new)
Definition: StateGraph.h:201
T * get() const
Definition: ref_ptr.h:92
static int numToPop(StateGraph *sg_curr)
Definition: StateGraph.h:296
float getMinimumDistance() const
Definition: StateGraph.h:141
void popStateSet()
std::map< const osg::StateSet *, osg::ref_ptr< StateGraph > > ChildList
Definition: StateGraph.h:46
const osg::Referenced * getUserData() const
Definition: StateGraph.h:102
Definition: AlphaFunc.h:19
void pushStateSet(const StateSet *dstate)
static void moveToRootStateGraph(osg::State &state, StateGraph *sg_curr)
Definition: StateGraph.h:285
#define OSGUTIL_EXPORT
Definition: Export.h:40
void addLeaf(RenderLeaf *leaf)
Definition: StateGraph.h:189
bool leaves_empty() const
Definition: StateGraph.h:118
std::vector< osg::ref_ptr< RenderLeaf > > LeafList
Definition: StateGraph.h:47
bool operator()(const osg::ref_ptr< RenderLeaf > &lhs, const osg::ref_ptr< RenderLeaf > &rhs)
Definition: StateGraph.h:33
StateGraph * _parent
Definition: StateGraph.h:49
Shader generator framework.
Definition: RenderInfo.h:20