Added support for occlusion of holes in occluders, and cleaned up the
interface to ShadowVolumeOccluders.
This commit is contained in:
parent
b3c26d5634
commit
21beb236d2
@ -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;
|
||||
|
@ -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;
|
||||
@ -71,6 +71,27 @@ osg::Node* createOccluder(const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec
|
||||
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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()));
|
||||
|
Loading…
Reference in New Issue
Block a user