Added support for occluders occluding other occluders, which helps reduce
the number of occluder that will be used in cull traversal to only the ones that will be effective. Note. Holes in occluders arn't handled in this occluder occlusion test, will implement this later.
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
#include <osg/OccluderNode>
|
||||
#include <osg/Projection>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace osg;
|
||||
|
||||
CollectOccludersVisitor::CollectOccludersVisitor()
|
||||
@@ -137,7 +139,7 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
|
||||
{
|
||||
// need to test occluder against view frustum.
|
||||
//std::cout << " adding in Occluder"<<std::endl;
|
||||
_occluderList.push_back(svo);
|
||||
_occluderSet.insert(svo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -155,4 +157,41 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node)
|
||||
popOccludersCurrentMask(_nodePath);
|
||||
}
|
||||
|
||||
void CollectOccludersVisitor::removeOccludedOccluders()
|
||||
{
|
||||
if (_occluderSet.empty()) return;
|
||||
|
||||
ShadowVolumeOccluderSet::iterator occludeeItr=_occluderSet.begin();
|
||||
|
||||
// skip the first element as this can't be occluded by anything else.
|
||||
occludeeItr++;
|
||||
|
||||
// step through the rest of the occluders, remove occluders which are themselves occluded.
|
||||
for(;
|
||||
occludeeItr!=_occluderSet.end();
|
||||
++occludeeItr)
|
||||
{
|
||||
|
||||
// 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;
|
||||
for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin();
|
||||
occluderItr!=occludeeItr;
|
||||
++occluderItr)
|
||||
{
|
||||
// cast away constness of the std::set element since ShadowVolumeOccluder::contains() is non const,
|
||||
// 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()))
|
||||
{
|
||||
// erase occluder from set.
|
||||
// take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr.
|
||||
ShadowVolumeOccluderSet::iterator eraseItr = occludeeItr--;
|
||||
_occluderSet.erase(eraseItr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ typedef std::vector<Point> PointList;
|
||||
typedef std::vector<Vec3> VertexList;
|
||||
|
||||
|
||||
// convert a vector for Vec3 into a vector of Point's.
|
||||
void convert(const VertexList& in,PointList& out)
|
||||
// copyVertexListToPointList a vector for Vec3 into a vector of Point's.
|
||||
void copyVertexListToPointList(const VertexList& in,PointList& out)
|
||||
{
|
||||
out.reserve(in.size());
|
||||
for(VertexList::const_iterator itr=in.begin();
|
||||
@@ -26,6 +26,17 @@ void convert(const VertexList& in,PointList& out)
|
||||
}
|
||||
}
|
||||
|
||||
void copyPointListToVertexList(const PointList& in,VertexList& out)
|
||||
{
|
||||
out.reserve(in.size());
|
||||
for(PointList::const_iterator itr=in.begin();
|
||||
itr!=in.end();
|
||||
++itr)
|
||||
{
|
||||
out.push_back(itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
// clip the convex hull 'in' to plane to generate a clipped convex hull 'out'
|
||||
// return true if points remain after clipping.
|
||||
unsigned int clip(const Plane& plane,const PointList& in, PointList& out,unsigned int planeMask)
|
||||
@@ -74,7 +85,7 @@ unsigned int clip(const Plane& plane,const PointList& in, PointList& out,unsigne
|
||||
unsigned int clip(const Polytope::PlaneList& planeList,const VertexList& vin,PointList& out)
|
||||
{
|
||||
PointList in;
|
||||
convert(vin,in);
|
||||
copyVertexListToPointList(vin,in);
|
||||
|
||||
unsigned int planeMask = 0x1;
|
||||
for(Polytope::PlaneList::const_iterator itr=planeList.begin();
|
||||
@@ -138,22 +149,6 @@ Plane computeFrontPlane(const PointList& front)
|
||||
return Plane(front[2].second,front[1].second,front[0].second);
|
||||
}
|
||||
|
||||
|
||||
// // compute the volume of tetrahedron
|
||||
// inline float computeVolume(const osg::Vec3& a,const osg::Vec3& b,const osg::Vec3& c,const osg::Vec3& d)
|
||||
// {
|
||||
// return fabs(((b-c)^(a-b))*(d-b));
|
||||
// }
|
||||
//
|
||||
// // compute the volume of prism.
|
||||
// inline float computeVolume(const osg::Vec3& f1,const osg::Vec3& f2,const osg::Vec3& f3,
|
||||
// const osg::Vec3& b1,const osg::Vec3& b2,const osg::Vec3& b3)
|
||||
// {
|
||||
// return computeVolume(f1,f2,f3,b1)+
|
||||
// computeVolume(b1,b2,b3,f2)+
|
||||
// computeVolume(b1,b3,f2,f3);
|
||||
// }
|
||||
|
||||
// compute the volume between the front and back polygons of the occluder/hole.
|
||||
float computePolytopeVolume(const PointList& front, const PointList& back)
|
||||
{
|
||||
@@ -275,6 +270,10 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
|
||||
// move the occlude points into projection space.
|
||||
transform(points,MV);
|
||||
|
||||
// use the points on the front plane as reference vertices on the _occluderVolume
|
||||
// so that the vertices can later by used to test for occlusion of the occluder itself.
|
||||
copyPointListToVertexList(points,_occluderVolume.getReferenceVertexList());
|
||||
|
||||
// create the front face of the occluder
|
||||
Plane occludePlane = computeFrontPlane(points);
|
||||
_occluderVolume.add(occludePlane);
|
||||
@@ -331,6 +330,10 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex
|
||||
// move the occlude points into projection space.
|
||||
transform(points,MV);
|
||||
|
||||
// use the points on the front plane as reference vertices on the _occluderVolume
|
||||
// so that the vertices can later by used to test for occlusion of the occluder itself.
|
||||
copyPointListToVertexList(points,polytope.getReferenceVertexList());
|
||||
|
||||
// create the front face of the occluder
|
||||
Plane occludePlane = computeFrontPlane(points);
|
||||
|
||||
|
||||
@@ -341,9 +341,14 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil
|
||||
cov.popProjectionMatrix();
|
||||
cov.popViewport();
|
||||
|
||||
//std::cout << "finished searching for occluder"<<std::endl;
|
||||
// sort the occluder from largest occluder volume to smallest.
|
||||
cov.removeOccludedOccluders();
|
||||
|
||||
cullVisitor->setOccluderList(cov.getCollectedOccluderList());
|
||||
|
||||
//std::cout << "finished searching for occluder"<<std::endl;
|
||||
|
||||
cullVisitor->getOccluderList().clear();
|
||||
std::copy(cov.getCollectedOccluderSet().begin(),cov.getCollectedOccluderSet().end(), std::back_insert_iterator<CullStack::OccluderList>(cullVisitor->getOccluderList()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user