diff --git a/include/osg/CollectOccludersVisitor b/include/osg/CollectOccludersVisitor index 1280c3266..6b308d225 100644 --- a/include/osg/CollectOccludersVisitor +++ b/include/osg/CollectOccludersVisitor @@ -50,6 +50,25 @@ class SG_EXPORT CollectOccludersVisitor : public osg::NodeVisitor, public osg::C bool _createDrawables; ShadowVolumeOccluderList _collectedOccluderList; + inline void handle_callbacks_and_traverse(osg::Node& node) + { + osg::NodeCallback* callback = node.getAppCallback(); + if (callback) (*callback)(&node,this); + else if (node.getNumChildrenRequiringAppTraversal()>0) traverse(node); + } + inline void handle_cull_callbacks_and_traverse(osg::Node& node) + { + /*osg::NodeCallback* callback = node.getCullCallback(); + if (callback) (*callback)(&node,this); + else*/ if (node.getNumChildrenWithOccluderNodes()>0) traverse(node); + } + + inline void handle_cull_callbacks_and_accept(osg::Node& node,osg::Node* acceptNode) + { + /*osg::NodeCallback* callback = node.getCullCallback(); + if (callback) (*callback)(&node,this); + else*/ if (node.getNumChildrenWithOccluderNodes()>0) acceptNode->accept(*this); + } }; } diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index d782efd69..00ab54ae8 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -32,7 +32,7 @@ void CollectOccludersVisitor::apply(osg::Node& node) // push the culling mode. pushCurrentMask(); - traverse(node); + handle_cull_callbacks_and_traverse(node); // pop the culling mode. popCurrentMask(); @@ -49,7 +49,7 @@ void CollectOccludersVisitor::apply(osg::Transform& node) node.getLocalToWorldMatrix(*matrix,this); pushModelViewMatrix(matrix.get()); - traverse(node); + handle_cull_callbacks_and_traverse(node); popModelViewMatrix(); @@ -67,7 +67,7 @@ void CollectOccludersVisitor::apply(osg::Projection& node) ref_ptr matrix = createOrReuseMatrix(node.getMatrix()); pushProjectionMatrix(matrix.get()); - traverse(node); + handle_cull_callbacks_and_traverse(node); popProjectionMatrix(); @@ -91,7 +91,7 @@ void CollectOccludersVisitor::apply(osg::LOD& node) pushCurrentMask(); //notify(INFO) << "selecting child "<accept(*this); + handle_cull_callbacks_and_accept(node,node.getChild(eval)); // pop the culling mode. popCurrentMask(); @@ -130,7 +130,7 @@ void CollectOccludersVisitor::apply(osg::OccluderNode& node) } } - traverse(node); + handle_cull_callbacks_and_traverse(node); // pop the culling mode. popCurrentMask(); diff --git a/src/osg/ShadowVolumeOccluder.cpp b/src/osg/ShadowVolumeOccluder.cpp index 44d992b47..93ea66a26 100644 --- a/src/osg/ShadowVolumeOccluder.cpp +++ b/src/osg/ShadowVolumeOccluder.cpp @@ -189,7 +189,6 @@ Drawable* createOccluderDrawable(const PointList& front, const PointList& back) } - bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables) { @@ -274,6 +273,62 @@ bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const Convex geode->addDrawable(createOccluderDrawable(points,farPoints)); } } + + + for(ConvexPlanerOccluder::HoleList::const_iterator hitr=occluder.getHoleList().begin(); + hitr!=occluder.getHoleList().end(); + ++hitr) + { + PointList points; + if (clip(cullingset.getFrustum().getPlaneList(),hitr->getVertexList(),points)>=3) + { + _holeList.push_back(); + Polytope& polytope = _holeList.back(); + + // compute the points on the far plane. + PointList farPoints; + farPoints.reserve(points.size()); + transform(points,farPoints,MVP); + pushToFarPlane(farPoints); + transform(farPoints,invP); + + // move the occlude points into projection space. + transform(points,MV); + + // create the front face of the occluder + Plane occludePlane = computeFrontPlane(points); + + // create the sides of the occluder + computePlanes(points,farPoints,polytope.getPlaneList()); + + polytope.setupMask(); + + // if the front face is pointing away from the eye point flip the whole polytope. + if (occludePlane[3]>0.0f) + { + polytope.flip(); + } + + if (createDrawables && !nodePath.empty()) + { + osg::Group* group = dynamic_cast(nodePath.back()); + if (group) + { + + osg::Matrix invMV; + invMV.invert(MV); + + transform(points,invMV); + transform(farPoints,invMV); + + osg::Geode* geode = osgNew osg::Geode; + group->addChild(geode); + geode->addDrawable(createOccluderDrawable(points,farPoints)); + } + } + } + + } return true;