diff --git a/include/osg/CullingSet b/include/osg/CullingSet new file mode 100644 index 000000000..a5d17362b --- /dev/null +++ b/include/osg/CullingSet @@ -0,0 +1,165 @@ +//C++ header - Open Scene Graph - Copyright (C) 1998-2001 Robert Osfield +//Distributed under the terms of the GNU Library General Public License (LGPL) +//as published by the Free Software Foundation. + +#ifndef OSG_CullingSet +#define OSG_CullingSet 1 + +#include +#include +#include + +namespace osg { + +/** A CullingSet class which contains a frustum and a list of occluder. */ +class SG_EXPORT CullingSet : public Referenced +{ + + public: + + + CullingSet(); + CullingSet(const CullingSet& cs,const osg::Matrix& matrix): + _mask(cs._mask), + _clippingVolume(cs._clippingVolume), + _occluderList(cs._occluderList), + _pixelSizeOffset(cs._pixelSizeOffset), + _pixelSizeVector(cs._pixelSizeVector) + { + _clippingVolume.transformProvidingInverse(matrix); + for(OccluderList::iterator itr=_occluderList.begin(); + itr!=_occluderList.end(); + ++itr) + { + itr->transformProvidingInverse(matrix); + } + } + + ~CullingSet(); + + typedef std::vector OccluderList; + + typedef unsigned int Mask; + + enum MaskValues + { + VIEW_FRUSTUM_CULLING = 0x1, + SMALL_FEATURE_CULLING = 0x2, + SHADOW_OCCLUSION_CULLING = 0x4, + ALL_CULLING = 0xffffffff + }; + + void setCullingMask(Mask mask) { _mask = mask; } + + void setFrustum(Polytope& cv) { _clippingVolume = cv; } + + Polytope& getFrustum() { return _clippingVolume; } + + void addOccluder(ShadowOccluderVolume& cv) { _occluderList.push_back(cv); } + + inline bool isCulled(const BoundingBox& bb) + { + if (_mask&VIEW_FRUSTUM_CULLING) + { + // is it outside the view frustum... + if (!_clippingVolume.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 (!_clippingVolume.contains(bs)) return true; + } + + if (_mask&SMALL_FEATURE_CULLING) + { + if ((bs.center()*_pixelSizeVector+_pixelSizeOffset)>bs.radius()) return true; + } + + 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; + } + } + } + + return false; + } + + inline void pushCurrentMask() + { + _clippingVolume.pushCurrentMask(); + + if (!_occluderList.empty()) + { + for(OccluderList::iterator itr=_occluderList.begin(); + itr!=_occluderList.end(); + ++itr) + { + itr->pushCurrentMask(); + } + } + } + + inline void popCurrentMask() + { + _clippingVolume.popCurrentMask(); + + if (!_occluderList.empty()) + { + for(OccluderList::iterator itr=_occluderList.begin(); + itr!=_occluderList.end(); + ++itr) + { + itr->popCurrentMask(); + } + } + } + + + protected: + + Mask _mask; + + Polytope _clippingVolume; + + OccluderList _occluderList; + + float _pixelSizeOffset; + Vec3 _pixelSizeVector; + +}; + +} // end of namespace + +#endif diff --git a/include/osg/ShadowOccluderVolume b/include/osg/ShadowOccluderVolume index 21a6b75fd..9e1152004 100644 --- a/include/osg/ShadowOccluderVolume +++ b/include/osg/ShadowOccluderVolume @@ -43,6 +43,18 @@ class SG_EXPORT ShadowOccluderVolume * within this shadow occluder volume.*/ bool contains(const BoundingBox& bound); + inline void transformProvidingInverse(const osg::Matrix& matrix) + { + _occluderVolume.transformProvidingInverse(matrix); + for(HoleList::iterator itr=_holeList.begin(); + itr!=_holeList.end(); + ++itr) + { + itr->transformProvidingInverse(matrix); + } + } + + protected: Polytope _occluderVolume; diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 178a10ecc..c174082a9 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -348,8 +348,8 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor - void pushPolytope(); - void popPolytope(); + void pushCullingSet(); + void popCullingSet(); // typedef std::vector PolytopeStack; @@ -380,8 +380,10 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor typedef osg::fast_back_stack CullingModeStack; CullingModeStack _cullingModeStack; - typedef osg::fast_back_stack > ClippingStack; - ClippingStack _clippingSet; + typedef osg::fast_back_stack > CullingStack; + CullingStack _clipspaceCullingStack; + CullingStack _projectionCullingStack; + CullingStack _modelviewCullingStack; unsigned int _bbCornerNear; diff --git a/src/osg/CullingSet.cpp b/src/osg/CullingSet.cpp index 34607fac0..f35e3b0a5 100644 --- a/src/osg/CullingSet.cpp +++ b/src/osg/CullingSet.cpp @@ -4,6 +4,7 @@ using namespace osg; CullingSet::CullingSet() { + _mask = ALL_CULLING; } CullingSet::~CullingSet() diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 1e1726675..4fc89b999 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -166,7 +166,7 @@ void CullVisitor::reset() _windowToModelFactor = 1.0f; } -void CullVisitor::pushPolytope() +void CullVisitor::pushCullingSet() { _modelviewPolytopeStack.push_back(); osg::Polytope& cv = _modelviewPolytopeStack.back(); @@ -177,14 +177,20 @@ void CullVisitor::pushPolytope() _MVPW_Stack.push_back(0L); _windowToModelFactorDirty = true; + + + _modelviewCullingStack.push_back(osgNew osg::CullingSet(*_projectionCullingStack.back(),*_modelviewStack.back())); + } -void CullVisitor::popPolytope() +void CullVisitor::popCullingSet() { _modelviewPolytopeStack.pop_back(); _MVPW_Stack.pop_back(); _windowToModelFactorDirty = true; + + _modelviewCullingStack.pop_back(); } void CullVisitor::pushViewport(osg::Viewport* viewport) @@ -207,7 +213,17 @@ void CullVisitor::pushProjectionMatrix(Matrix* matrix) _projectionPolytopeStack.back().setToUnitFrustumWithoutNearFar(); _projectionPolytopeStack.back().transformProvidingInverse(*matrix); - pushPolytope(); + + osg::CullingSet* cullingSet = osgNew osg::CullingSet(); + cullingSet->getFrustum().setToUnitFrustumWithoutNearFar(); + cullingSet->getFrustum().transformProvidingInverse(*matrix); + + _projectionCullingStack.push_back(cullingSet); + + //_projectionCullingStack.push_back(osgNew osg::CullingSet(*_clipspaceCullingStack.back(),*matrix)); + + + pushCullingSet(); } void CullVisitor::popProjectionMatrix() @@ -241,14 +257,16 @@ void CullVisitor::popProjectionMatrix() _projectionStack.pop_back(); _projectionPolytopeStack.pop_back(); - popPolytope(); + _projectionCullingStack.pop_back(); + + popCullingSet(); } void CullVisitor::pushModelViewMatrix(Matrix* matrix) { _modelviewStack.push_back(matrix); - pushPolytope(); + pushCullingSet(); // fast method for computing the eye point in local coords which doesn't require the inverse matrix. const float x_0 = (*matrix)(0,0); @@ -285,7 +303,7 @@ void CullVisitor::popModelViewMatrix() { _modelviewStack.pop_back(); _eyePointStack.pop_back(); - popPolytope(); + popCullingSet(); osg::Vec3 lookVector(0.0f,0.0f,-1.0f);