Fixes to the occluder culling code to properly disable occluders to prevent

self occlusion.
This commit is contained in:
Robert Osfield
2002-06-17 09:10:26 +00:00
parent 156a9fbaea
commit 27412c27c9
10 changed files with 151 additions and 61 deletions

View File

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

View File

@@ -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:

View File

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

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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