diff --git a/examples/osgshadow/osgshadow.cpp b/examples/osgshadow/osgshadow.cpp index 6876e8a41..0cacccfbd 100644 --- a/examples/osgshadow/osgshadow.cpp +++ b/examples/osgshadow/osgshadow.cpp @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -707,7 +706,6 @@ int main(int argc, char** argv) arguments.getApplicationUsage()->addCommandLineOption("--receivesShadowMask", "Override default receivesShadowMask (default - 0x1)"); arguments.getApplicationUsage()->addCommandLineOption("--base", "Add a base geometry to test shadows."); - arguments.getApplicationUsage()->addCommandLineOption("--sv", "Select ShadowVolume implementation."); arguments.getApplicationUsage()->addCommandLineOption("--ssm", "Select SoftShadowMap implementation."); arguments.getApplicationUsage()->addCommandLineOption("--sm", "Select ShadowMap implementation."); @@ -873,15 +871,8 @@ int main(int argc, char** argv) } else if (arguments.read("--sv")) { - // hint to tell viewer to request stencil buffer when setting up windows - osg::DisplaySettings::instance()->setMinimumNumStencilBits(8); - - osg::ref_ptr sv = new osgShadow::ShadowVolume; - sv->setDynamicShadowVolumes(updateLightPosition); - while (arguments.read("--two-sided")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED); - while (arguments.read("--two-pass")) sv->setDrawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_PASS); - - shadowedScene->setShadowTechnique(sv.get()); + OSG_NOTICE<<"Warning: ShadowVolume no longer supported."< -#include -#include -#include - -#include - - -namespace osgShadow { - -class ShadowVolumeGeometry; - -/** OccluderGeometry provides a sepecialised geometry representation of objects in scene that occlude light and therefore cast shadows. - * OccluderGeometry supports the computation of silhouette edges and shadow volume geometries, as well as use as geometry that one can rendering - * into a shadow map or end caps for the ZP+ algorithm. OccluderGeometry may be of the same resolution as an underlying geometry that it - * represents, or can be of lower resolution and combine manager separate geometries together into a single shadow casting object. - * OccluderGeometry may be attached as UserData to Nodes or to Drawables. */ -class OSGSHADOW_EXPORT OccluderGeometry : public osg::Drawable -{ - public : - OccluderGeometry(); - - OccluderGeometry(const OccluderGeometry& oc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); - - virtual Object* cloneType() const { return new OccluderGeometry(); } - virtual Object* clone(const osg::CopyOp& copyop) const { return new OccluderGeometry(*this,copyop); } - virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } - 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 computeShadowVolumeGeometry(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 computeBoundingBox() const; - - typedef std::vector Vec3List; - typedef std::vector UIntList; - - public: - - void processGeometry(osg::Drawable* drawable, osg::Matrix* matrix=0, float sampleRatio=1.0f); - - protected : - - virtual ~OccluderGeometry() {} - - struct Edge - { - Edge(): - _p1(0), - _p2(0), - _t1(-1), - _t2(-1) {} - - Edge(unsigned int p1, unsigned int p2): - _p1(p1), - _p2(p2), - _t1(-1), - _t2(-1) - { - if (p1>p2) - { - // swap ordering so p1 is less than or equal to p2 - _p1 = p2; - _p2 = p1; - } - } - - inline bool operator < (const Edge& rhs) const - { - if (_p1 < rhs._p1) return true; - if (_p1 > rhs._p1) return false; - return (_p2 < rhs._p2); - } - - bool addTriangle(unsigned int tri) const - { - if (_t1<0) - { - _t1 = tri; - return true; - } - else if (_t2<0) - { - _t2 = tri; - return true; - } - // argg more than two triangles assigned - return false; - } - - bool boundaryEdge() const { return _t2<0; } - - unsigned int _p1; - unsigned int _p2; - - mutable int _t1; - mutable int _t2; - - mutable osg::Vec3 _normal; - }; - - typedef std::vector EdgeList; - - inline bool isLightPointSilhouetteEdge(const osg::Vec3& lightpos, const Edge& edge) const - { - if (edge.boundaryEdge()) return true; - - float offset = 0.0f; - - osg::Vec3 delta(lightpos-_vertices[edge._p1]); - delta.normalize(); - - float n1 = delta * _triangleNormals[edge._t1] + offset; - float n2 = delta * _triangleNormals[edge._t2] + offset; - - float angle_offset = 0.0f; - - n1 = cos(acosf(n1) + angle_offset); - n2 = cos(acosf(n2) + angle_offset); - - if (n1==0.0f && n2==0.0f) return false; - - return n1*n2 <= 0.0f; - } - - inline bool isLightDirectionSilhouetteEdge(const osg::Vec3& lightdirection, const Edge& edge) const - { - if (edge.boundaryEdge()) return true; - - float offset = 0.0f; - - float n1 = lightdirection * _triangleNormals[edge._t1] + offset; - float n2 = lightdirection * _triangleNormals[edge._t2] + offset; - - float angle_offset = 0.0f; - - n1 = cos(acosf(n1) + angle_offset); - n2 = cos(acosf(n2) + angle_offset); - - if (n1==0.0f && n2==0.0f) return false; - - return n1*n2 <= 0.0f; - } - - void setUpInternalStructures(); - - void removeDuplicateVertices(); - void removeNullTriangles(); - void computeNormals(); - void buildEdgeMaps(); - - void computeLightDirectionSilhouetteEdges(const osg::Vec3& lightdirection, UIntList& silhouetteIndices) const; - void computeLightPositionSilhouetteEdges(const osg::Vec3& lightpos, UIntList& silhouetteIndices) const; - - osg::Polytope _boundingPolytope; - - Vec3List _vertices; - Vec3List _normals; - Vec3List _triangleNormals; - UIntList _triangleIndices; - - EdgeList _edges; -}; - -class OSGSHADOW_EXPORT ShadowVolumeGeometry : public osg::Drawable -{ - public : - ShadowVolumeGeometry(); - - ShadowVolumeGeometry(const ShadowVolumeGeometry& oc, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); - - virtual Object* cloneType() const { return new ShadowVolumeGeometry(); } - virtual Object* clone(const osg::CopyOp& copyop) const { return new ShadowVolumeGeometry(*this,copyop); } - virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } - virtual const char* libraryName() const { return "osgShadow"; } - virtual const char* className() const { return "ShadowVolumeGeometry"; } - - enum DrawMode - { - GEOMETRY, - STENCIL_TWO_PASS, - STENCIL_TWO_SIDED - }; - - void setDrawMode(DrawMode mode) { _drawMode = mode; } - DrawMode getDrawMode() const { return _drawMode; } - - typedef std::vector Vec3List; - typedef std::vector UIntList; - - void setVertices(const Vec3List& vertices) { _vertices = vertices; } - Vec3List& getVertices() { return _vertices; } - const Vec3List& getVertices() const { return _vertices; } - - void setNormals(const Vec3List& normals) { _normals = normals; } - Vec3List& getNormals() { return _normals; } - const Vec3List& getNormals() const { return _normals; } - - - /** Render the occluder geometry. */ - virtual void drawImplementation(osg::RenderInfo& renderInfo) const; - - /** Compute the bounding box around occluder geometry.*/ - virtual osg::BoundingBox computeBoundingBox() const; - - public: - - protected : - - virtual ~ShadowVolumeGeometry() {} - - DrawMode _drawMode; - Vec3List _vertices; - Vec3List _normals; - UIntList _indices; -}; - -} - -#endif diff --git a/include/osgShadow/ShadowVolume b/include/osgShadow/ShadowVolume deleted file mode 100644 index 07efd516d..000000000 --- a/include/osgShadow/ShadowVolume +++ /dev/null @@ -1,91 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ - -#ifndef OSGSHADOW_SHADOWVOLUME -#define OSGSHADOW_SHADOWVOLUME 1 - -#include -#include -#include - -#include -#include - -namespace osgShadow { - -/** ShadowedTexture provides an implementation of shadow textures.*/ -class OSGSHADOW_EXPORT ShadowVolume : public ShadowTechnique -{ - public : - ShadowVolume(); - - ShadowVolume(const ShadowVolume& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); - - META_Object(osgShadow, ShadowVolume); - - - void setDrawMode(osgShadow::ShadowVolumeGeometry::DrawMode drawMode); - osgShadow::ShadowVolumeGeometry::DrawMode getDrawMode() const { return _drawMode; } - - void setDynamicShadowVolumes(bool dynamicShadowVolumes); - bool getDynamicShadowVolumes() const { return _dynamicShadowVolumes; } - - /** initialize the ShadowedScene and local cached data structures.*/ - virtual void init(); - - /** run the update traversal of the ShadowedScene and update any loca chached data structures.*/ - virtual void update(osg::NodeVisitor& nv); - - /** run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/ - virtual void cull(osgUtil::CullVisitor& cv); - - /** Clean scene graph from any shadow technique specific nodes, state and drawables.*/ - virtual void cleanSceneGraph(); - - - /** Resize any per context GLObject buffers to specified size. */ - virtual void resizeGLObjectBuffers(unsigned int maxSize); - - /** If State is non-zero, this function releases any associated OpenGL objects for - * the specified graphics context. Otherwise, releases OpenGL objects - * for all graphics contexts. */ - virtual void releaseGLObjects(osg::State* = 0) const; - - protected : - - virtual ~ShadowVolume(); - - osgShadow::ShadowVolumeGeometry::DrawMode _drawMode; - bool _dynamicShadowVolumes; - - osg::ref_ptr _occluder; - - OpenThreads::Mutex _shadowVolumeMutex; - osg::ref_ptr _shadowVolume; - - osg::Vec4 _lightpos; - - osg::ref_ptr _ambientLight; - osg::ref_ptr _diffuseLight; - - osg::ref_ptr _ss1; - osg::ref_ptr _mainShadowStateSet; - osg::ref_ptr _shadowVolumeStateSet; - osg::ref_ptr _shadowedSceneStateSet; - - -}; - -} - -#endif diff --git a/src/osgPlugins/shadow/ReaderWriterOsgShadow.cpp b/src/osgPlugins/shadow/ReaderWriterOsgShadow.cpp index 723c219ee..d31934908 100644 --- a/src/osgPlugins/shadow/ReaderWriterOsgShadow.cpp +++ b/src/osgPlugins/shadow/ReaderWriterOsgShadow.cpp @@ -11,9 +11,9 @@ */ #include -#include #include #include +#include #include #include @@ -110,15 +110,14 @@ public: osg::ref_ptr technique; if (!params.empty()) { - if (params=="ShadowVolume" || params=="sv") technique = new osgShadow::ShadowVolume; - else if (params=="ShadowTexture" || params=="st") technique = new osgShadow::ShadowTexture; - else if (params=="ShadowMap" || params=="sm") technique = new osgShadow::ShadowMap; -// else if (params=="ParallelSplitShadowMap" || params=="pssm") technique = new osgShadow::ParallelSplitShadowMap; + if (params=="ShadowTexture" || params=="st") technique = new osgShadow::ShadowTexture; + else if (params=="ViewDependentShadowMap" || params=="vdsm") technique = new osgShadow::ViewDependentShadowMap; + else if (params=="ShadowMap" || params=="sm") technique = new osgShadow::ShadowMap; else subFileName += std::string(".") + params; } // default fallback to using ShadowVolume - if (!technique) technique = new osgShadow::ShadowVolume; + if (!technique) technique = new osgShadow::ViewDependentShadowMap; // recursively load the subfile. osg::ref_ptr node = osgDB::readRefNodeFile( subFileName, options ); diff --git a/src/osgShadow/CMakeLists.txt b/src/osgShadow/CMakeLists.txt index 1e2aa74f7..cf9ac58d0 100644 --- a/src/osgShadow/CMakeLists.txt +++ b/src/osgShadow/CMakeLists.txt @@ -18,11 +18,9 @@ SET(LIB_NAME osgShadow) SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) SET(TARGET_H ${HEADER_PATH}/Export - ${HEADER_PATH}/OccluderGeometry ${HEADER_PATH}/ShadowMap ${HEADER_PATH}/ShadowTechnique ${HEADER_PATH}/ShadowTexture - ${HEADER_PATH}/ShadowVolume ${HEADER_PATH}/ShadowedScene ${HEADER_PATH}/ShadowSettings ${HEADER_PATH}/SoftShadowMap @@ -42,11 +40,9 @@ SET(TARGET_H # FIXME: For OS X, need flag for Framework or dylib SET(TARGET_SRC - OccluderGeometry.cpp ShadowMap.cpp ShadowTechnique.cpp ShadowTexture.cpp - ShadowVolume.cpp ShadowedScene.cpp ShadowSettings.cpp SoftShadowMap.cpp diff --git a/src/osgShadow/OccluderGeometry.cpp b/src/osgShadow/OccluderGeometry.cpp deleted file mode 100644 index 7ac19699d..000000000 --- a/src/osgShadow/OccluderGeometry.cpp +++ /dev/null @@ -1,984 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - - -using namespace osgShadow; - -OccluderGeometry::OccluderGeometry() -{ -} - -OccluderGeometry::OccluderGeometry(const OccluderGeometry& oc, const osg::CopyOp& copyop): - osg::Drawable(oc,copyop) -{ - -} - - -class CollectOccludersVisitor : public osg::NodeVisitor -{ -public: - CollectOccludersVisitor(OccluderGeometry* oc, osg::Matrix* matrix, float ratio): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), - _oc(oc), - _ratio(ratio) - { - if (matrix) pushMatrix(*matrix); - } - - META_NodeVisitor("osgShadow","CollectOccludersVisitor") - - void apply(osg::Node& node) - { - if (node.getStateSet()) pushState(node.getStateSet()); - - traverse(node); - - if (node.getStateSet()) popState(); - } - - void apply(osg::Transform& transform) - { - if (transform.getStateSet()) pushState(transform.getStateSet()); - - osg::Matrix matrix; - if (!_matrixStack.empty()) matrix = _matrixStack.back(); - - transform.computeLocalToWorldMatrix(matrix,this); - - pushMatrix(matrix); - - traverse(transform); - - popMatrix(); - - if (transform.getStateSet()) popState(); - } - - void apply(osg::Drawable& drawable) - { - if (drawable.getStateSet()) pushState(drawable.getStateSet()); - - apply(&drawable); - - if (drawable.getStateSet()) popState(); - } - - void pushState(osg::StateSet* stateset) - { - osg::StateAttribute::GLModeValue prevBlendModeValue = _blendModeStack.empty() ? osg::StateAttribute::GLModeValue(osg::StateAttribute::INHERIT) : _blendModeStack.back(); - osg::StateAttribute::GLModeValue newBlendModeValue = stateset->getMode(GL_BLEND); - - if (!(newBlendModeValue & osg::StateAttribute::PROTECTED) && - (prevBlendModeValue & osg::StateAttribute::OVERRIDE) ) - { - newBlendModeValue = prevBlendModeValue; - } - - _blendModeStack.push_back(newBlendModeValue); - } - - void popState() - { - _blendModeStack.pop_back(); - } - - void pushMatrix(osg::Matrix& matrix) - { - _matrixStack.push_back(matrix); - } - - void popMatrix() - { - _matrixStack.pop_back(); - } - - void apply(osg::Drawable* drawable) - { - osg::StateAttribute::GLModeValue blendModeValue = _blendModeStack.empty() ? osg::StateAttribute::GLModeValue(osg::StateAttribute::INHERIT) : _blendModeStack.back(); - if (blendModeValue & osg::StateAttribute::ON) - { - // OSG_NOTICE<<"Ignoring transparent drawable."<processGeometry(drawable, (_matrixStack.empty() ? 0 : &_matrixStack.back()), _ratio); - - } - -protected: - - OccluderGeometry* _oc; - - typedef std::vector MatrixStack; - typedef std::vector ModeStack; - - float _ratio; - MatrixStack _matrixStack; - ModeStack _blendModeStack; - -}; - -void OccluderGeometry::computeOccluderGeometry(osg::Node* subgraph, osg::Matrix* matrix, float sampleRatio) -{ - OSG_NOTICE<<"computeOccluderGeometry(osg::Node* subgraph, float sampleRatio)"<tick(); - - CollectOccludersVisitor cov(this, matrix, sampleRatio); - subgraph->accept(cov); - - setUpInternalStructures(); - - osg::Timer_t endTick = osg::Timer::instance()->tick(); - - OSG_NOTICE<<"done in "<delta_m(startTick, endTick)<<" ms"< VertexPointers; - VertexPointers _vertexPointers; - - OccluderGeometry::Vec3List _tempoaryTriangleVertices; - - TriangleCollector(): - _vertices(0), - _triangleIndices(0), - _matrix(0) { } - - void set(OccluderGeometry::Vec3List* vertices, OccluderGeometry::UIntList* triangleIndices, osg::Matrix* matrix) - { - _vertices = vertices; - _triangleIndices = triangleIndices; - _matrix = matrix; - } - - - // bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r) - inline void operator () (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3) - { - // OSG_NOTICE<<"Triangle ("< maxVertex) maxVertex = *itr; - } - - unsigned int base = _vertices->size(); - unsigned int numberNewVertices = _vertexPointers.empty() ? 0 : (maxVertex - minVertex) + 1; - - // OSG_NOTICE<<"base = "<accept(tc); - - tc.copyToLocalData(); - -#if 0 - for(Vec3List::iterator vitr = _vertices.begin(); - vitr != _vertices.end(); - ++vitr) - { - OSG_NOTICE<<"v "<<*vitr<tick(); - - removeDuplicateVertices(); - - osg::Timer_t t1 = osg::Timer::instance()->tick(); - - removeNullTriangles(); - - osg::Timer_t t2 = osg::Timer::instance()->tick(); - - computeNormals(); - - osg::Timer_t t3 = osg::Timer::instance()->tick(); - - buildEdgeMaps(); - - osg::Timer_t t4 = osg::Timer::instance()->tick(); - - - OSG_NOTICE<<"removeDuplicateVertices "<delta_m(t0,t1)<<" ms"<delta_m(t1,t2)<<" ms"<delta_m(t2,t3)<<" ms"<delta_m(t3,t4)<<" ms"<delta_m(t0,t4)<<" ms"<normalize(); - } - - -} - -void OccluderGeometry::buildEdgeMaps() -{ - // OSG_NOTICE<<"OccluderGeometry::buildEdgeMaps()"< EdgeSet; - EdgeSet edgeSet; - - unsigned int numTriangleErrors = 0; - unsigned int triNo=0; - for(UIntList::iterator titr = _triangleIndices.begin(); - titr != _triangleIndices.end(); - ++triNo) - { - GLuint p1 = *titr++; - GLuint p2 = *titr++; - GLuint p3 = *titr++; - - { - Edge edge12(p1,p2); - EdgeSet::iterator itr = edgeSet.find(edge12); - if (itr == edgeSet.end()) - { - if (!edge12.addTriangle(triNo)) ++numTriangleErrors; - edgeSet.insert(edge12); - } - else - { - if (!itr->addTriangle(triNo)) ++numTriangleErrors; - } - } - - { - Edge edge23(p2,p3); - EdgeSet::iterator itr = edgeSet.find(edge23); - if (itr == edgeSet.end()) - { - if (!edge23.addTriangle(triNo)) ++numTriangleErrors; - edgeSet.insert(edge23); - } - else - { - if (!itr->addTriangle(triNo)) ++numTriangleErrors; - } - } - - { - Edge edge31(p3,p1); - EdgeSet::iterator itr = edgeSet.find(edge31); - if (itr == edgeSet.end()) - { - if (!edge31.addTriangle(triNo)) ++numTriangleErrors; - - edgeSet.insert(edge31); - } - else - { - if (!itr->addTriangle(triNo)) ++numTriangleErrors; - } - } - } - - _edges.clear(); - _edges.reserve(edgeSet.size()); - - unsigned int numEdgesWithNoTriangles = 0; - unsigned int numEdgesWithOneTriangles = 0; - unsigned int numEdgesWithTwoTriangles = 0; - - for(EdgeSet::iterator eitr = edgeSet.begin(); - eitr != edgeSet.end(); - ++eitr) - { - const Edge& edge = *eitr; - osg::Vec3 pos(0.0,0.0,0.0); - osg::Vec3 mid = (_vertices[edge._p1] + _vertices[edge._p2]) * 0.5f; - unsigned int numTriangles = 0; - if (edge._t1>=0) - { - ++numTriangles; - - GLuint p1 = _triangleIndices[edge._t1*3]; - GLuint p2 = _triangleIndices[edge._t1*3+1]; - GLuint p3 = _triangleIndices[edge._t1*3+2]; - GLuint opposite = p1; - if (p1 != edge._p1 && p1 != edge._p2) opposite = p1; - else if (p2 != edge._p1 && p2 != edge._p2) opposite = p2; - else if (p3 != edge._p1 && p3 != edge._p2) opposite = p3; - pos = _vertices[opposite]; - } - - if (edge._t2>=0) - { - ++numTriangles; - - GLuint p1 = _triangleIndices[edge._t2*3]; - GLuint p2 = _triangleIndices[edge._t2*3+1]; - GLuint p3 = _triangleIndices[edge._t2*3+2]; - GLuint opposite = p1; - if (p1 != edge._p1 && p1 != edge._p2) opposite = p1; - else if (p2 != edge._p1 && p2 != edge._p2) opposite = p2; - else if (p3 != edge._p1 && p3 != edge._p2) opposite = p3; - pos += _vertices[opposite]; - } - - switch(numTriangles) - { - case(0): - ++numEdgesWithNoTriangles; - edge._normal.set(0.0,0.0,0.0); - OSG_NOTICE<<"Warning no triangles on edge."< 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::computeLightPositionSilhouetteEdges(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::computeShadowVolumeGeometry(const osg::Vec4& lightpos, ShadowVolumeGeometry& svg) const -{ - // osg::Timer_t t0 = osg::Timer::instance()->tick(); - - ShadowVolumeGeometry::Vec3List& shadowVertices = svg.getVertices(); - shadowVertices.clear(); - - ShadowVolumeGeometry::Vec3List& shadowNormals = svg.getNormals(); - shadowNormals.clear(); - - - // need to have some kind of handling of case when no planes exist. - if (_boundingPolytope.getPlaneList().empty()) - { - OSG_NOTICE<<"Warning: no bounding polytope registered with OccluderGeometry."< pitr->dotProductNormal(lightdirection)) - { - basePlane = *pitr; - } - } - - // compute the silhouette edge - UIntList silhouetteIndices; - computeLightDirectionSilhouetteEdges(lightdirection, silhouetteIndices); - - float directionScale = 1.0f / basePlane.dotProductNormal(lightdirection); - - for(UIntList::iterator itr = silhouetteIndices.begin(); - itr != silhouetteIndices.end(); - ) - { - const osg::Vec3& v1 = _vertices[*itr++]; - const osg::Vec3& v2 = _vertices[*itr++]; - - float r1 = basePlane.distance(v1) * directionScale; - float r2 = basePlane.distance(v2) * directionScale; - - osg::Vec3 v1_projected = v1 - (lightdirection * r1); - osg::Vec3 v2_projected = v2 - (lightdirection * r2); - - shadowVertices.push_back( v1); - shadowVertices.push_back( v1_projected); - shadowVertices.push_back( v2_projected); - shadowVertices.push_back( v2); - - osg::Vec3 normal = lightdirection ^ (v2-v1); - normal.normalize(); - shadowNormals.push_back(normal); - shadowNormals.push_back(normal); - shadowNormals.push_back(normal); - shadowNormals.push_back(normal); - } - - } - else - { - // positional light - osg::Vec3 lightposition( lightpos.x(), lightpos.y(), lightpos.z()); - - osg::Plane basePlane(0.0, 0.0, 1.0, 0.0); - - // OSG_NOTICE<<"Positional light"<delta_m(t0,t1)<<" ms"<disableAllVertexArrays(); - - renderInfo.getState()->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) ); - - if (!_normals.empty()) - { - renderInfo.getState()->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) ); - } - - if (!_triangleIndices.empty()) - { - glDrawElements(GL_TRIANGLES, _triangleIndices.size(), GL_UNSIGNED_INT, &(_triangleIndices.front()) ); - } -} - -osg::BoundingBox OccluderGeometry::computeBoundingBox() const -{ - osg::BoundingBox bb; - for(Vec3List::const_iterator itr = _vertices.begin(); - itr != _vertices.end(); - ++itr) - { - bb.expandBy(*itr); - } - - return bb; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// ShadowVolumeGeometry -// -ShadowVolumeGeometry::ShadowVolumeGeometry(): - _drawMode(GEOMETRY) -{ -} - -ShadowVolumeGeometry::ShadowVolumeGeometry(const ShadowVolumeGeometry& oc, const osg::CopyOp& copyop): - osg::Drawable(oc,copyop), - _drawMode(oc._drawMode) -{ -} - -void ShadowVolumeGeometry::drawImplementation(osg::RenderInfo& renderInfo) const -{ - if (_drawMode==GEOMETRY) - { - osg::State* state = renderInfo.getState(); - - state->disableAllVertexArrays(); - - state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) ); - - if (!_normals.empty()) - { - state->setNormalPointer( GL_FLOAT, 0, &(_normals.front()) ); - } - else - { - state->Normal(0.0f, 0.0f, 0.0f); - } - - - state->Color(0.5f, 1.0f, 1.0f, 1.0f); - - glDrawArrays( GL_QUADS, 0, _vertices.size() ); - } - else if (_drawMode==STENCIL_TWO_PASS) - { - osg::State* state = renderInfo.getState(); - - state->disableAllVertexArrays(); - state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) ); - - // draw front faces of shadow volume - glCullFace(GL_BACK); - glStencilOp( GL_KEEP, GL_KEEP, GL_INCR); - - glDrawArrays( GL_QUADS, 0, _vertices.size() ); - - // draw back faces of shadow volume - glCullFace(GL_FRONT); - glStencilOp( GL_KEEP, GL_KEEP, GL_DECR); - - glDrawArrays( GL_QUADS, 0, _vertices.size() ); - - state->haveAppliedAttribute(osg::StateAttribute::CULLFACE); - state->haveAppliedAttribute(osg::StateAttribute::STENCIL); - - } - else // stencil two sided, note state all set up separately. - { - osg::State* state = renderInfo.getState(); - - state->disableAllVertexArrays(); - state->setVertexPointer( 3, GL_FLOAT, 0, &(_vertices.front()) ); - - glDrawArrays( GL_QUADS, 0, _vertices.size() ); - } -} - -osg::BoundingBox ShadowVolumeGeometry::computeBoundingBox() const -{ - osg::BoundingBox bb; - for(Vec3List::const_iterator itr = _vertices.begin(); - itr != _vertices.end(); - ++itr) - { - bb.expandBy(*itr); - } - - return bb; -} diff --git a/src/osgShadow/ShadowVolume.cpp b/src/osgShadow/ShadowVolume.cpp deleted file mode 100644 index 319afed5c..000000000 --- a/src/osgShadow/ShadowVolume.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield - * - * This library is open source and may be redistributed and/or modified under - * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or - * (at your option) any later version. The full license is in LICENSE file - * included with this distribution, and on the openscenegraph.org website. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * OpenSceneGraph Public License for more details. -*/ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace osgShadow; - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// ShadowVolume -// -ShadowVolume::ShadowVolume(): - _drawMode(osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED), - _dynamicShadowVolumes(false) -{ - // _drawMode = osgShadow::ShadowVolumeGeometry::GEOMETRY; - - OSG_INFO<<"Warning: osgShadow::ShadowVolume technique is still in development, with current limitations that make it unsuitable for deployment. Please contact the osg-users for an update of developements."<osg::Group::traverse(cbbv); - - - osg::Vec4 ambient(0.2,0.2,0.2,1.0); - osg::Vec4 diffuse(0.8,0.8,0.8,1.0); - osg::Vec4 zero_colour(0.0,0.0,0.0,1.0); - - osg::Vec4 lightpos; - lightpos.set(0.5f,0.25f,0.8f,0.0f); - - // set up the occluder - _occluder = new osgShadow::OccluderGeometry; - _occluder->computeOccluderGeometry(_shadowedScene); -// cbbv.getPolytope(_occluder->getBoundingPolytope(),0.001); - cbbv.getBase(_occluder->getBoundingPolytope(),0.001); - - - // set up shadow volume - _shadowVolume = new osgShadow::ShadowVolumeGeometry; - _shadowVolume->setUseDisplayList(!_dynamicShadowVolumes); - _shadowVolume->setDrawMode(_drawMode); - _occluder->computeShadowVolumeGeometry(lightpos, *_shadowVolume); - - osg::ref_ptr geode = new osg::Geode; - _shadowedScene->addChild(geode.get()); - int shadowVolumeBin = 1000; - - if (_drawMode == osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED) - { - OSG_NOTICE<<"STENCIL_TWO_SIDED selected"<getOrCreateStateSet(); - ss_sv1->setRenderBinDetails(shadowVolumeBin, "RenderBin"); - geode->addDrawable(_shadowVolume.get()); - } - else - { - OSG_NOTICE<<"STENCIL_TWO_PASSES selected"<getOrCreateStateSet(); - ss_sv1->setRenderBinDetails(shadowVolumeBin, "RenderBin"); - geode->addDrawable(_shadowVolume.get()); - } - - { - - // first group, render the depth buffer + ambient light contribution - { - _ss1 = new osg::StateSet; - - osg::LightModel* lm1 = new osg::LightModel; - lm1->setAmbientIntensity(ambient); - _ss1->setAttribute(lm1); - - _ambientLight = new osg::Light; - _ambientLight->setAmbient(ambient); - _ambientLight->setDiffuse(zero_colour); - _ss1->setAttributeAndModes(_ambientLight.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - - _ss1->setMode(GL_LIGHTING, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - } - - { - _mainShadowStateSet = new osg::StateSet; - - osg::Depth* depth = new osg::Depth; - depth->setWriteMask(false); - depth->setFunction(osg::Depth::LEQUAL); - _mainShadowStateSet->setAttribute(depth); - _mainShadowStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - } - - { - _shadowVolumeStateSet = new osg::StateSet; - - osg::Depth* depth = new osg::Depth; - depth->setWriteMask(false); - depth->setFunction(osg::Depth::LEQUAL); - _shadowVolumeStateSet->setAttribute(depth); - _shadowVolumeStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); - _shadowVolumeStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); - - - if (_drawMode == osgShadow::ShadowVolumeGeometry::STENCIL_TWO_SIDED) - { - osg::StencilTwoSided* stencil = new osg::StencilTwoSided; - stencil->setFunction(osg::StencilTwoSided::BACK, osg::StencilTwoSided::ALWAYS,0,~0u); - stencil->setOperation(osg::StencilTwoSided::BACK, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::DECR_WRAP); - stencil->setFunction(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::ALWAYS,0,~0u); - stencil->setOperation(osg::StencilTwoSided::FRONT, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::KEEP, osg::StencilTwoSided::INCR_WRAP); - - osg::ColorMask* colourMask = new osg::ColorMask(false, false, false, false); - - _shadowVolumeStateSet->setAttributeAndModes(stencil,osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - _shadowVolumeStateSet->setAttribute(colourMask, osg::StateAttribute::OVERRIDE); - _shadowVolumeStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::OFF); - - - } - else - { - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::ALWAYS,0,~0u); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); - - osg::ColorMask* colourMask = new osg::ColorMask(false, false, false, false); - - _shadowVolumeStateSet->setAttributeAndModes(stencil,osg::StateAttribute::ON); - _shadowVolumeStateSet->setAttribute(colourMask); - _shadowVolumeStateSet->setMode(GL_CULL_FACE,osg::StateAttribute::ON); - } - } - - - { - _shadowedSceneStateSet = new osg::StateSet; - - osg::Depth* depth = new osg::Depth; - depth->setWriteMask(false); - depth->setFunction(osg::Depth::LEQUAL); - _shadowedSceneStateSet->setAttribute(depth); - _shadowedSceneStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); - // _shadowedSceneStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - - osg::LightModel* lm1 = new osg::LightModel; - lm1->setAmbientIntensity(zero_colour); - _shadowedSceneStateSet->setAttribute(lm1); - - _diffuseLight = new osg::Light; - _diffuseLight->setAmbient(zero_colour); - _diffuseLight->setDiffuse(diffuse); - - _shadowedSceneStateSet->setMode(GL_LIGHT0, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - _shadowedSceneStateSet->setAttribute(_diffuseLight.get()); - - // set up the stencil ops so that only operator on this mirrors stencil value. - osg::Stencil* stencil = new osg::Stencil; - stencil->setFunction(osg::Stencil::EQUAL,0,~0u); - stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP); - _shadowedSceneStateSet->setAttributeAndModes(stencil,osg::StateAttribute::ON); - - osg::BlendFunc* blend = new osg::BlendFunc; - blend->setFunction(osg::BlendFunc::ONE, osg::BlendFunc::ONE); - _shadowedSceneStateSet->setAttributeAndModes(blend, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - // _shadowedSceneStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); - } - - _ss1->setThreadSafeRefUnref(true); - _mainShadowStateSet->setThreadSafeRefUnref(true); - _shadowVolumeStateSet->setThreadSafeRefUnref(true); - _shadowedSceneStateSet->setThreadSafeRefUnref(true); - - } - - _dirty = false; -} - -void ShadowVolume::update(osg::NodeVisitor& nv) -{ - _shadowedScene->osg::Group::traverse(nv); -} - -void ShadowVolume::cull(osgUtil::CullVisitor& cv) -{ - - osg::ref_ptr original_bin = cv.getCurrentRenderBin(); - - osg::ref_ptr new_bin = original_bin->find_or_insert(0,"RenderBin"); - - cv.setCurrentRenderBin(new_bin.get()); - - _shadowedScene->osg::Group::traverse(cv); - - cv.setCurrentRenderBin(original_bin.get()); - - osg::ref_ptr shadowVolumeBin; - osgUtil::RenderBin::RenderBinList::iterator rb_itr = new_bin->getRenderBinList().find(1000); - if (rb_itr != new_bin->getRenderBinList().end()) - { - shadowVolumeBin = rb_itr->second; - - if (shadowVolumeBin.valid()) - { - //OSG_NOTICE<<"Found shadow volume bin, now removing it"<getRenderBinList().erase(rb_itr); - } - } - - if (shadowVolumeBin.valid()) - { - original_bin->setStateSet(_ss1.get()); - - osgUtil::RenderStage* orig_rs = cv.getRenderStage(); - osgUtil::RenderStage* new_rs = new osgUtil::RenderStage; - orig_rs->addPostRenderStage(new_rs); - - new_rs->setViewport(orig_rs->getViewport()); - new_rs->setClearColor(orig_rs->getClearColor()); - new_rs->setClearMask(GL_STENCIL_BUFFER_BIT); - new_rs->setDrawBuffer(orig_rs->getDrawBuffer(), orig_rs->getDrawBufferApplyMask()); - new_rs->setReadBuffer(orig_rs->getReadBuffer(), orig_rs->getReadBufferApplyMask()); - new_rs->setColorMask(orig_rs->getColorMask()); - - osg::Vec4 lightpos; - - osg::ref_ptr ps = new osgUtil::PositionalStateContainer; - new_rs->setPositionalStateContainer(ps.get()); - - const osg::Light* selectLight = 0; - - osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList(); - for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin(); - itr != aml.end(); - ++itr) - { - const osg::Light* light = dynamic_cast(itr->first.get()); - if (light) - { - osg::RefMatrix* matrix = itr->second.get(); - if (matrix) lightpos = light->getPosition() * (*matrix); - else lightpos = light->getPosition(); - - selectLight = light; - } - else - { - ps->addPositionedAttribute(itr->second.get(), itr->first.get()); - } - } - - _ambientLight->setPosition(lightpos); - - orig_rs->addPositionedAttribute(0,_ambientLight.get()); - - _diffuseLight->setPosition(lightpos); - if (selectLight) - { - _ambientLight->setAmbient(selectLight->getAmbient()); - - _diffuseLight->setDiffuse(selectLight->getDiffuse()); - _diffuseLight->setSpecular(selectLight->getSpecular()); - _diffuseLight->setDirection(selectLight->getDirection()); - _diffuseLight->setConstantAttenuation(selectLight->getConstantAttenuation()); - _diffuseLight->setLinearAttenuation(selectLight->getLinearAttenuation()); - _diffuseLight->setQuadraticAttenuation(selectLight->getQuadraticAttenuation()); - _diffuseLight->setSpotExponent(selectLight->getSpotExponent()); - _diffuseLight->setSpotCutoff(selectLight->getSpotCutoff()); - } - ps->addPositionedAttribute(0, _diffuseLight.get()); - - if (_lightpos != lightpos && _dynamicShadowVolumes) - { - _lightpos = lightpos; - - osg::Matrix eyeToWorld; - eyeToWorld.invert(*cv.getModelViewMatrix()); - - _occluder->computeShadowVolumeGeometry(lightpos * eyeToWorld, *_shadowVolume); - } - - if (shadowVolumeBin.valid()) - { - // new_rs->setStateSet(_mainShadowStateSet.get()); - new_rs->getRenderBinList()[0] = shadowVolumeBin; - shadowVolumeBin->setStateSet(_shadowVolumeStateSet.get()); - - osg::ref_ptr nested_bin = new_rs->find_or_insert(1,"RenderBin"); - nested_bin->getRenderBinList()[0] = new_bin; - nested_bin->setStateSet(_shadowedSceneStateSet.get()); - } - } - - -} - -void ShadowVolume::cleanSceneGraph() -{ -} - diff --git a/src/osgWrappers/deprecated-dotosg/osgShadow/ShadowVolume.cpp b/src/osgWrappers/deprecated-dotosg/osgShadow/ShadowVolume.cpp index 32ac2d550..9bb024108 100644 --- a/src/osgWrappers/deprecated-dotosg/osgShadow/ShadowVolume.cpp +++ b/src/osgWrappers/deprecated-dotosg/osgShadow/ShadowVolume.cpp @@ -1,5 +1,3 @@ -#include - #include #include @@ -17,7 +15,7 @@ bool ShadowVolume_writeLocalData(const osg::Object &obj, osgDB::Output &fw); REGISTER_DOTOSGWRAPPER(ShadowVolume_Proxy) ( - new osgShadow::ShadowVolume, + 0, "ShadowVolume", "Object ShadowTechnique ShadowVolume", ShadowVolume_readLocalData, diff --git a/src/osgWrappers/serializers/osgShadow/ShadowVolume.cpp b/src/osgWrappers/serializers/osgShadow/ShadowVolume.cpp index 1dbccdf6f..57f009736 100644 --- a/src/osgWrappers/serializers/osgShadow/ShadowVolume.cpp +++ b/src/osgWrappers/serializers/osgShadow/ShadowVolume.cpp @@ -1,8 +1,44 @@ -#include +#include + #include #include #include +namespace osgShadow +{ + +class ShadowVolumeGeometry +{ + public : + enum DrawMode + { + GEOMETRY, + STENCIL_TWO_PASS, + STENCIL_TWO_SIDED + }; +}; + +class ShadowVolume : public osgShadow::ShadowTechnique +{ +public: + ShadowVolume() {} + + ShadowVolume(const ShadowVolume& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) {} + + META_Object(osgShadow, ShadowVolume); + + void setDrawMode(osgShadow::ShadowVolumeGeometry::DrawMode) {} + osgShadow::ShadowVolumeGeometry::DrawMode getDrawMode() const { return osgShadow::ShadowVolumeGeometry::GEOMETRY; } + + void setDynamicShadowVolumes(bool) {} + bool getDynamicShadowVolumes() const { return false; } + + virtual void resizeGLObjectBuffers(unsigned int maxSize) {} + virtual void releaseGLObjects(osg::State* = 0) const {} +}; + +} + REGISTER_OBJECT_WRAPPER( osgShadow_ShadowVolume, new osgShadow::ShadowVolume, osgShadow::ShadowVolume,