Added support for positional lights into computeShadowVolumeGeometry code and cleaned up OccluderGeometry interface.

This commit is contained in:
Robert Osfield
2006-11-24 11:37:57 +00:00
parent 51744272d5
commit 006435e679
3 changed files with 126 additions and 103 deletions

View File

@@ -150,7 +150,12 @@ int main(int argc, char** argv)
//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);
#else
occluder->comptueShadowVolumeGeometry(osg::Vec4(0.5f,-.5f,-1.0f,0.0f), *shadowVolume);
#endif
geode->addDrawable(shadowVolume.get());

View File

@@ -44,19 +44,44 @@ class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable
virtual const char* libraryName() const { return "osgShadow"; }
virtual const char* className() const { return "OccluderGeometry"; }
/** Compute an occluder geometry containing all the geometry in specified subgraph.*/
void computeOccluderGeometry(osg::Node* subgraph, osg::Matrix* matrix=0, float sampleRatio=1.0f);
/** Compute an occluder geometry containing the geometry in specified drawable.*/
void computeOccluderGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f);
/** Compute ShadowVolumeGeometry. */
void comptueShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg) const;
/** Set the bounding polytope of the OccluderGeometry.*/
void setBoundingPolytope(const osg::Polytope& polytope) { _boundingPolytope = polytope; }
/** Get the bounding polytope of the OccluderGeometry.*/
osg::Polytope& getBoundingPolytope() { return _boundingPolytope; }
/** Get the const bounding polytope of the OccluderGeometry.*/
const osg::Polytope& getBoundingPolytope() const { return _boundingPolytope; }
/** Render the occluder geometry. */
virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
/** Compute the bounding box around occluder geometry.*/
virtual osg::BoundingBox computeBound() const;
typedef std::vector<osg::Vec3> Vec3List;
typedef std::vector<GLuint> UIntList;
struct Point
{
Point() {}
public:
UIntList _edges;
};
void processGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f);
typedef std::vector<Point> PointList;
protected :
virtual ~OccluderGeometry() {}
struct Edge
{
Edge():
@@ -115,42 +140,6 @@ class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable
typedef std::vector<Edge> EdgeList;
/** Compute an occluder geometry containing all the geometry in specified subgraph.*/
void computeOccluderGeometry(osg::Node* subgraph, osg::Matrix* matrix=0, float sampleRatio=1.0f);
/** Compute an occluder geometry containing the geometry in specified drawable.*/
void computeOccluderGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f);
/** Compute ShadowVolumeGeometry. */
void comptueShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg);
/** Set the bounding polytope of the OccluderGeometry.*/
void setBoundingPolytope(const osg::Polytope& polytope) { _boundingPolytope = polytope; }
/** Get the bounding polytope of the OccluderGeometry.*/
osg::Polytope& getBoundingPolytope() { return _boundingPolytope; }
/** Get the const bounding polytope of the OccluderGeometry.*/
const osg::Polytope& getBoundingPolytope() const { return _boundingPolytope; }
/** Render the occluder geometry. */
virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
/** Compute the bounding box around occluder geometry.*/
virtual osg::BoundingBox computeBound() const;
public:
void processGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f);
protected :
virtual ~OccluderGeometry() {}
inline bool isLightPointSilhouetteEdge(const osg::Vec3& lightpos, const Edge& edge) const
{
if (edge.boundaryEdge()) return true;
@@ -183,8 +172,8 @@ class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable
void computeNormals();
void buildEdgeMaps();
void computeLightPointSlihouetteEdges(const osg::Vec3& lightpos);
void computeLightDirectionSlihouetteEdges(const osg::Vec3& lightdirection);
void computeLightDirectionSlihouetteEdges(const osg::Vec3& lightdirection, UIntList& silhouetteIndices) const;
void computeLightPositionSlihouetteEdges(const osg::Vec3& lightpos, UIntList& silhouetteIndices) const;
osg::Polytope _boundingPolytope;
@@ -193,9 +182,7 @@ class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable
Vec3List _triangleNormals;
UIntList _triangleIndices;
PointList _points;
EdgeList _edges;
UIntList _silhouetteIndices;
};
class OSGSHADOW_EXPORT ShadowVolumeGeometry : public osg::Drawable

View File

@@ -319,21 +319,12 @@ void OccluderGeometry::setUpInternalStructures()
osg::Timer_t t4 = osg::Timer::instance()->tick();
computeLightDirectionSlihouetteEdges(osg::Vec3(0.0,0.0,1.0f));
osg::Timer_t t45 = osg::Timer::instance()->tick();
computeLightDirectionSlihouetteEdges(osg::Vec3(0.0,0.0,1.0f));
osg::Timer_t t5 = osg::Timer::instance()->tick();
osg::notify(osg::NOTICE)<<"removeDuplicateVertices "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"removeNullTriangles "<<osg::Timer::instance()->delta_m(t1,t2)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"computeNormals "<<osg::Timer::instance()->delta_m(t2,t3)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"buildEdgeMaps "<<osg::Timer::instance()->delta_m(t3,t4)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"computeLightDirectionSlihouetteEdges "<<osg::Timer::instance()->delta_m(t4,t45)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"computeLightDirectionSlihouetteEdges "<<osg::Timer::instance()->delta_m(t45,t5)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"setUpInternalStructures "<<osg::Timer::instance()->delta_m(t0,t5)<<" ms"<<std::endl;
osg::notify(osg::NOTICE)<<"setUpInternalStructures "<<osg::Timer::instance()->delta_m(t0,t4)<<" ms"<<std::endl;
dirtyBound();
@@ -684,53 +675,68 @@ void OccluderGeometry::buildEdgeMaps()
}
void OccluderGeometry::computeLightPointSlihouetteEdges(const osg::Vec3& lightpos)
void OccluderGeometry::computeLightDirectionSlihouetteEdges(const osg::Vec3& lightdirection, UIntList& silhouetteIndices) const
{
_silhouetteIndices.clear();
silhouetteIndices.clear();
for(EdgeList::iterator eitr = _edges.begin();
for(EdgeList::const_iterator eitr = _edges.begin();
eitr != _edges.end();
++eitr)
{
Edge& edge = *eitr;
if (isLightPointSilhouetteEdge(lightpos,edge))
{
_silhouetteIndices.push_back(edge._p1);
_silhouetteIndices.push_back(edge._p2);
}
}
}
void OccluderGeometry::computeLightDirectionSlihouetteEdges(const osg::Vec3& lightdirection)
{
_silhouetteIndices.clear();
for(EdgeList::iterator eitr = _edges.begin();
eitr != _edges.end();
++eitr)
{
Edge& edge = *eitr;
const Edge& edge = *eitr;
if (isLightDirectionSilhouetteEdge(lightdirection,edge))
{
osg::Vec3& v1 = _vertices[edge._p1];
osg::Vec3& v2 = _vertices[edge._p2];
const osg::Vec3& v1 = _vertices[edge._p1];
const osg::Vec3& v2 = _vertices[edge._p2];
osg::Vec3 normal = (v2-v1) ^ lightdirection;
if (normal * edge._normal < 0.0)
{
_silhouetteIndices.push_back(edge._p1);
_silhouetteIndices.push_back(edge._p2);
silhouetteIndices.push_back(edge._p1);
silhouetteIndices.push_back(edge._p2);
}
else
{
_silhouetteIndices.push_back(edge._p2);
_silhouetteIndices.push_back(edge._p1);
silhouetteIndices.push_back(edge._p2);
silhouetteIndices.push_back(edge._p1);
}
}
}
}
void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg)
void OccluderGeometry::computeLightPositionSlihouetteEdges(const osg::Vec3& lightpos, UIntList& silhouetteIndices) const
{
silhouetteIndices.clear();
for(EdgeList::const_iterator eitr = _edges.begin();
eitr != _edges.end();
++eitr)
{
const Edge& edge = *eitr;
if (isLightPointSilhouetteEdge(lightpos,edge))
{
const osg::Vec3& v1 = _vertices[edge._p1];
const osg::Vec3& v2 = _vertices[edge._p2];
osg::Vec3 normal = (v2-v1) ^ (v1-lightpos);
if (normal * edge._normal < 0.0)
{
silhouetteIndices.push_back(edge._p1);
silhouetteIndices.push_back(edge._p2);
}
else
{
silhouetteIndices.push_back(edge._p2);
silhouetteIndices.push_back(edge._p1);
}
}
}
}
void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg) const
{
osg::Timer_t t0 = osg::Timer::instance()->tick();
ShadowVolumeGeometry::Vec3List& shadowVertices = svg.getVertices();
shadowVertices.clear();
@@ -746,25 +752,27 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
basePlane = planes[0];
}
osg::Vec3 offset;
if (lightpos.w()==0.0)
{
// directional light.
osg::Vec3 lightdirection( lightpos.x(), lightpos.y(), lightpos.z());
osg::notify(osg::NOTICE)<<"Directional light"<<std::endl;
computeLightDirectionSlihouetteEdges(lightdirection);
offset = lightdirection*5.0f;
// compute the silhouette edge
UIntList silhouetteIndices;
computeLightDirectionSlihouetteEdges(lightdirection, silhouetteIndices);
osg::Vec3 offset( lightdirection*5.0f );
float directionScale = 1.0f / (basePlane.getNormal() * lightdirection);
for(UIntList::iterator itr = _silhouetteIndices.begin();
itr != _silhouetteIndices.end();
for(UIntList::iterator itr = silhouetteIndices.begin();
itr != silhouetteIndices.end();
)
{
osg::Vec3& v1 = _vertices[*itr++];
osg::Vec3& v2 = _vertices[*itr++];
const osg::Vec3& v1 = _vertices[*itr++];
const osg::Vec3& v2 = _vertices[*itr++];
float r1 = basePlane.distance(v1) * directionScale;
float r2 = basePlane.distance(v2) * directionScale;
@@ -788,19 +796,49 @@ void OccluderGeometry::comptueShadowVolumeGeometry(const osg::Vec4& lightpos, Sh
}
else
{
// positional light
osg::Vec3 lightposition( lightpos.x(), lightpos.y(), lightpos.z());
osg::notify(osg::NOTICE)<<"Positional light"<<std::endl;
computeLightPointSlihouetteEdges(lightposition);
UIntList silhouetteIndices;
computeLightPositionSlihouetteEdges(lightposition, silhouetteIndices);
offset.set(0.0,0.0,-.5);
for(UIntList::iterator itr = silhouetteIndices.begin();
itr != silhouetteIndices.end();
)
{
const osg::Vec3& v1 = _vertices[*itr++];
const osg::Vec3& v2 = _vertices[*itr++];
osg::Vec3d d1 = v1 - lightposition;
osg::Vec3d d2 = v2 - lightposition;
float r1 = basePlane.distance(v1) / (basePlane.getNormal() * d1);
float r2 = basePlane.distance(v2) / (basePlane.getNormal() * d2);
osg::Vec3 v1_projected = v1 - (d1 * r1);
osg::Vec3 v2_projected = v2 - (d2 * r2);
shadowVertices.push_back( v1);
shadowVertices.push_back( v1_projected);
shadowVertices.push_back( v2_projected);
shadowVertices.push_back( v2);
osg::Vec3 normal = (v2-v1) ^ d1;
normal.normalize();
shadowNormals.push_back(normal);
shadowNormals.push_back(normal);
shadowNormals.push_back(normal);
shadowNormals.push_back(normal);
}
}
svg.dirtyDisplayList();
svg.dirtyBound();
osg::Timer_t t1 = osg::Timer::instance()->tick();
osg::notify(osg::NOTICE)<<"comptueShadowVolumeGeometry "<<osg::Timer::instance()->delta_m(t0,t1)<<" ms"<<std::endl;
}
void OccluderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
@@ -818,13 +856,6 @@ void OccluderGeometry::drawImplementation(osg::RenderInfo& renderInfo) const
{
glDrawElements(GL_TRIANGLES, _triangleIndices.size(), GL_UNSIGNED_INT, &(_triangleIndices.front()) );
}
if (!_silhouetteIndices.empty())
{
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glDrawElements(GL_LINES, _silhouetteIndices.size(), GL_UNSIGNED_INT, &(_silhouetteIndices.front()) );
}
}
osg::BoundingBox OccluderGeometry::computeBound() const