osgUtil::CullVisitor* Culling::asCullVisitor(osg::NodeVisitor* nv) { if ( !nv ) return 0L; osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>( nv ); if ( cv ) return cv; ProxyCullVisitor* pcv = dynamic_cast<ProxyCullVisitor*>( nv ); if ( pcv ) return pcv->getCullVisitor(); return 0L; }
void ClampingCullSet::accept(osg::NodeVisitor& nv) { if ( nv.getVisitorType() == nv.CULL_VISITOR ) { ProxyCullVisitor* cv = dynamic_cast<ProxyCullVisitor*>(&nv); // We will use the visitor's path to prevent doubely-applying the statesets // of common ancestors const osg::NodePath& nvPath = nv.getNodePath(); int frame = nv.getFrameStamp() ? nv.getFrameStamp()->getFrameNumber() : 0u; unsigned passed = 0u; for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry ) { if ( frame - entry->_frame > 1 ) continue; // If there's an active (non-identity matrix), apply it if ( entry->_matrix.valid() ) { entry->_matrix->postMult( *cv->getModelViewMatrix() ); cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF ); } // After pushing the matrix, we can perform the culling bounds test. if (!cv->isCulledByProxyFrustum(*entry->_node.get())) { // Apply the statesets in the entry's node path, but skip over the ones that are // shared with the current visitor's path since they are already in effect. // Count them so we can pop them later. int numStateSets = 0; osg::RefNodePath nodePath; if ( entry->_path.getRefNodePath(nodePath) ) { for(unsigned i=0; i<nodePath.size(); ++i) { if (nodePath[i].valid()) { if (i >= nvPath.size() || nvPath[i] != nodePath[i].get()) { osg::StateSet* stateSet = nodePath[i]->getStateSet(); if ( stateSet ) { cv->getCullVisitor()->pushStateSet( stateSet ); ++numStateSets; } } } } } // Cull the DrapeableNode's children (but not the DrapeableNode itself!) for(unsigned i=0; i<entry->_node->getNumChildren(); ++i) { entry->_node->getChild(i)->accept( nv ); } // pop the same number we pushed for(int i=0; i<numStateSets; ++i) { cv->getCullVisitor()->popStateSet(); } ++passed; } // pop the model view: if ( entry->_matrix.valid() ) { cv->popModelViewMatrix(); } //Registry::instance()->startActivity("ClampingCullSet", Stringify() << std::hex << this << std::dec << " / " << passed << "/" << _entries.size()); } // mark this set so it will reset for the next frame _frameCulled = true; } }