Further work on moving culling functionality from CullVisitor into CullingSet,
in preperation for occlusion culling.
This commit is contained in:
parent
0732701e9d
commit
f67be7c07f
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,10 @@ class SG_EXPORT ShadowOccluderVolume
|
||||
|
||||
typedef std::vector<Polytope> HoleList;
|
||||
|
||||
ShadowOccluderVolume(const ShadowOccluderVolume& soc):
|
||||
_occluderVolume(soc._occluderVolume),
|
||||
_holeList(soc._holeList) {}
|
||||
|
||||
ShadowOccluderVolume(const ShadowOccluderVolume& soc,Matrix& MVP);
|
||||
|
||||
ShadowOccluderVolume(const ConvexPlanerOccluder& occluder,Matrix& MVP);
|
||||
|
@ -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
|
||||
|
@ -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())<osg::square(_smallFeatureCullingPixelSize)) return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return node.isCullingActive() && _modelviewCullingStack.back()->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<osg::Polytope> PolytopeStack;
|
||||
// typedef std::vector<osg::ref_ptr<osg::Matrix> > MatrixStack;
|
||||
|
||||
typedef osg::fast_back_stack<osg::Polytope> PolytopeStack;
|
||||
typedef osg::fast_back_stack< osg::ref_ptr<osg::Matrix> > MatrixStack;
|
||||
|
||||
MatrixStack _projectionStack;
|
||||
MatrixStack _PW_Stack;
|
||||
PolytopeStack _projectionPolytopeStack;
|
||||
|
||||
MatrixStack _modelviewStack;
|
||||
MatrixStack _MVPW_Stack;
|
||||
PolytopeStack _modelviewPolytopeStack;
|
||||
|
||||
bool _windowToModelFactorDirty;
|
||||
float _windowToModelFactor;
|
||||
|
||||
// typedef std::vector<osg::ref_ptr<osg::Viewport> > ViewportStack;
|
||||
|
||||
typedef osg::fast_back_stack<osg::ref_ptr<osg::Viewport> > ViewportStack;
|
||||
ViewportStack _viewportStack;
|
||||
|
||||
// typedef std::vector<osg::Vec3> EyePointStack;
|
||||
typedef osg::fast_back_stack<osg::Vec3> EyePointStack;
|
||||
EyePointStack _eyePointStack;
|
||||
|
||||
typedef osg::fast_back_stack<CullingMode> CullingModeStack;
|
||||
CullingModeStack _cullingModeStack;
|
||||
CullingMode _cullingMode;
|
||||
|
||||
typedef osg::fast_back_stack<osg::ref_ptr<osg::CullingSet> > CullingStack;
|
||||
CullingStack _clipspaceCullingStack;
|
||||
|
@ -5,6 +5,8 @@ using namespace osg;
|
||||
CullingSet::CullingSet()
|
||||
{
|
||||
_mask = ALL_CULLING;
|
||||
_pixelSizeVector.set(0,0,0,1);
|
||||
_smallFeatureCullingPixelSize=1.0f;
|
||||
}
|
||||
|
||||
CullingSet::~CullingSet()
|
||||
|
@ -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()<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();
|
||||
@ -990,11 +964,6 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
|
||||
|
||||
pushStateSet(dummyState.get());
|
||||
|
||||
|
||||
// switch off the view frustum culling, since we will have
|
||||
// the whole subgraph in view.
|
||||
_cullingModeStack.push_back((_cullingModeStack.back() & ~VIEW_FRUSTUM_CULLING));
|
||||
|
||||
{
|
||||
|
||||
// traversing the usual LOD selected child.
|
||||
@ -1002,9 +971,6 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node)
|
||||
|
||||
}
|
||||
|
||||
// restore the culling mode.
|
||||
popCurrentMask();
|
||||
|
||||
popStateSet();
|
||||
|
||||
// restore the previous model view matrix.
|
||||
|
Loading…
Reference in New Issue
Block a user