diff --git a/include/osg/CullSettings b/include/osg/CullSettings index 3bebebf84..dece95893 100644 --- a/include/osg/CullSettings +++ b/include/osg/CullSettings @@ -161,7 +161,8 @@ class OSG_EXPORT CullSettings { DO_NOT_COMPUTE_NEAR_FAR = 0, COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES, - COMPUTE_NEAR_FAR_USING_PRIMITIVES + COMPUTE_NEAR_FAR_USING_PRIMITIVES, + COMPUTE_NEAR_USING_PRIMITIVES }; void setComputeNearFarMode(ComputeNearFarMode cnfm) { _computeNearFar=cnfm; applyMaskAction(COMPUTE_NEAR_FAR_MODE); } diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 97d1daad4..368917b70 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -211,6 +211,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac inline value_type getCalculatedFarPlane() const { return _computed_zfar; } value_type computeNearestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable); + value_type computeFurthestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable); bool updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb); @@ -381,6 +382,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac typedef std::multimap DistanceMatrixDrawableMap; DistanceMatrixDrawableMap _nearPlaneCandidateMap; + DistanceMatrixDrawableMap _farPlaneCandidateMap; osg::ref_ptr _identifier; }; diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 1064fd61a..dba97e76b 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -131,6 +131,7 @@ void CullVisitor::reset() _currentReuseRenderLeafIndex = 0; _nearPlaneCandidateMap.clear(); + _farPlaneCandidateMap.clear(); } float CullVisitor::getDistanceToEyePoint(const Vec3& pos, bool withLODScale) const @@ -161,10 +162,11 @@ float CullVisitor::getDistanceFromEyePoint(const osg::Vec3& pos, bool withLODSca void CullVisitor::computeNearPlane() { + //OSG_NOTICE<<"CullVisitor::computeNearPlane()"<tick(); + //osg::Timer_t start_t = osg::Timer::instance()->tick(); // update near from defferred list of drawables unsigned int numTests = 0; @@ -182,11 +184,39 @@ void CullVisitor::computeNearPlane() } } - // osg::Timer_t end_t = osg::Timer::instance()->tick(); - // OSG_NOTICE<<"Took "<delta_m(start_t,end_t)<<"ms to test "<tick(); + //OSG_NOTICE<<"Took "<delta_m(start_t,end_t)<<"ms to test "<tick(); + + // update near from defferred list of drawables + unsigned int numTests = 0; + for(DistanceMatrixDrawableMap::reverse_iterator itr=_farPlaneCandidateMap.rbegin(); + itr!=_farPlaneCandidateMap.rend() && itr->first>_computed_zfar; + ++itr) + { + ++numTests; + // OSG_WARN<<"testing computeFurthestPointInFrustum with d_far = "<first<second._matrix, itr->second._planes,*(itr->second._drawable)); + if (d_far>_computed_zfar) + { + _computed_zfar = d_far; + // OSG_WARN<<"updating znear to "<<_computed_znear<tick(); + //OSG_NOTICE<<"Took "<delta_m(start_t,end_t)<<"ms to test "< +struct ComputeNearFarFunctor { - ComputeNearestPointFunctor(): + ComputeNearFarFunctor(): _planes(0) {} void set(CullVisitor::value_type znear, const osg::Matrix& matrix, const osg::Polytope::PlaneList* planes) @@ -321,6 +352,8 @@ struct ComputeNearestPointFunctor typedef std::pair DistancePoint; typedef std::vector Polygon; + Comparator _comparator; + CullVisitor::value_type _znear; osg::Matrix _matrix; const osg::Polytope::PlaneList* _planes; @@ -335,7 +368,7 @@ struct ComputeNearestPointFunctor CullVisitor::value_type n1 = distance(v1,_matrix); // check if point is behind znear, if so discard - if (n1 >= _znear) + if (_comparator.greaterEqual(n1,_znear)) { //OSG_NOTICE<<"Point beyond znear"<= _znear && - n2 >= _znear) + if (_comparator.greaterEqual(n1,_znear) && + _comparator.greaterEqual(n2,_znear)) { //OSG_NOTICE<<"Line totally beyond znear"<= _znear && - n2 >= _znear && - n3 >= _znear) + if (_comparator.greaterEqual(n1,_znear) && + _comparator.greaterEqual(n2,_znear) && + _comparator.greaterEqual(n3,_znear)) { //OSG_NOTICE<<"Triangle totally beyond znear"<=rhs; } + inline CullVisitor::value_type minimum(CullVisitor::value_type lhs, CullVisitor::value_type rhs) const { return lhs ComputeNearestPointFunctor; + +struct GreaterComparator +{ + inline bool less(CullVisitor::value_type lhs, CullVisitor::value_type rhs) const { return lhs>rhs; } + inline bool lessEqual(CullVisitor::value_type lhs, CullVisitor::value_type rhs) const { return lhs>=rhs; } + inline bool greaterEqual(CullVisitor::value_type lhs, CullVisitor::value_type rhs) const { return lhs<=rhs; } + inline CullVisitor::value_type minimum(CullVisitor::value_type lhs, CullVisitor::value_type rhs) const { return lhs>rhs?lhs:rhs; } +}; +typedef ComputeNearFarFunctor ComputeFurthestPointFunctor; + + CullVisitor::value_type CullVisitor::computeNearestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable) { - // OSG_WARN<<"CullVisitor::computeNearestPointInFrustum("< cnpf; cnpf.set(_computed_znear, matrix, &planes); @@ -634,6 +687,18 @@ CullVisitor::value_type CullVisitor::computeNearestPointInFrustum(const osg::Mat return cnpf._znear; } +CullVisitor::value_type CullVisitor::computeFurthestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable) +{ + //OSG_NOTICE<<"CullVisitor::computeFurthestPointInFrustum("< cnpf; + cnpf.set(_computed_zfar, matrix, &planes); + + drawable.accept(cnpf); + + return cnpf._znear; +} + bool CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::BoundingBox& bb) { // efficient computation of near and far, only taking into account the nearest and furthest @@ -759,9 +824,9 @@ bool CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::D return false; } - if (d_near<_computed_znear) + if (_computeNearFar==COMPUTE_NEAR_FAR_USING_PRIMITIVES || _computeNearFar==COMPUTE_NEAR_USING_PRIMITIVES) { - if (_computeNearFar==COMPUTE_NEAR_FAR_USING_PRIMITIVES) + if (d_near<_computed_znear || d_far>_computed_zfar) { osg::Polytope& frustum = getCurrentCullingSet().getFrustum(); if (frustum.getResultMask()) @@ -770,42 +835,76 @@ bool CullVisitor::updateCalculatedNearFar(const osg::Matrix& matrix,const osg::D { // OSG_WARN<<"Adding billboard into deffered list"<_computed_zfar) + { + _farPlaneCandidateMap.insert(DistanceMatrixDrawableMap::value_type(d_far,mpd) ); + } + } + } else { // insert drawable into the deferred list of drawables which will be handled at the popProjectionMatrix(). - _nearPlaneCandidateMap.insert( - DistanceMatrixDrawableMap::value_type(d_near,MatrixPlanesDrawables(matrix,&drawable,frustum)) ); - } + MatrixPlanesDrawables mpd(matrix,&drawable,frustum); + if (d_near<_computed_znear) + { + _nearPlaneCandidateMap.insert(DistanceMatrixDrawableMap::value_type(d_near,mpd) ); + } + if (_computeNearFar==COMPUTE_NEAR_FAR_USING_PRIMITIVES) + { + if (d_far>_computed_zfar) + { + _farPlaneCandidateMap.insert(DistanceMatrixDrawableMap::value_type(d_far,mpd) ); + } + } + } + // use the far point if its nearer than current znear as this is a conservative estimate of the znear // while the final computation for this drawable is deferred. - if (d_far<_computed_znear) + if (d_far>=0.0 && d_far<_computed_znear) { - if (d_far>=0.0) _computed_znear = d_far; - else OSG_INFO<<" 1) ignoring compute dnear="<