StateGraph 11 KB

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