Added support for positional lights into computeShadowVolumeGeometry code and cleaned up OccluderGeometry interface.
This commit is contained in:
@@ -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());
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user