Added fine grained computation of the far plane when using the COMPUTE_NEAR_FAR_USING_PRIMITIVES ComputeNearFarMode.

Added COMPUTE_NEAR_FAR_USING_PRIMITIVES option that provides the original functionality where only the near plane
is computed in a fine grained way, with the far plane being computed simply from bound volumes.
This commit is contained in:
Robert Osfield
2011-09-01 18:48:21 +00:00
parent b21d206d3a
commit 1fd3c84287
3 changed files with 151 additions and 41 deletions

View File

@@ -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); }

View File

@@ -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<value_type, MatrixPlanesDrawables> DistanceMatrixDrawableMap;
DistanceMatrixDrawableMap _nearPlaneCandidateMap;
DistanceMatrixDrawableMap _farPlaneCandidateMap;
osg::ref_ptr<Identifier> _identifier;
};

View File

@@ -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()"<<std::endl;
if (!_nearPlaneCandidateMap.empty())
{
// osg::Timer_t start_t = osg::Timer::instance()->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 "<<osg::Timer::instance()->delta_m(start_t,end_t)<<"ms to test "<<numTests<<" out of "<<_nearPlaneCandidateMap.size()<<std::endl;
//osg::Timer_t end_t = osg::Timer::instance()->tick();
//OSG_NOTICE<<"Took "<<osg::Timer::instance()->delta_m(start_t,end_t)<<"ms to test "<<numTests<<" out of "<<_nearPlaneCandidateMap.size()<<std::endl;
_nearPlaneCandidateMap.clear();
}
if (!_farPlaneCandidateMap.empty())
{
//osg::Timer_t start_t = osg::Timer::instance()->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 = "<<itr->first<<std::endl;
value_type d_far = computeFurthestPointInFrustum(itr->second._matrix, itr->second._planes,*(itr->second._drawable));
if (d_far>_computed_zfar)
{
_computed_zfar = d_far;
// OSG_WARN<<"updating znear to "<<_computed_znear<<std::endl;
}
}
//osg::Timer_t end_t = osg::Timer::instance()->tick();
//OSG_NOTICE<<"Took "<<osg::Timer::instance()->delta_m(start_t,end_t)<<"ms to test "<<numTests<<" out of "<<_farPlaneCandidateMap.size()<<std::endl;
_farPlaneCandidateMap.clear();
}
}
void CullVisitor::popProjectionMatrix()
@@ -305,10 +335,11 @@ bool CullVisitor::clampProjectionMatrixImplementation(osg::Matrixd& projection,
return _clampProjectionMatrix( projection, znear, zfar, _nearFarRatio );
}
struct ComputeNearestPointFunctor
template<typename Comparator>
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<float, osg::Vec3> DistancePoint;
typedef std::vector<DistancePoint> 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"<<std::endl;
return;
@@ -375,8 +408,8 @@ struct ComputeNearestPointFunctor
CullVisitor::value_type n2 = distance(v2,_matrix);
// check if line is totally behind znear, if so discard
if (n1 >= _znear &&
n2 >= _znear)
if (_comparator.greaterEqual(n1,_znear) &&
_comparator.greaterEqual(n2,_znear))
{
//OSG_NOTICE<<"Line totally beyond znear"<<std::endl;
return;
@@ -421,8 +454,8 @@ struct ComputeNearestPointFunctor
if (active_mask==0)
{
_znear = osg::minimum(_znear,n1);
_znear = osg::minimum(_znear,n2);
_znear = minimum(_znear,n1);
_znear = minimum(_znear,n2);
// OSG_NOTICE<<"Line all inside frustum "<<n1<<"\t"<<n2<<" number of plane="<<_planes->size()<<std::endl;
return;
}
@@ -472,7 +505,7 @@ struct ComputeNearestPointFunctor
n1 = distance(p1.second,_matrix);
n2 = distance(p2.second,_matrix);
_znear = osg::minimum(n1, n2);
_znear = _comparator.minimum(n1, n2);
//OSG_NOTICE<<"Near plane updated "<<_znear<<std::endl;
}
@@ -484,9 +517,9 @@ struct ComputeNearestPointFunctor
CullVisitor::value_type n3 = distance(v3,_matrix);
// check if triangle is total behind znear, if so discard
if (n1 >= _znear &&
n2 >= _znear &&
n3 >= _znear)
if (_comparator.greaterEqual(n1,_znear) &&
_comparator.greaterEqual(n2,_znear) &&
_comparator.greaterEqual(n3,_znear))
{
//OSG_NOTICE<<"Triangle totally beyond znear"<<std::endl;
return;
@@ -534,9 +567,9 @@ struct ComputeNearestPointFunctor
if (active_mask==0)
{
_znear = osg::minimum(_znear,n1);
_znear = osg::minimum(_znear,n2);
_znear = osg::minimum(_znear,n3);
_znear = _comparator.minimum(_znear,n1);
_znear = _comparator.minimum(_znear,n2);
_znear = _comparator.minimum(_znear,n3);
// OSG_NOTICE<<"Triangle all inside frustum "<<n1<<"\t"<<n2<<"\t"<<n3<<" number of plane="<<_planes->size()<<std::endl;
return;
}
@@ -606,7 +639,7 @@ struct ComputeNearestPointFunctor
++polyItr)
{
CullVisitor::value_type dist = distance(polyItr->second,_matrix);
if (dist < _znear)
if (_comparator.less(dist,_znear))
{
_znear = dist;
//OSG_NOTICE<<"Near plane updated "<<_znear<<std::endl;
@@ -622,9 +655,29 @@ struct ComputeNearestPointFunctor
}
};
struct LessComparator
{
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<LessComparator> 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<GreaterComparator> ComputeFurthestPointFunctor;
CullVisitor::value_type CullVisitor::computeNearestPointInFrustum(const osg::Matrix& matrix, const osg::Polytope::PlaneList& planes,const osg::Drawable& drawable)
{
// OSG_WARN<<"CullVisitor::computeNearestPointInFrustum("<<getTraversalNumber()<<"\t"<<planes.size()<<std::endl;
// OSG_NOTICE<<"CullVisitor::computeNearestPointInFrustum("<<getTraversalNumber()<<"\t"<<planes.size()<<std::endl;
osg::TemplatePrimitiveFunctor<ComputeNearestPointFunctor> 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("<<getTraversalNumber()<<"\t"<<planes.size()<<")"<<std::endl;
osg::TemplatePrimitiveFunctor<ComputeFurthestPointFunctor> 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"<<std::endl;
// insert drawable into the deferred list of drawables which will be handled at the popProjectionMatrix().
osg::Polytope transformed_frustum;
transformed_frustum.setAndTransformProvidingInverse(getProjectionCullingStack().back().getFrustum(),matrix);
MatrixPlanesDrawables mpd(matrix,&drawable,transformed_frustum);
// 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,transformed_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) );
}
}
}
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="<<d_near<<" dfar="<<d_far<< std::endl;
_computed_znear = d_far;
}
if (_computeNearFar==COMPUTE_NEAR_FAR_USING_PRIMITIVES)
{
// use the near point if its further than current zfar as this is a conservative estimate of the zfar
// while the final computation for this drawable is deferred.
if (d_near>=0.0 && d_near>_computed_zfar)
{
_computed_zfar = d_near;
}
}
else // computing zfar using bounding sphere
{
if (d_far>_computed_zfar) _computed_zfar = d_far;
}
}
else
{
if (d_near>=0.0) _computed_znear = d_near;
else OSG_INFO<<" 2) ignoring computed d_near="<<d_near<< std::endl;
if (d_near<_computed_znear) _computed_znear = d_near;
if (d_far>_computed_zfar) _computed_zfar = d_far;
}
}
else
{
//if (d_near<0.0) OSG_WARN<<" 3) set near with d_near="<<d_near<< std::endl;
_computed_znear = d_near;
}
}
if (d_far>_computed_zfar) _computed_zfar = d_far;
else
{
if (d_near<_computed_znear) _computed_znear = d_near;
if (d_far>_computed_zfar) _computed_zfar = d_far;
}
/*
@@ -1176,6 +1275,9 @@ void CullVisitor::apply(Projection& node)
DistanceMatrixDrawableMap previousNearPlaneCandidateMap;
previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);
DistanceMatrixDrawableMap previousFarPlaneCandidateMap;
previousFarPlaneCandidateMap.swap(_farPlaneCandidateMap);
_computed_znear = FLT_MAX;
_computed_zfar = -FLT_MAX;
@@ -1201,6 +1303,7 @@ void CullVisitor::apply(Projection& node)
// swap back the near plane candidates
previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);
previousFarPlaneCandidateMap.swap(_farPlaneCandidateMap);
// pop the node's state off the render graph stack.
if (node_state) popStateSet();
@@ -1406,6 +1509,9 @@ void CullVisitor::apply(osg::Camera& camera)
DistanceMatrixDrawableMap previousNearPlaneCandidateMap;
previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);
DistanceMatrixDrawableMap previousFarPlaneCandidateMap;
previousFarPlaneCandidateMap.swap(_farPlaneCandidateMap);
_computed_znear = FLT_MAX;
_computed_zfar = -FLT_MAX;
@@ -1565,6 +1671,7 @@ void CullVisitor::apply(osg::Camera& camera)
// swap back the near plane candidates
previousNearPlaneCandidateMap.swap(_nearPlaneCandidateMap);
previousFarPlaneCandidateMap.swap(_farPlaneCandidateMap);
if (camera.getViewport()) popViewport();