CullStack 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 OSG_CULLSTACK
  14. #define OSG_CULLSTACK 1
  15. #include <osg/CullingSet>
  16. #include <osg/CullSettings>
  17. #include <osg/Viewport>
  18. #include <osg/fast_back_stack>
  19. #include <osg/Transform>
  20. namespace osg {
  21. /** A CullStack class which accumulates the current project, modelview matrices
  22. and the CullingSet. */
  23. class OSG_EXPORT CullStack : public osg::CullSettings
  24. {
  25. public:
  26. CullStack();
  27. CullStack(const CullStack& cs);
  28. ~CullStack();
  29. typedef std::vector<ShadowVolumeOccluder> OccluderList;
  30. void reset();
  31. void pushCullingSet();
  32. void popCullingSet();
  33. void setOccluderList(const ShadowVolumeOccluderList& svol) { _occluderList = svol; }
  34. ShadowVolumeOccluderList& getOccluderList() { return _occluderList; }
  35. const ShadowVolumeOccluderList& getOccluderList() const { return _occluderList; }
  36. void pushViewport(osg::Viewport* viewport);
  37. void popViewport();
  38. void pushProjectionMatrix(osg::RefMatrix* matrix);
  39. void popProjectionMatrix();
  40. void pushModelViewMatrix(osg::RefMatrix* matrix, Transform::ReferenceFrame referenceFrame);
  41. void popModelViewMatrix();
  42. inline float getFrustumVolume() { if (_frustumVolume<0.0f) computeFrustumVolume(); return _frustumVolume; }
  43. /** Compute the pixel size of an object at position v, with specified radius.*/
  44. float pixelSize(const Vec3& v,float radius) const
  45. {
  46. return getCurrentCullingSet().pixelSize(v,radius);
  47. }
  48. /** Compute the pixel size of the bounding sphere.*/
  49. float pixelSize(const BoundingSphere& bs) const
  50. {
  51. return pixelSize(bs.center(),bs.radius());
  52. }
  53. /** Compute the pixel size of an object at position v, with specified radius. fabs()ed to always be positive. */
  54. float clampedPixelSize(const Vec3& v,float radius) const
  55. {
  56. return getCurrentCullingSet().clampedPixelSize(v,radius);
  57. }
  58. /** Compute the pixel size of the bounding sphere. fabs()ed to always be positive. */
  59. float clampedPixelSize(const BoundingSphere& bs) const
  60. {
  61. return clampedPixelSize(bs.center(),bs.radius());
  62. }
  63. inline void disableAndPushOccludersCurrentMask(NodePath& nodePath)
  64. {
  65. getCurrentCullingSet().disableAndPushOccludersCurrentMask(nodePath);
  66. }
  67. inline void popOccludersCurrentMask(NodePath& nodePath)
  68. {
  69. getCurrentCullingSet().popOccludersCurrentMask(nodePath);
  70. }
  71. inline bool isCulled(const std::vector<Vec3>& vertices)
  72. {
  73. return getCurrentCullingSet().isCulled(vertices);
  74. }
  75. inline bool isCulled(const BoundingBox& bb)
  76. {
  77. return bb.valid() && getCurrentCullingSet().isCulled(bb);
  78. }
  79. inline bool isCulled(const BoundingSphere& bs)
  80. {
  81. return getCurrentCullingSet().isCulled(bs);
  82. }
  83. inline bool isCulled(const osg::Node& node)
  84. {
  85. if (node.isCullingActive())
  86. {
  87. return getCurrentCullingSet().isCulled(node.getBound());
  88. }
  89. else
  90. {
  91. getCurrentCullingSet().resetCullingMask();
  92. return false;
  93. }
  94. }
  95. inline void pushCurrentMask()
  96. {
  97. getCurrentCullingSet().pushCurrentMask();
  98. }
  99. inline void popCurrentMask()
  100. {
  101. getCurrentCullingSet().popCurrentMask();
  102. }
  103. typedef std::vector< CullingSet > CullingStack;
  104. inline CullingStack& getClipSpaceCullingStack() { return _clipspaceCullingStack; }
  105. inline CullingStack& getProjectionCullingStack() { return _projectionCullingStack; }
  106. inline CullingStack& getModelViewCullingStack() { return _modelviewCullingStack; }
  107. inline CullingSet& getCurrentCullingSet() { return *_back_modelviewCullingStack; }
  108. inline const CullingSet& getCurrentCullingSet() const { return *_back_modelviewCullingStack; }
  109. inline osg::Viewport* getViewport();
  110. inline const osg::Viewport* getViewport() const;
  111. inline osg::RefMatrix* getModelViewMatrix();
  112. inline const osg::RefMatrix* getModelViewMatrix() const;
  113. inline osg::RefMatrix* getProjectionMatrix();
  114. inline const osg::RefMatrix* getProjectionMatrix() const;
  115. inline osg::Matrix getWindowMatrix() const;
  116. inline const osg::RefMatrix* getMVPW();
  117. inline const osg::Vec3& getReferenceViewPoint() const { return _referenceViewPoints.back(); }
  118. inline void pushReferenceViewPoint(const osg::Vec3& viewPoint) { _referenceViewPoints.push_back(viewPoint); }
  119. inline void popReferenceViewPoint() { _referenceViewPoints.pop_back(); }
  120. inline const osg::Vec3& getEyeLocal() const { return _eyePointStack.back(); }
  121. inline const osg::Vec3& getViewPointLocal() const { return _viewPointStack.back(); }
  122. inline const osg::Vec3 getUpLocal() const
  123. {
  124. const osg::Matrix& matrix = *_modelviewStack.back();
  125. return osg::Vec3(matrix(0,1),matrix(1,1),matrix(2,1));
  126. }
  127. inline const osg::Vec3 getLookVectorLocal() const
  128. {
  129. const osg::Matrix& matrix = *_modelviewStack.back();
  130. return osg::Vec3(-matrix(0,2),-matrix(1,2),-matrix(2,2));
  131. }
  132. typedef fast_back_stack< ref_ptr<RefMatrix> > MatrixStack;
  133. MatrixStack& getProjectionStack() { return _projectionStack; }
  134. const MatrixStack& getProjectionStack() const { return _projectionStack; }
  135. MatrixStack& getModelViewStack() { return _modelviewStack; }
  136. const MatrixStack& getModelViewStack() const { return _modelviewStack; }
  137. MatrixStack& getMVPWStack() { return _MVPW_Stack; }
  138. const MatrixStack& getMVPWStack() const { return _MVPW_Stack; }
  139. protected:
  140. // base set of shadow volume occluder to use in culling.
  141. ShadowVolumeOccluderList _occluderList;
  142. MatrixStack _projectionStack;
  143. MatrixStack _modelviewStack;
  144. MatrixStack _MVPW_Stack;
  145. typedef fast_back_stack<ref_ptr<Viewport> > ViewportStack;
  146. ViewportStack _viewportStack;
  147. typedef fast_back_stack<Vec3> EyePointStack;
  148. EyePointStack _referenceViewPoints;
  149. EyePointStack _eyePointStack;
  150. EyePointStack _viewPointStack;
  151. CullingStack _clipspaceCullingStack;
  152. CullingStack _projectionCullingStack;
  153. CullingStack _modelviewCullingStack;
  154. unsigned int _index_modelviewCullingStack;
  155. CullingSet* _back_modelviewCullingStack;
  156. void computeFrustumVolume();
  157. float _frustumVolume;
  158. unsigned int _bbCornerNear;
  159. unsigned int _bbCornerFar;
  160. ref_ptr<osg::RefMatrix> _identity;
  161. typedef std::vector< osg::ref_ptr<osg::RefMatrix> > MatrixList;
  162. MatrixList _reuseMatrixList;
  163. unsigned int _currentReuseMatrixIndex;
  164. inline osg::RefMatrix* createOrReuseMatrix(const osg::Matrix& value);
  165. };
  166. inline osg::Viewport* CullStack::getViewport()
  167. {
  168. return _viewportStack.empty() ? 0 : _viewportStack.back().get();
  169. }
  170. inline const osg::Viewport* CullStack::getViewport() const
  171. {
  172. return _viewportStack.empty() ? 0 : _viewportStack.back().get();
  173. }
  174. inline osg::RefMatrix* CullStack::getModelViewMatrix()
  175. {
  176. return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get();
  177. }
  178. inline const osg::RefMatrix* CullStack::getModelViewMatrix() const
  179. {
  180. return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get();
  181. }
  182. inline osg::RefMatrix* CullStack::getProjectionMatrix()
  183. {
  184. return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get();
  185. }
  186. inline const osg::RefMatrix* CullStack::getProjectionMatrix() const
  187. {
  188. return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get();
  189. }
  190. inline osg::Matrix CullStack::getWindowMatrix() const
  191. {
  192. if (!_viewportStack.empty())
  193. {
  194. osg::Viewport* viewport = _viewportStack.back().get();
  195. return viewport->computeWindowMatrix();
  196. }
  197. else
  198. {
  199. return *_identity;
  200. }
  201. }
  202. inline const osg::RefMatrix* CullStack::getMVPW()
  203. {
  204. if (!_MVPW_Stack.empty())
  205. {
  206. if (!_MVPW_Stack.back())
  207. {
  208. _MVPW_Stack.back() = createOrReuseMatrix(*getModelViewMatrix());
  209. (*_MVPW_Stack.back()) *= *(getProjectionMatrix());
  210. (*_MVPW_Stack.back()) *= getWindowMatrix();
  211. }
  212. return _MVPW_Stack.back().get();
  213. }
  214. else
  215. {
  216. return _identity.get();
  217. }
  218. }
  219. inline RefMatrix* CullStack::createOrReuseMatrix(const osg::Matrix& value)
  220. {
  221. // skip of any already reused matrix.
  222. while (_currentReuseMatrixIndex<_reuseMatrixList.size() &&
  223. _reuseMatrixList[_currentReuseMatrixIndex]->referenceCount()>1)
  224. {
  225. ++_currentReuseMatrixIndex;
  226. }
  227. // if still within list, element must be singularly referenced
  228. // there return it to be reused.
  229. if (_currentReuseMatrixIndex<_reuseMatrixList.size())
  230. {
  231. RefMatrix* matrix = _reuseMatrixList[_currentReuseMatrixIndex++].get();
  232. matrix->set(value);
  233. return matrix;
  234. }
  235. // otherwise need to create new matrix.
  236. osg::RefMatrix* matrix = new RefMatrix(value);
  237. _reuseMatrixList.push_back(matrix);
  238. ++_currentReuseMatrixIndex;
  239. return matrix;
  240. }
  241. } // end of namespace
  242. #endif