123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /* -*-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 OSG_CullingSet
- #define OSG_CullingSet 1
- #include <osg/Polytope>
- #include <osg/ShadowVolumeOccluder>
- #include <osg/Viewport>
- #include <math.h>
- namespace osg {
- #define COMPILE_WITH_SHADOW_OCCLUSION_CULLING
- /** A CullingSet class which contains a frustum and a list of occluders. */
- class OSG_EXPORT CullingSet : public Referenced
- {
- public:
- typedef std::pair< osg::ref_ptr<osg::StateSet>, osg::Polytope > StateFrustumPair;
- typedef std::vector< StateFrustumPair > StateFrustumList;
- CullingSet();
- CullingSet(const CullingSet& cs):
- Referenced(),
- _mask(cs._mask),
- _frustum(cs._frustum),
- _stateFrustumList(cs._stateFrustumList),
- _occluderList(cs._occluderList),
- _pixelSizeVector(cs._pixelSizeVector),
- _smallFeatureCullingPixelSize(cs._smallFeatureCullingPixelSize)
- {
- }
- CullingSet(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector):
- _mask(cs._mask),
- _frustum(cs._frustum),
- _stateFrustumList(cs._stateFrustumList),
- _occluderList(cs._occluderList),
- _pixelSizeVector(pixelSizeVector),
- _smallFeatureCullingPixelSize(cs._smallFeatureCullingPixelSize)
- {
- _frustum.transformProvidingInverse(matrix);
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- itr->transformProvidingInverse(matrix);
- }
- }
- CullingSet& operator = (const CullingSet& cs)
- {
- if (this==&cs) return *this;
- _mask = cs._mask;
- _frustum = cs._frustum;
- _stateFrustumList = cs._stateFrustumList;
- _occluderList = cs._occluderList;
- _pixelSizeVector = cs._pixelSizeVector;
- _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
- return *this;
- }
- inline void set(const CullingSet& cs)
- {
- _mask = cs._mask;
- _frustum = cs._frustum;
- _stateFrustumList = cs._stateFrustumList;
- _occluderList = cs._occluderList;
- _pixelSizeVector = cs._pixelSizeVector;
- _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
- }
- inline void set(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector)
- {
- _mask = cs._mask;
- _stateFrustumList = cs._stateFrustumList;
- _occluderList = cs._occluderList;
- _pixelSizeVector = pixelSizeVector;
- _smallFeatureCullingPixelSize = cs._smallFeatureCullingPixelSize;
- //_frustum = cs._frustum;
- //_frustum.transformProvidingInverse(matrix);
- _frustum.setAndTransformProvidingInverse(cs._frustum,matrix);
- for(StateFrustumList::iterator sitr=_stateFrustumList.begin();
- sitr!=_stateFrustumList.end();
- ++sitr)
- {
- sitr->second.transformProvidingInverse(matrix);
- }
- for(OccluderList::iterator oitr=_occluderList.begin();
- oitr!=_occluderList.end();
- ++oitr)
- {
- oitr->transformProvidingInverse(matrix);
- }
- }
- typedef std::vector<ShadowVolumeOccluder> OccluderList;
- typedef int Mask;
- enum MaskValues
- {
- NO_CULLING = 0x0,
- VIEW_FRUSTUM_SIDES_CULLING = 0x1,
- NEAR_PLANE_CULLING = 0x2,
- FAR_PLANE_CULLING = 0x4,
- VIEW_FRUSTUM_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
- NEAR_PLANE_CULLING|
- FAR_PLANE_CULLING,
- SMALL_FEATURE_CULLING = 0x8,
- SHADOW_OCCLUSION_CULLING = 0x10,
- DEFAULT_CULLING = VIEW_FRUSTUM_SIDES_CULLING|
- SMALL_FEATURE_CULLING|
- SHADOW_OCCLUSION_CULLING,
- ENABLE_ALL_CULLING = VIEW_FRUSTUM_CULLING|
- SMALL_FEATURE_CULLING|
- SHADOW_OCCLUSION_CULLING
- };
- void setCullingMask(Mask mask) { _mask = mask; }
- Mask getCullingMask() const { return _mask; }
- void setFrustum(Polytope& cv) { _frustum = cv; }
- Polytope& getFrustum() { return _frustum; }
- const Polytope& getFrustum() const { return _frustum; }
- void addStateFrustum(StateSet* stateset, Polytope& polytope) { _stateFrustumList.push_back(StateFrustumPair(stateset,polytope)); }
- void getStateFrustumList(StateFrustumList& sfl) { _stateFrustumList = sfl; }
- StateFrustumList& getStateFrustumList() { return _stateFrustumList; }
- void addOccluder(ShadowVolumeOccluder& cv) { _occluderList.push_back(cv); }
- void setPixelSizeVector(const Vec4& v) { _pixelSizeVector = v; }
- Vec4& getPixelSizeVector() { return _pixelSizeVector; }
- const Vec4& getPixelSizeVector() const { return _pixelSizeVector; }
- /** Threshold at which small features are culled.
- \param value Bounding volume size in screen space. Default is 2.0. */
- void setSmallFeatureCullingPixelSize(float value) { _smallFeatureCullingPixelSize=value; }
- float& getSmallFeatureCullingPixelSize() { return _smallFeatureCullingPixelSize; }
- float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
- /** Compute the pixel of an object at position v, with specified radius.*/
- float pixelSize(const Vec3& v,float radius) const { return radius/(v*_pixelSizeVector); }
- /** Compute the pixel of a bounding sphere.*/
- float pixelSize(const BoundingSphere& bs) const { return bs.radius()/(bs.center()*_pixelSizeVector); }
- /** Compute the pixel of an object at position v, with specified radius. fabs()ed to always be positive. */
- float clampedPixelSize(const Vec3& v,float radius) const { return fabs(pixelSize(v, radius)); }
- /** Compute the pixel of a bounding sphere. fabs()ed to always be positive. */
- float clampedPixelSize(const BoundingSphere& bs) const { return fabs(pixelSize(bs)); }
- inline bool isCulled(const std::vector<Vec3>& vertices)
- {
- if (_mask&VIEW_FRUSTUM_CULLING)
- {
- // is it outside the view frustum...
- if (!_frustum.contains(vertices)) return true;
- }
- if (_mask&SMALL_FEATURE_CULLING)
- {
- }
- if (_mask&SHADOW_OCCLUSION_CULLING)
- {
- // is it in one of the shadow occluder volumes.
- if (!_occluderList.empty())
- {
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- if (itr->contains(vertices)) return true;
- }
- }
- }
- return false;
- }
- inline bool isCulled(const BoundingBox& bb)
- {
- if (_mask&VIEW_FRUSTUM_CULLING)
- {
- // is it outside the view frustum...
- if (!_frustum.contains(bb)) return true;
- }
- if (_mask&SMALL_FEATURE_CULLING)
- {
- }
- if (_mask&SHADOW_OCCLUSION_CULLING)
- {
- // is it in one of the shadow occluder volumes.
- if (!_occluderList.empty())
- {
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- if (itr->contains(bb)) return true;
- }
- }
- }
- return false;
- }
- inline bool isCulled(const BoundingSphere& bs)
- {
- if (_mask&VIEW_FRUSTUM_CULLING)
- {
- // is it outside the view frustum...
- if (!_frustum.contains(bs)) return true;
- }
- if (_mask&SMALL_FEATURE_CULLING)
- {
- if (((bs.center()*_pixelSizeVector)*_smallFeatureCullingPixelSize)>bs.radius()) return true;
- }
- #ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
- if (_mask&SHADOW_OCCLUSION_CULLING)
- {
- // is it in one of the shadow occluder volumes.
- if (!_occluderList.empty())
- {
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- if (itr->contains(bs)) return true;
- }
- }
- }
- #endif
- return false;
- }
- inline void pushCurrentMask()
- {
- _frustum.pushCurrentMask();
- if (!_stateFrustumList.empty())
- {
- for(StateFrustumList::iterator itr=_stateFrustumList.begin();
- itr!=_stateFrustumList.end();
- ++itr)
- {
- itr->second.pushCurrentMask();
- }
- }
- #ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
- if (!_occluderList.empty())
- {
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- itr->pushCurrentMask();
- }
- }
- #endif
- }
- inline void popCurrentMask()
- {
- _frustum.popCurrentMask();
- if (!_stateFrustumList.empty())
- {
- for(StateFrustumList::iterator itr=_stateFrustumList.begin();
- itr!=_stateFrustumList.end();
- ++itr)
- {
- itr->second.popCurrentMask();
- }
- }
- #ifdef COMPILE_WITH_SHADOW_OCCLUSION_CULLING
- if (!_occluderList.empty())
- {
- for(OccluderList::iterator itr=_occluderList.begin();
- itr!=_occluderList.end();
- ++itr)
- {
- itr->popCurrentMask();
- }
- }
- #endif
- }
- inline void resetCullingMask()
- {
- _frustum.setResultMask(_frustum.getCurrentMask());
- }
- void disableAndPushOccludersCurrentMask(NodePath& nodePath);
- void popOccludersCurrentMask(NodePath& nodePath);
- static osg::Vec4 computePixelSizeVector(const Viewport& W, const Matrix& P, const Matrix& M);
- virtual ~CullingSet();
- protected:
- Mask _mask;
- Polytope _frustum;
- StateFrustumList _stateFrustumList;
- OccluderList _occluderList;
- Vec4 _pixelSizeVector;
- float _smallFeatureCullingPixelSize;
- };
- } // end of namespace
- #endif
|