Fixes to the occluder culling code to properly disable occluders to prevent
self occlusion.
This commit is contained in:
@@ -85,9 +85,14 @@ class SG_EXPORT CullStack
|
||||
return pixelSize(bs.center(),bs.radius());
|
||||
}
|
||||
|
||||
inline void disableOccluder(NodePath& nodePath)
|
||||
inline void disableAndPushOccludersCurrentMask(NodePath& nodePath)
|
||||
{
|
||||
_modelviewCullingStack.back()->disableOccluder(nodePath);
|
||||
_modelviewCullingStack.back()->disableAndPushOccludersCurrentMask(nodePath);
|
||||
}
|
||||
|
||||
inline void popOccludersCurrentMask(NodePath& nodePath)
|
||||
{
|
||||
_modelviewCullingStack.back()->popOccludersCurrentMask(nodePath);
|
||||
}
|
||||
|
||||
inline bool isCulled(const std::vector<Vec3>& vertices)
|
||||
|
||||
@@ -77,7 +77,6 @@ class SG_EXPORT CullingSet : public Referenced
|
||||
/** Compute the pixel of an bounding sphere.*/
|
||||
float pixelSize(const BoundingSphere& bs) const { return bs.radius()/(bs.center()*_pixelSizeVector); }
|
||||
|
||||
void disableOccluder(NodePath& nodePath);
|
||||
|
||||
inline bool isCulled(const std::vector<Vec3>& vertices)
|
||||
{
|
||||
@@ -197,6 +196,9 @@ class SG_EXPORT CullingSet : public Referenced
|
||||
}
|
||||
}
|
||||
|
||||
void disableAndPushOccludersCurrentMask(NodePath& nodePath);
|
||||
|
||||
void popOccludersCurrentMask(NodePath& nodePath);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ class SG_EXPORT Polytope
|
||||
public:
|
||||
|
||||
typedef unsigned int ClippingMask;
|
||||
typedef std::vector<osg::Plane> PlaneList;
|
||||
typedef std::vector<Plane> PlaneList;
|
||||
typedef fast_back_stack<ClippingMask> MaskStack;
|
||||
|
||||
inline Polytope() {setupMask();}
|
||||
|
||||
@@ -94,6 +95,9 @@ class SG_EXPORT Polytope
|
||||
|
||||
inline ClippingMask getResultMask() const { return _resultMask; }
|
||||
|
||||
MaskStack& getMaskStack() { return _maskStack; }
|
||||
|
||||
const MaskStack& getMaskStack() const { return _maskStack; }
|
||||
|
||||
|
||||
inline void pushCurrentMask()
|
||||
@@ -305,7 +309,7 @@ class SG_EXPORT Polytope
|
||||
protected:
|
||||
|
||||
|
||||
fast_back_stack<ClippingMask> _maskStack;
|
||||
MaskStack _maskStack;
|
||||
ClippingMask _resultMask;
|
||||
PlaneList _planeList;
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ typedef std::vector<ShadowVolumeOccluder> ShadowVolumeOccluderList;
|
||||
|
||||
inline void ShadowVolumeOccluder::disableResultMasks()
|
||||
{
|
||||
//std::cout<<"ShadowVolumeOccluder::disableResultMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
|
||||
_occluderVolume.setResultMask(0);
|
||||
for(HoleList::iterator itr=_holeList.begin();
|
||||
itr!=_holeList.end();
|
||||
@@ -114,6 +115,7 @@ inline void ShadowVolumeOccluder::disableResultMasks()
|
||||
|
||||
inline void ShadowVolumeOccluder::pushCurrentMask()
|
||||
{
|
||||
//std::cout<<"ShadowVolumeOccluder::pushCurrentMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
|
||||
_occluderVolume.pushCurrentMask();
|
||||
if (!_holeList.empty())
|
||||
{
|
||||
@@ -138,6 +140,7 @@ inline void ShadowVolumeOccluder::popCurrentMask()
|
||||
itr->popCurrentMask();
|
||||
}
|
||||
}
|
||||
//std::cout<<"ShadowVolumeOccluder::popCurrentMasks() - _occluderVolume.getMaskStack().size()="<<_occluderVolume.getMaskStack().size()<<" "<<_occluderVolume.getCurrentMask()<<std::endl;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
||||
@@ -52,29 +52,11 @@ void write_usage(std::ostream& out,const std::string& name)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
osg::Node* createOccludersAroundModel(osg::Node* model)
|
||||
osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4)
|
||||
{
|
||||
osg::Group* scene = osgNew osg::Group;
|
||||
scene->setName("rootgroup");
|
||||
|
||||
|
||||
// add the loaded model into a the scene group.
|
||||
scene->addChild(model);
|
||||
model->setName("model");
|
||||
|
||||
|
||||
// create and occluder which will site along side the loadmodel model.
|
||||
// create and occluder which will site along side the loadmodel model.
|
||||
osg::OccluderNode* occluderNode = osgNew osg::OccluderNode;
|
||||
|
||||
// get the bounding volume of the model.
|
||||
const osg::BoundingSphere bs = model->getBound();
|
||||
|
||||
// create a bounding box around the sphere.
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
// create the convex planer occluder
|
||||
osg::ConvexPlanerOccluder* cpo = osgNew osg::ConvexPlanerOccluder;
|
||||
|
||||
@@ -84,25 +66,11 @@ osg::Node* createOccludersAroundModel(osg::Node* model)
|
||||
|
||||
// set the occluder up for the front face of the bounding box.
|
||||
osg::ConvexPlanerPolygon& occluder = cpo->getOccluder();
|
||||
occluder.add(osg::Vec3(bb.xMin(),bb.yMin(),bb.zMin()));
|
||||
occluder.add(osg::Vec3(bb.xMax(),bb.yMin(),bb.zMin()));
|
||||
occluder.add(osg::Vec3(bb.xMax(),bb.yMin(),bb.zMax()));
|
||||
occluder.add(osg::Vec3(bb.xMin(),bb.yMin(),bb.zMax()));
|
||||
|
||||
//
|
||||
// // create a hole in the occluder.
|
||||
// osg::Vec3 center((bb.xMin()+bb.xMax())*0.5f,bb.yMin(),(bb.zMin()+bb.zMax())*0.5f);
|
||||
// float dx = (bb.xMax()-bb.xMin())*0.25f;
|
||||
// float dz = (bb.zMax()-bb.zMin())*0.25f;
|
||||
//
|
||||
//
|
||||
// cpo->getHoleList().push_back();
|
||||
// osg::ConvexPlanerPolygon& hole = cpo->getHoleList().back();
|
||||
// hole.add(center+osg::Vec3(-dx,0.0,-dz));
|
||||
// hole.add(center+osg::Vec3(dx,0.0,-dz));
|
||||
// hole.add(center+osg::Vec3(dx,0.0,dz));
|
||||
// hole.add(center+osg::Vec3(-dx,0.0,dz));
|
||||
|
||||
occluder.add(v1);
|
||||
occluder.add(v2);
|
||||
occluder.add(v3);
|
||||
occluder.add(v4);
|
||||
|
||||
|
||||
// create a drawable for occluder.
|
||||
osg::GeoSet* geoset = osgNew osg::GeoSet;
|
||||
@@ -134,8 +102,50 @@ osg::Node* createOccludersAroundModel(osg::Node* model)
|
||||
// geode will never be occluder by this occluder.
|
||||
occluderNode->addChild(geode);
|
||||
|
||||
// add the occluder node into the scene.
|
||||
scene->addChild(occluderNode);
|
||||
return occluderNode;
|
||||
|
||||
}
|
||||
|
||||
osg::Node* createOccludersAroundModel(osg::Node* model)
|
||||
{
|
||||
osg::Group* scene = osgNew osg::Group;
|
||||
scene->setName("rootgroup");
|
||||
|
||||
|
||||
// add the loaded model into a the scene group.
|
||||
scene->addChild(model);
|
||||
model->setName("model");
|
||||
|
||||
// get the bounding volume of the model.
|
||||
const osg::BoundingSphere bs = model->getBound();
|
||||
|
||||
// create a bounding box around the sphere.
|
||||
osg::BoundingBox bb;
|
||||
bb.expandBy(bs);
|
||||
|
||||
// front
|
||||
scene->addChild(createOccluder(bb.corner(0),
|
||||
bb.corner(1),
|
||||
bb.corner(5),
|
||||
bb.corner(4)));
|
||||
|
||||
// right side
|
||||
scene->addChild(createOccluder(bb.corner(1),
|
||||
bb.corner(3),
|
||||
bb.corner(7),
|
||||
bb.corner(5)));
|
||||
|
||||
// left side
|
||||
scene->addChild(createOccluder(bb.corner(2),
|
||||
bb.corner(0),
|
||||
bb.corner(4),
|
||||
bb.corner(6)));
|
||||
|
||||
// back side
|
||||
scene->addChild(createOccluder(bb.corner(3),
|
||||
bb.corner(2),
|
||||
bb.corner(6),
|
||||
bb.corner(7)));
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ CollectOccludersVisitor::CollectOccludersVisitor()
|
||||
FAR_PLANE_CULLING|
|
||||
SMALL_FEATURE_CULLING);
|
||||
|
||||
_minimumShadowOccluderVolume = 0.01f;
|
||||
_minimumShadowOccluderVolume = 0.005f;
|
||||
_createDrawables = false;
|
||||
|
||||
}
|
||||
@@ -107,10 +107,14 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
|
||||
{
|
||||
// need to check if occlusion node is in the occluder
|
||||
// list, if so disable the appropriate ShadowOccluderVolume
|
||||
disableOccluder(_nodePath);
|
||||
disableAndPushOccludersCurrentMask(_nodePath);
|
||||
|
||||
|
||||
if (isCulled(node)) return;
|
||||
if (isCulled(node))
|
||||
{
|
||||
popOccludersCurrentMask(_nodePath);
|
||||
return;
|
||||
}
|
||||
|
||||
// std::cout<<"CollectOccludersVisitor:: We have found an Occlusion node in frustum"<<&node<<std::endl;
|
||||
|
||||
@@ -132,12 +136,12 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
|
||||
if (svo.getVolume()>_minimumShadowOccluderVolume)
|
||||
{
|
||||
// need to test occluder against view frustum.
|
||||
std::cout << " adding in Occluder"<<std::endl;
|
||||
//std::cout << " adding in Occluder"<<std::endl;
|
||||
_occluderList.push_back(svo);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " rejecting Occluder as its volume is too small "<<svo.getVolume()<<std::endl;
|
||||
//std::cout << " rejecting Occluder as its volume is too small "<<svo.getVolume()<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -146,6 +150,9 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
|
||||
// pop the current mask for the disabled occluder
|
||||
popOccludersCurrentMask(_nodePath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,21 +13,53 @@ CullingSet::~CullingSet()
|
||||
{
|
||||
}
|
||||
|
||||
void CullingSet::disableOccluder(NodePath& nodePath)
|
||||
void PrintNodePath(const NodePath& nodePath)
|
||||
{
|
||||
//std::cout<<" trying to disable occluder"<<std::endl;
|
||||
for(NodePath::const_iterator itr=nodePath.begin();
|
||||
itr!=nodePath.end();
|
||||
++itr)
|
||||
{
|
||||
std::cout<<*itr<<" ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CullingSet::disableAndPushOccludersCurrentMask(NodePath& nodePath)
|
||||
{
|
||||
//std::cout<<" trying to disable occluder ";PrintNodePath(nodePath);std::cout<<std::endl;
|
||||
for(OccluderList::iterator itr=_occluderList.begin();
|
||||
itr!=_occluderList.end();
|
||||
++itr)
|
||||
{
|
||||
//std::cout<<" checking against ";PrintNodePath(itr->getNodePath());std::cout<<std::endl;
|
||||
if (itr->getNodePath()==nodePath)
|
||||
{
|
||||
//std::cout<<" ++ disabling occluder"<<std::endl;
|
||||
//std::cout<<" ++ disabling occluder "<<itr<<std::endl;
|
||||
// we have trapped for the case an occlude potentially occluding itself,
|
||||
// to prevent this we disable the results mask so that no subsequnt
|
||||
// when the next pushCurrentMask calls happens this occluder is switched off.
|
||||
itr->disableResultMasks();
|
||||
itr->pushCurrentMask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CullingSet::popOccludersCurrentMask(NodePath& nodePath)
|
||||
{
|
||||
//std::cout<<" trying to pop occluder ";PrintNodePath(nodePath);std::cout<<std::endl;
|
||||
for(OccluderList::iterator itr=_occluderList.begin();
|
||||
itr!=_occluderList.end();
|
||||
++itr)
|
||||
{
|
||||
//std::cout<<" checking against ";PrintNodePath(itr->getNodePath());std::cout<<std::endl;
|
||||
if (itr->getNodePath()==nodePath)
|
||||
{
|
||||
//std::cout<<" popping occluder "<<itr<<std::endl;
|
||||
// we have trapped for the case an occlude potentially occluding itself,
|
||||
// to prevent this we disable the results mask so that no subsequnt
|
||||
// when the next pushCurrentMask calls happens this occluder is switched off.
|
||||
itr->popCurrentMask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,30 +396,44 @@ bool ShadowVolumeOccluder::contains(const std::vector<Vec3>& vertices)
|
||||
|
||||
bool ShadowVolumeOccluder::contains(const BoundingSphere& bound)
|
||||
{
|
||||
//std::cout << "Sphere testing occluder "<<this<<" mask="<<_occluderVolume.getCurrentMask();
|
||||
if (_occluderVolume.containsAllOf(bound))
|
||||
{
|
||||
for(HoleList::iterator itr=_holeList.begin();
|
||||
itr!=_holeList.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->contains(bound)) return false;
|
||||
if (itr->contains(bound))
|
||||
{
|
||||
//std::cout << " - not in occluder"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//std::cout << " - in occluder ******"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
//std::cout << " - not in occluder"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShadowVolumeOccluder::contains(const BoundingBox& bound)
|
||||
{
|
||||
//std::cout << "Box testing occluder "<<this<<" mask="<<_occluderVolume.getCurrentMask();
|
||||
if (_occluderVolume.containsAllOf(bound))
|
||||
{
|
||||
for(HoleList::iterator itr=_holeList.begin();
|
||||
itr!=_holeList.end();
|
||||
++itr)
|
||||
{
|
||||
if (itr->contains(bound)) return false;
|
||||
if (itr->contains(bound))
|
||||
{
|
||||
//std::cout << " + not in occluder"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//std::cout << "+ in occluder ********"<<std::endl;
|
||||
return true;
|
||||
}
|
||||
//std::cout << "+ not in occluder"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -548,12 +548,14 @@ void CullVisitor::apply(osg::OccluderNode& node)
|
||||
{
|
||||
// need to check if occlusion node is in the occluder
|
||||
// list, if so disable the appropriate ShadowOccluderVolume
|
||||
disableOccluder(_nodePath);
|
||||
disableAndPushOccludersCurrentMask(_nodePath);
|
||||
|
||||
// std::cout<<"CullVisitor:: We are in an Occlusion node"<<&node<<std::endl;
|
||||
|
||||
|
||||
if (isCulled(node)) return;
|
||||
if (isCulled(node))
|
||||
{
|
||||
popOccludersCurrentMask(_nodePath);
|
||||
return;
|
||||
}
|
||||
|
||||
// push the culling mode.
|
||||
pushCurrentMask();
|
||||
@@ -571,6 +573,9 @@ void CullVisitor::apply(osg::OccluderNode& node)
|
||||
|
||||
// pop the culling mode.
|
||||
popCurrentMask();
|
||||
|
||||
// pop the current mask for the disabled occluder
|
||||
popOccludersCurrentMask(_nodePath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -138,6 +138,14 @@ void SceneView::app()
|
||||
{
|
||||
if (!_initCalled) init();
|
||||
|
||||
|
||||
|
||||
//std::cout<<std::endl;
|
||||
//std::cout<<std::endl;
|
||||
//std::cout<<"*************************** New frame ************"<<std::endl;
|
||||
|
||||
|
||||
|
||||
if (_sceneData.valid() && _appVisitor.valid())
|
||||
{
|
||||
_appVisitor->reset();
|
||||
@@ -333,7 +341,7 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil
|
||||
cov.popProjectionMatrix();
|
||||
cov.popViewport();
|
||||
|
||||
// std::cout << "finished searching for occluder"<<std::endl;
|
||||
//std::cout << "finished searching for occluder"<<std::endl;
|
||||
|
||||
cullVisitor->setOccluderList(cov.getCollectedOccluderList());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user