Improved handling of bounding polytope

This commit is contained in:
Robert Osfield
2006-11-24 17:20:01 +00:00
parent 006435e679
commit 5044a85c9e
3 changed files with 82 additions and 21 deletions

View File

@@ -22,6 +22,19 @@ public:
}
osg::BoundingBox& getBoundingBox() { return _bb; }
void getPolytope(osg::Polytope& polytope, float margin=0.1) const
{
float delta = _bb.radius()*margin;
polytope.add( osg::Plane(0.0, 0.0, 1.0, -(_bb.zMin()-delta)) );
polytope.add( osg::Plane(0.0, 0.0, -1.0, (_bb.zMax()+delta)) );
polytope.add( osg::Plane(1.0, 0.0, 0.0, -(_bb.xMin()-delta)) );
polytope.add( osg::Plane(-1.0, 0.0, 0.0, (_bb.xMax()+delta)) );
polytope.add( osg::Plane(0.0, 1.0, 0.0, -(_bb.yMin()-delta)) );
polytope.add( osg::Plane(0.0, -1.0, 0.0, (_bb.yMax()+delta)) );
}
void apply(osg::Node& node)
{
@@ -137,24 +150,26 @@ int main(int argc, char** argv)
return 1;
}
ComputeBoundingBoxVisitor cbbv;
model->accept(cbbv);
const osg::BoundingBox& bb = cbbv.getBoundingBox();
osg::Plane basePlane(0.0, 0.0, 1.0, -bb.zMin() );
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osgShadow::OccluderGeometry> occluder = new osgShadow::OccluderGeometry;
occluder->computeOccluderGeometry(model.get());
occluder->getBoundingPolytope().add(basePlane);
ComputeBoundingBoxVisitor cbbv;
model->accept(cbbv);
cbbv.getPolytope(occluder->getBoundingPolytope(),0.001);
osg::BoundingBox bb = cbbv.getBoundingBox();
//geode->addDrawable(occluder.get());
osg::ref_ptr<osgShadow::ShadowVolumeGeometry> shadowVolume = new osgShadow::ShadowVolumeGeometry;
#if 0
occluder->comptueShadowVolumeGeometry(osg::Vec4(bb.xMin(), bb.yMin(), bb.zMax() + bb.radius() ,1.0f), *shadowVolume);
#if 1
// occluder->comptueShadowVolumeGeometry(osg::Vec4(bb.xMin()+ bb.radius(), bb.yMin()+ bb.radius(), bb.zMax() + bb.radius() ,1.0f), *shadowVolume);
occluder->comptueShadowVolumeGeometry(osg::Vec4(bb.center().x(), bb.center().y(), bb.zMax() + bb.radius() ,1.0f), *shadowVolume);
#else
occluder->comptueShadowVolumeGeometry(osg::Vec4(0.5f,-.5f,-1.0f,0.0f), *shadowVolume);
occluder->comptueShadowVolumeGeometry(osg::Vec4(0.5f,.25f,0.2f,0.0f), *shadowVolume);
#endif
geode->addDrawable(shadowVolume.get());

View File

@@ -123,6 +123,14 @@ class OSG_EXPORT Plane
_fv[3];
}
/** calculate the dot product of the plane normal and a point.*/
inline float dotProductNormal(const osg::Vec3& v) const
{
return _fv[0]*v.x()+
_fv[1]*v.y()+
_fv[2]*v.z();
}
/** intersection test between plane and vertex list
return 1 if the bs is completely above plane,
return 0 if the bs intersects the plane,

View File

@@ -743,15 +743,15 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
ShadowVolumeGeometry::Vec3List& shadowNormals = svg.getNormals();
shadowNormals.clear();
osg::Plane basePlane(0.0, 0.0, 1.0, 0.0);
const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
if (!planes.empty())
// need to have some kind of handling of case when no planes exist.
if (_boundingPolytope.getPlaneList().empty())
{
basePlane = planes[0];
osg::notify(osg::NOTICE)<<"Warning: no bounding polytope registered with OccluderGeometry."<<std::endl;
return;
}
if (lightpos.w()==0.0)
{
// directional light.
@@ -759,13 +759,29 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
osg::notify(osg::NOTICE)<<"Directional light"<<std::endl;
// choose the base plane
const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
osg::Polytope::PlaneList::const_iterator pitr = planes.begin();
osg::Plane basePlane = *pitr;
++pitr;
for(;
pitr != planes.end();
++pitr)
{
if (basePlane.dotProductNormal(lightdirection) > pitr->dotProductNormal(lightdirection))
{
basePlane = *pitr;
}
}
// compute the silhouette edge
UIntList silhouetteIndices;
computeLightDirectionSlihouetteEdges(lightdirection, silhouetteIndices);
osg::Vec3 offset( lightdirection*5.0f );
float directionScale = 1.0f / (basePlane.getNormal() * lightdirection);
float directionScale = 1.0f / basePlane.dotProductNormal(lightdirection);
for(UIntList::iterator itr = silhouetteIndices.begin();
itr != silhouetteIndices.end();
@@ -799,10 +815,16 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
// positional light
osg::Vec3 lightposition( lightpos.x(), lightpos.y(), lightpos.z());
osg::Plane basePlane(0.0, 0.0, 1.0, 0.0);
osg::notify(osg::NOTICE)<<"Positional light"<<std::endl;
UIntList silhouetteIndices;
computeLightPositionSlihouetteEdges(lightposition, silhouetteIndices);
osg::notify(osg::NOTICE)<<"basePlane "<<basePlane[0]<<" "<<basePlane[1]<<" "<<basePlane[2]<<" "<<basePlane[3]<<std::endl;
osg::notify(osg::NOTICE)<<"lightpos = "<<std::endl;
const osg::Polytope::PlaneList& planes = _boundingPolytope.getPlaneList();
for(UIntList::iterator itr = silhouetteIndices.begin();
itr != silhouetteIndices.end();
)
@@ -810,14 +832,30 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
const osg::Vec3& v1 = _vertices[*itr++];
const osg::Vec3& v2 = _vertices[*itr++];
osg::Vec3d d1 = v1 - lightposition;
osg::Vec3d d2 = v2 - lightposition;
osg::Vec3 d1 = v1 - lightposition;
osg::Vec3 d2 = v2 - lightposition;
float r1 = basePlane.distance(v1) / (basePlane.getNormal() * d1);
float r2 = basePlane.distance(v2) / (basePlane.getNormal() * d2);
osg::Polytope::PlaneList::const_iterator pitr = planes.begin();
float r1 = - pitr->distance(v1) / (pitr->dotProductNormal(d1));
float r2 = - pitr->distance(v2) / (pitr->dotProductNormal(d2));
++pitr;
osg::Vec3 v1_projected = v1 - (d1 * r1);
osg::Vec3 v2_projected = v2 - (d2 * r2);
for(;
pitr != planes.end();
++pitr)
{
float lr1 = - pitr->distance(v1) / (pitr->dotProductNormal(d1));
float lr2 = - pitr->distance(v2) / (pitr->dotProductNormal(d2));
if (lr1>=0.0f && lr2>=0.0f && (lr1+lr2)<(r1+r2))
{
r1 = lr1;
r2 = lr2;
}
}
osg::Vec3 v1_projected = v1 + (d1 * r1);
osg::Vec3 v2_projected = v2 + (d2 * r2);
shadowVertices.push_back( v1);
shadowVertices.push_back( v1_projected);