diff --git a/include/osg/CullingSet b/include/osg/CullingSet index a5d17362b..33aea1771 100644 --- a/include/osg/CullingSet +++ b/include/osg/CullingSet @@ -19,12 +19,12 @@ class SG_EXPORT CullingSet : public Referenced CullingSet(); - CullingSet(const CullingSet& cs,const osg::Matrix& matrix): + CullingSet(const CullingSet& cs,const Matrix& matrix, const Vec4& pixelSizeVector): _mask(cs._mask), _clippingVolume(cs._clippingVolume), _occluderList(cs._occluderList), - _pixelSizeOffset(cs._pixelSizeOffset), - _pixelSizeVector(cs._pixelSizeVector) + _pixelSizeVector(pixelSizeVector), + _smallFeatureCullingPixelSize(cs._smallFeatureCullingPixelSize) { _clippingVolume.transformProvidingInverse(matrix); for(OccluderList::iterator itr=_occluderList.begin(); @@ -54,9 +54,29 @@ class SG_EXPORT CullingSet : public Referenced void setFrustum(Polytope& cv) { _clippingVolume = cv; } Polytope& getFrustum() { return _clippingVolume; } + const Polytope& getFrustum() const { return _clippingVolume; } void addOccluder(ShadowOccluderVolume& cv) { _occluderList.push_back(cv); } + + void setPixelSizeVector(const Vec4& v) { _pixelSizeVector = v; } + + Vec4& getPixelSizeVector() { return _pixelSizeVector; } + const Vec4& getPixelSizeVector() const { return _pixelSizeVector; } + + 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 an bounding sphere.*/ + float pixelSize(const BoundingSphere& bs) const { return bs.radius()/(bs.center()*_pixelSizeVector); } + inline bool isCulled(const BoundingBox& bb) { if (_mask&VIEW_FRUSTUM_CULLING) @@ -96,7 +116,7 @@ class SG_EXPORT CullingSet : public Referenced if (_mask&SMALL_FEATURE_CULLING) { - if ((bs.center()*_pixelSizeVector+_pixelSizeOffset)>bs.radius()) return true; + if (((bs.center()*_pixelSizeVector)*_smallFeatureCullingPixelSize)>bs.radius()) return true; } if (_mask&SHADOW_OCCLUSION_CULLING) @@ -149,14 +169,11 @@ class SG_EXPORT CullingSet : public Referenced protected: - Mask _mask; - - Polytope _clippingVolume; - - OccluderList _occluderList; - - float _pixelSizeOffset; - Vec3 _pixelSizeVector; + Mask _mask; + Polytope _clippingVolume; + OccluderList _occluderList; + Vec4 _pixelSizeVector; + float _smallFeatureCullingPixelSize; }; diff --git a/include/osg/ShadowOccluderVolume b/include/osg/ShadowOccluderVolume index 9e1152004..469cbee19 100644 --- a/include/osg/ShadowOccluderVolume +++ b/include/osg/ShadowOccluderVolume @@ -20,6 +20,10 @@ class SG_EXPORT ShadowOccluderVolume typedef std::vector HoleList; + ShadowOccluderVolume(const ShadowOccluderVolume& soc): + _occluderVolume(soc._occluderVolume), + _holeList(soc._holeList) {} + ShadowOccluderVolume(const ShadowOccluderVolume& soc,Matrix& MVP); ShadowOccluderVolume(const ConvexPlanerOccluder& occluder,Matrix& MVP); diff --git a/include/osg/Vec4 b/include/osg/Vec4 index 4a561f917..0dbdbb436 100644 --- a/include/osg/Vec4 +++ b/include/osg/Vec4 @@ -217,6 +217,19 @@ class Vec4 }; // end of class Vec4 + +/** Compute the dot product of a (Vec3,1.0) and a Vec4.*/ +inline float operator * (const Vec3& lhs,const Vec4& rhs) +{ + return lhs[0]*rhs[0]+lhs[1]*rhs[1]+lhs[2]*rhs[2]+rhs[3]; +} + +/** Compute the dot product of a Vec4 and a (Vec3,1.0).*/ +inline float operator * (const Vec4& lhs,const Vec3& rhs) +{ + return lhs[0]*rhs[0]+lhs[1]*rhs[1]+lhs[2]*rhs[2]+lhs[3]; +} + } // end of namespace osg #endif diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index c174082a9..71435bb4b 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -232,64 +232,29 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor inline float pixelSize(const osg::Vec3& v, float const radius) { - const osg::Matrix& mvpw = getMVPW(); - if (_windowToModelFactorDirty) - { - _windowToModelFactorDirty=false; - _windowToModelFactor = osg::Vec3(mvpw(0,0),mvpw(1,0),mvpw(2,0)).length(); - } - float W = v.x()*mvpw(0,3)+ - v.y()*mvpw(1,3)+ - v.z()*mvpw(2,3)+ - mvpw(3,3); - - return fabs(radius*_windowToModelFactor/W); - - } - - inline float pixelSize2(const osg::Vec3& v, float const radius) - { - const float R2 = osg::square(_viewportStack.back()->width()/osg::DegreesToRadians(38.0f))*1.15f; - - //float p1 = fabs(radius*_windowToModelFactor/W); - return R2*radius*radius/(v-getEyeLocal()).length2(); - + return _modelviewCullingStack.back()->pixelSize(v,radius); } inline bool isCulled(const osg::Node& node) { - if (node.isCullingActive()) - { - const osg::BoundingSphere& sp = node.getBound(); - if (!(_modelviewPolytopeStack.back().contains(sp))) return true; -// if (pixelSize(sp.center(),sp.radius())<_smallFeatureCullingPixelSize) return true; - if (pixelSize2(sp.center(),sp.radius())isCulled(node.getBound()); } inline const bool isCulled(const osg::BoundingBox& bb) { - if (!bb.isValid()) return true; - - //return !_modelviewPolytopeStack.back().contains(bb,mode); - return !_modelviewPolytopeStack.back().contains(bb); - //return false; + return bb.isValid() && _modelviewCullingStack.back()->isCulled(bb); } inline void pushCurrentMask() { - _modelviewPolytopeStack.back().pushCurrentMask(); + _modelviewCullingStack.back()->pushCurrentMask(); } inline void popCurrentMask() { - _modelviewPolytopeStack.back().popCurrentMask(); + _modelviewCullingStack.back()->popCurrentMask(); } - const CullingMode getCurrentCullingMode() const { return _cullingModeStack.back(); } - void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable) { updateCalculatedNearFar(matrix,drawable.getBound()); } void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb); void updateCalculatedNearFar(const osg::Vec3& pos); @@ -352,33 +317,22 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor void popCullingSet(); -// typedef std::vector PolytopeStack; -// typedef std::vector > MatrixStack; - typedef osg::fast_back_stack PolytopeStack; typedef osg::fast_back_stack< osg::ref_ptr > MatrixStack; MatrixStack _projectionStack; MatrixStack _PW_Stack; - PolytopeStack _projectionPolytopeStack; MatrixStack _modelviewStack; MatrixStack _MVPW_Stack; - PolytopeStack _modelviewPolytopeStack; - - bool _windowToModelFactorDirty; - float _windowToModelFactor; - -// typedef std::vector > ViewportStack; + typedef osg::fast_back_stack > ViewportStack; ViewportStack _viewportStack; -// typedef std::vector EyePointStack; typedef osg::fast_back_stack EyePointStack; EyePointStack _eyePointStack; - typedef osg::fast_back_stack CullingModeStack; - CullingModeStack _cullingModeStack; + CullingMode _cullingMode; typedef osg::fast_back_stack > CullingStack; CullingStack _clipspaceCullingStack; diff --git a/src/osg/CullingSet.cpp b/src/osg/CullingSet.cpp index f35e3b0a5..c23d71dc0 100644 --- a/src/osg/CullingSet.cpp +++ b/src/osg/CullingSet.cpp @@ -5,6 +5,8 @@ using namespace osg; CullingSet::CullingSet() { _mask = ALL_CULLING; + _pixelSizeVector.set(0,0,0,1); + _smallFeatureCullingPixelSize=1.0f; } CullingSet::~CullingSet() diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 31ba31b3a..80563a7f7 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -84,11 +84,7 @@ CullVisitor::CullVisitor() _LODBias = 1.0f; - // note all subsequent _cullingModeStack code assumes that there - // is a least this one value on the stack, therefore they never - // check whether the stack is empty. This shouldn't be a problem - // unless there is bug somewhere... - _cullingModeStack.push_back(ENABLE_ALL_CULLING); + _cullingMode = ENABLE_ALL_CULLING; //_tsm = LOOK_VECTOR_DISTANCE; @@ -105,8 +101,6 @@ CullVisitor::CullVisitor() _numFramesToKeepImpostorSprites = 10; _impostorSpriteManager = osgNew ImpostorSpriteManager; - _windowToModelFactorDirty = true; - _windowToModelFactor = 1.0f; _smallFeatureCullingPixelSize = 3.0f; } @@ -125,18 +119,14 @@ void CullVisitor::reset() // first unref all referenced objects and then empty the containers. // _projectionStack.clear(); - _projectionPolytopeStack.clear(); - _modelviewStack.clear(); - _modelviewPolytopeStack.clear(); - _viewportStack.clear(); - _eyePointStack.clear(); - // remove all accept the first element of the stack. - //_cullingModeStack.erase(_cullingModeStack.begin()+1,_cullingModeStack.end()); - _cullingModeStack.clear(); + + _clipspaceCullingStack.clear(); + _projectionCullingStack.clear(); + _modelviewCullingStack.clear(); // reset the calculated near far planes. _computed_znear = FLT_MAX; @@ -162,35 +152,55 @@ void CullVisitor::reset() (*itr)->reset(); } - _windowToModelFactorDirty = true; - _windowToModelFactor = 1.0f; } void CullVisitor::pushCullingSet() { - _modelviewPolytopeStack.push_back(); - osg::Polytope& cv = _modelviewPolytopeStack.back(); - cv = _projectionPolytopeStack.back(); - - if (!_modelviewStack.empty()) cv.transformProvidingInverse(*_modelviewStack.back()); - _MVPW_Stack.push_back(0L); - - _windowToModelFactorDirty = true; + const osg::Matrix& mvpw = getMVPW(); + float scale = osg::Vec3(mvpw(0,0),mvpw(1,0),mvpw(2,0)).length(); + Vec4 pixelSizeVector(mvpw(0,3),mvpw(1,3),mvpw(2,3),mvpw(3,3)); + if (scale>0.0f) pixelSizeVector /= scale; - if (_modelviewStack.empty()) _modelviewCullingStack.push_back(_projectionCullingStack.back()); - else _modelviewCullingStack.push_back(osgNew osg::CullingSet(*_projectionCullingStack.back(),*_modelviewStack.back())); + + + + if (_modelviewStack.empty()) + { + _modelviewCullingStack.push_back(_projectionCullingStack.back()); + + } + else + { +// Need to account for window matrix... +// osg::Matrix& P = *_projectionStack.back(); +// osg::Matrix& M = *_modelviewStack.back(); +// +// float P00 = P(0,0); +// float P20 = P(2,0); +// osg::Vec3 scale(M(0,0)*P00 + M(0,2)*P20, +// M(1,0)*P00 + M(1,2)*P20, +// M(2,0)*P00 + M(2,2)*P20); +// +// float P23 = P(2,3); +// float P33 = P(3,3); +// osg::Vec4 pixelSizeVector(M(0,2)*P23, +// M(1,2)*P23, +// M(2,2)*P23, +// M(3,2)*P23 + M(3,3)*P33); +// +// pixelSizeVector /= scale.length(); + + _modelviewCullingStack.push_back(osgNew osg::CullingSet(*_projectionCullingStack.back(),*_modelviewStack.back(),pixelSizeVector)); + } } void CullVisitor::popCullingSet() { - _modelviewPolytopeStack.pop_back(); _MVPW_Stack.pop_back(); - _windowToModelFactorDirty = true; - _modelviewCullingStack.pop_back(); } @@ -210,14 +220,10 @@ void CullVisitor::pushProjectionMatrix(Matrix* matrix) { _projectionStack.push_back(matrix); - _projectionPolytopeStack.push_back(); - _projectionPolytopeStack.back().setToUnitFrustumWithoutNearFar(); - _projectionPolytopeStack.back().transformProvidingInverse(*matrix); - - osg::CullingSet* cullingSet = osgNew osg::CullingSet(); cullingSet->getFrustum().setToUnitFrustumWithoutNearFar(); cullingSet->getFrustum().transformProvidingInverse(*matrix); + cullingSet->setSmallFeatureCullingPixelSize(_smallFeatureCullingPixelSize); _projectionCullingStack.push_back(cullingSet); @@ -256,7 +262,6 @@ void CullVisitor::popProjectionMatrix() } _projectionStack.pop_back(); - _projectionPolytopeStack.pop_back(); _projectionCullingStack.pop_back(); @@ -368,13 +373,13 @@ void CullVisitor::updateCalculatedNearFar(const osg::Vec3& pos) void CullVisitor::setCullingMode(CullingMode mode) { - _cullingModeStack.back()=mode; + _cullingMode=mode; } CullVisitor::CullingMode CullVisitor::getCullingMode() const { - return _cullingModeStack.back(); + return _cullingMode; } void CullVisitor::apply(Node& node) @@ -455,37 +460,6 @@ void CullVisitor::apply(Geode& node) } } -// osg::Timer timer; -// osg::Timer_t ta = timer.tick(); -// const osg::Matrix& mvpw = getMVPW(); -// osg::Timer_t tb = timer.tick(); -// -// const osg::BoundingSphere& sp = node.getBound(); -// osg::Vec3 v = sp._center; -// float radius = sp._radius; -// osg::Timer_t t1 = timer.tick(); -// bool result1 = pixelSize(v,sp.radius())<4.0f; -// osg::Timer_t t2 = timer.tick(); -// -// const float _ratio2 = 0.002f*0.002f; -// osg::Vec3 delta(v-getEyeLocal()); -// bool result2 = (sp.radius2()