Added pixelSize method to CullVisitor, and converted small feature
culling to use the pixelSize method instead of a ratio of radius to distance from eye point. setSmallFeatureCullingPixelSize() method has also been added to provide the user with finer control of small featyre culling.
This commit is contained in:
@@ -197,6 +197,47 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
return _eyePointStack.back();
|
||||
}
|
||||
|
||||
|
||||
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 bool isCulled(const osg::BoundingSphere& sp,CullingMode& mode)
|
||||
{
|
||||
if (!sp.isValid()) return true;
|
||||
|
||||
if (!(_modelviewClippingVolumeStack.back().contains(sp,mode))) return true;
|
||||
|
||||
if (mode&SMALL_FEATURE_CULLING)
|
||||
{
|
||||
if (pixelSize(sp.center(),sp.radius())<_smallFeatureCullingPixelSize) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline const bool isCulled(const osg::BoundingBox& bb,CullingMode mode)
|
||||
{
|
||||
if (!bb.isValid()) return true;
|
||||
|
||||
return !_modelviewClippingVolumeStack.back().contains(bb,mode);
|
||||
}
|
||||
|
||||
void setSmallFeatureCullingPixelSize(float s) { _smallFeatureCullingPixelSize=s; }
|
||||
float getSmallFeatureCullingPixelSize() const { return _smallFeatureCullingPixelSize; }
|
||||
|
||||
protected:
|
||||
|
||||
/** prevent unwanted copy construction.*/
|
||||
@@ -233,30 +274,6 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
}
|
||||
|
||||
|
||||
inline bool isCulled(const osg::BoundingSphere& sp,CullingMode& mode) const
|
||||
{
|
||||
if (!sp.isValid()) return true;
|
||||
|
||||
if (!(_modelviewClippingVolumeStack.back().contains(sp,mode))) return true;
|
||||
|
||||
if (mode&SMALL_FEATURE_CULLING)
|
||||
{
|
||||
const float _ratio2 = 0.002f*0.002f;
|
||||
osg::Vec3 delta(sp._center-getEyeLocal());
|
||||
if (sp.radius2()<delta.length2()*_ratio2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline const bool isCulled(const osg::BoundingBox& bb,CullingMode mode) const
|
||||
{
|
||||
if (!bb.isValid()) return true;
|
||||
|
||||
return !_modelviewClippingVolumeStack.back().contains(bb,mode);
|
||||
}
|
||||
|
||||
void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable);
|
||||
void updateCalculatedNearFar(const osg::Vec3& pos);
|
||||
@@ -356,7 +373,9 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
{
|
||||
if (!_MVPW_Stack.back())
|
||||
{
|
||||
_MVPW_Stack.back() = new osg::Matrix(getModelViewMatrix()*getProjectionMatrix()*getWindowMatrix());
|
||||
_MVPW_Stack.back() = createOrReuseMatrix(getModelViewMatrix());
|
||||
(*_MVPW_Stack.back()) *= getProjectionMatrix();
|
||||
(*_MVPW_Stack.back()) *= getWindowMatrix();
|
||||
}
|
||||
return *_MVPW_Stack.back();
|
||||
}
|
||||
@@ -381,7 +400,10 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
MatrixStack _modelviewStack;
|
||||
MatrixStack _MVPW_Stack;
|
||||
ClippingVolumeStack _modelviewClippingVolumeStack;
|
||||
|
||||
|
||||
bool _windowToModelFactorDirty;
|
||||
float _windowToModelFactor;
|
||||
|
||||
typedef std::vector<osg::ref_ptr<osg::Viewport> > ViewportStack;
|
||||
ViewportStack _viewportStack;
|
||||
|
||||
@@ -404,7 +426,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
|
||||
|
||||
float _LODBias;
|
||||
|
||||
float _smallFeatureCullingPixelSize;
|
||||
|
||||
enum ComputeNearFarMode
|
||||
{
|
||||
@@ -430,7 +452,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor
|
||||
MatrixList _reuseMatrixList;
|
||||
unsigned int _currentReuseMatrixIndex;
|
||||
|
||||
inline osg::Matrix* createOrReuseMatrix(const osg::Matrix value)
|
||||
inline osg::Matrix* createOrReuseMatrix(const osg::Matrix& value)
|
||||
{
|
||||
// skip of any already reused matrix.
|
||||
while (_currentReuseMatrixIndex<_reuseMatrixList.size() &&
|
||||
|
||||
@@ -105,6 +105,10 @@ CullVisitor::CullVisitor()
|
||||
_numFramesToKeepImpostorSprites = 10;
|
||||
_impostorSpriteManager = osgNew ImpostorSpriteManager;
|
||||
|
||||
_windowToModelFactorDirty = true;
|
||||
_windowToModelFactor = 1.0f;
|
||||
_smallFeatureCullingPixelSize = 3.0f;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +163,8 @@ void CullVisitor::reset()
|
||||
(*itr)->reset();
|
||||
}
|
||||
|
||||
_windowToModelFactorDirty = true;
|
||||
_windowToModelFactor = 1.0f;
|
||||
}
|
||||
|
||||
void CullVisitor::pushClippingVolume()
|
||||
@@ -167,12 +173,16 @@ void CullVisitor::pushClippingVolume()
|
||||
if (!_modelviewStack.empty()) _modelviewClippingVolumeStack.back().transformProvidingInverse(*_modelviewStack.back());
|
||||
|
||||
_MVPW_Stack.push_back(0L);
|
||||
|
||||
_windowToModelFactorDirty = true;
|
||||
}
|
||||
|
||||
void CullVisitor::popClippingVolume()
|
||||
{
|
||||
_modelviewClippingVolumeStack.pop_back();
|
||||
_MVPW_Stack.pop_back();
|
||||
|
||||
_windowToModelFactorDirty = true;
|
||||
}
|
||||
|
||||
void CullVisitor::pushViewport(osg::Viewport* viewport)
|
||||
@@ -436,6 +446,37 @@ 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()<delta.length2()*_ratio2);
|
||||
//
|
||||
// osg::Timer_t t3 = timer.tick();
|
||||
//
|
||||
// float W = v.x()*mvpw(0,3)+
|
||||
// v.y()*mvpw(1,3)+
|
||||
// v.z()*mvpw(2,3)+
|
||||
// mvpw(3,3);
|
||||
//
|
||||
// bool result3 = fabs(radius*_windowToModelFactor/W);
|
||||
//
|
||||
// osg::Timer_t t4 = timer.tick();
|
||||
//
|
||||
// cout << "time pixelSize = "<<t2-t1<<endl;
|
||||
// cout << " odl = "<<t3-t2<<endl;
|
||||
// cout << " stripped = "<<t4-t3<<endl;
|
||||
// cout << " getMVPW = "<<tb-ta<<endl;
|
||||
|
||||
// pop the node's state off the geostate stack.
|
||||
if (node_state) popStateSet();
|
||||
|
||||
Reference in New Issue
Block a user