Improved handling of bounding polytope
This commit is contained in:
@@ -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());
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user