Added support for occlusion of holes in occluders, and cleaned up the

interface to ShadowVolumeOccluders.
This commit is contained in:
Robert Osfield 2002-06-19 10:19:10 +00:00
parent b3c26d5634
commit 21beb236d2
5 changed files with 61 additions and 8 deletions

View File

@ -60,8 +60,22 @@ class SG_EXPORT ShadowVolumeOccluder
inline NodePath& getNodePath() { return _nodePath; }
inline const NodePath& getNodePath() const { return _nodePath; }
/** get the volume of the occluder minus its holes, in eye coords, the volume is normalized by dividing by
* the volume of the view frustum in eye coords.*/
float getVolume() const { return _volume; }
/** return the occluder polytope.*/
Polytope& getOccluder() { return _occluderVolume; }
/** return the const occluder polytope.*/
const Polytope& getOccluder() const { return _occluderVolume; }
/** return the list of holes.*/
HoleList& getHoleList() { return _holeList; }
/** return the const list of holes.*/
const HoleList& getHoleList() const { return _holeList; }
/** return true if the specified vertex list is contaned entirely
@ -88,7 +102,7 @@ class SG_EXPORT ShadowVolumeOccluder
}
// protected:
protected:
float _volume;
NodePath _nodePath;

View File

@ -52,7 +52,7 @@ void write_usage(std::ostream& out,const std::string& name)
}
osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4)
osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3,const osg::Vec3& v4,float holeRatio=-1.0f)
{
// create and occluder which will site along side the loadmodel model.
osg::OccluderNode* occluderNode = osgNew osg::OccluderNode;
@ -70,7 +70,28 @@ osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec
occluder.add(v2);
occluder.add(v3);
occluder.add(v4);
// create a whole at the center of the occluder if needed.
if (holeRatio>0.0f)
{
// create hole.
float ratio = holeRatio;
float one_minus_ratio = 1-ratio;
osg::Vec3 center = (v1+v2+v3+v4)*0.25f;
osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio;
osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio;
osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio;
osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio;
osg::ConvexPlanerPolygon hole;
hole.add(v1dash);
hole.add(v2dash);
hole.add(v3dash);
hole.add(v4dash);
cpo->addHole(hole);
}
// create a drawable for occluder.
osg::GeoSet* geoset = osgNew osg::GeoSet;
@ -145,7 +166,8 @@ osg::Node* createOccludersAroundModel(osg::Node* model)
scene->addChild(createOccluder(bb.corner(3),
bb.corner(2),
bb.corner(6),
bb.corner(7)));
bb.corner(7),
0.5f)); // create a hole half the size of the occluder.
return scene;
}

View File

@ -175,7 +175,9 @@ void CollectOccludersVisitor::removeOccludedOccluders()
// search for any occluders that occlude the current occluder,
// we only need to test any occluder near the front of the set since
// you can't be occluder by something smaller than you.
const ShadowVolumeOccluder& occludee = *occludeeItr;
ShadowVolumeOccluder& occludee = const_cast<ShadowVolumeOccluder&>(*occludeeItr);
ShadowVolumeOccluder::HoleList& holeList = occludee.getHoleList();
for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin();
occluderItr!=occludeeItr;
++occluderItr)
@ -184,7 +186,7 @@ void CollectOccludersVisitor::removeOccludedOccluders()
// and the std::set is a const, just for the invariance of the operator <!! Ahhhhh. oh well the below
// should be robust since contains won't change the getVolume which is used by the operator <. Honest, :-)
ShadowVolumeOccluder* occluder = const_cast<ShadowVolumeOccluder*>(&(*occluderItr));
if (occluder->contains(occludee._occluderVolume.getReferenceVertexList()))
if (occluder->contains(occludee.getOccluder().getReferenceVertexList()))
{
// erase occluder from set.
// take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr.
@ -192,6 +194,20 @@ void CollectOccludersVisitor::removeOccludedOccluders()
_occluderSet.erase(eraseItr);
break;
}
// now check all the holes in the occludee against the occluder,
// do so in reverse order so that the iterators remain valid.
for(ShadowVolumeOccluder::HoleList::reverse_iterator holeItr=holeList.rbegin();
holeItr!=holeList.rend();
++holeItr)
{
if (occluder->contains(holeItr->getReferenceVertexList()))
{
holeList.erase(holeItr.base());
}
}
}
}
}

View File

@ -390,7 +390,8 @@ bool ShadowVolumeOccluder::contains(const std::vector<Vec3>& vertices)
itr!=_holeList.end();
++itr)
{
if (itr->contains(vertices)) return false;
PointList points;
if (clip(itr->getPlaneList(),vertices,points)>=3) return false;
}
return true;
}

View File

@ -345,7 +345,7 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil
cov.removeOccludedOccluders();
//std::cout << "finished searching for occluder"<<std::endl;
//std::cout << "finished searching for occluder - found "<<cov.getCollectedOccluderSet().size()<<std::endl;
cullVisitor->getOccluderList().clear();
std::copy(cov.getCollectedOccluderSet().begin(),cov.getCollectedOccluderSet().end(), std::back_insert_iterator<CullStack::OccluderList>(cullVisitor->getOccluderList()));