#include #include #include #include #include #include #include using namespace osg; CollectOccludersVisitor::CollectOccludersVisitor() { // overide the default node visitor mode. setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); setCullingMode(VIEW_FRUSTUM_CULLING| NEAR_PLANE_CULLING| FAR_PLANE_CULLING| SMALL_FEATURE_CULLING); _minimumShadowOccluderVolume = 0.005f; _createDrawables = false; } CollectOccludersVisitor::~CollectOccludersVisitor() { } void CollectOccludersVisitor::reset() { CullStack::reset(); } void CollectOccludersVisitor::apply(osg::Node& node) { if (isCulled(node)) return; // push the culling mode. pushCurrentMask(); handle_cull_callbacks_and_traverse(node); // pop the culling mode. popCurrentMask(); } void CollectOccludersVisitor::apply(osg::Transform& node) { if (isCulled(node)) return; // push the culling mode. pushCurrentMask(); ref_ptr matrix = createOrReuseMatrix(getModelViewMatrix()); node.getLocalToWorldMatrix(*matrix,this); pushModelViewMatrix(matrix.get()); handle_cull_callbacks_and_traverse(node); popModelViewMatrix(); // pop the culling mode. popCurrentMask(); } void CollectOccludersVisitor::apply(osg::Projection& node) { if (isCulled(node)) return; // push the culling mode. pushCurrentMask(); ref_ptr matrix = createOrReuseMatrix(node.getMatrix()); pushProjectionMatrix(matrix.get()); handle_cull_callbacks_and_traverse(node); popProjectionMatrix(); // pop the culling mode. popCurrentMask(); } void CollectOccludersVisitor::apply(osg::Switch& node) { apply((Group&)node); } void CollectOccludersVisitor::apply(osg::LOD& node) { if (isCulled(node)) return; int eval = node.evaluate(getEyeLocal(),_LODBias); if (eval<0) return; // push the culling mode. pushCurrentMask(); //notify(INFO) << "selecting child "<_minimumShadowOccluderVolume) { // need to test occluder against view frustum. //std::cout << " adding in Occluder"<(*occludeeItr); ShadowVolumeOccluder::HoleList& holeList = occludee.getHoleList(); for(ShadowVolumeOccluderSet::iterator occluderItr=_occluderSet.begin(); occluderItr!=occludeeItr; ++occluderItr) { // cast away constness of the std::set element since ShadowVolumeOccluder::contains() is non const, // and the std::set is a const, just for the invariance of the operator (&(*occluderItr)); if (occluder->contains(occludee.getOccluder().getReferenceVertexList())) { // erase occluder from set. // take a copy of the iterator then rewind it one element so to prevent invalidating the occludeeItr. ShadowVolumeOccluderSet::iterator eraseItr = occludeeItr--; _occluderSet.erase(eraseItr); break; } // now check all the holes in the occludee against the occluder, // do so in reverse order so that the iterators remain valid. for(ShadowVolumeOccluder::HoleList::reverse_iterator holeItr=holeList.rbegin(); holeItr!=holeList.rend(); ) { if (occluder->contains(holeItr->getReferenceVertexList())) { holeList.erase((++holeItr).base()); } else { ++holeItr; } } } } }