/* -*-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 using namespace osgUtil; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // IntersectorGroup // IntersectorGroup::IntersectorGroup() { } void IntersectorGroup::addIntersector(Intersector* intersector) { _intersectors.push_back(intersector); } void IntersectorGroup::clear() { _intersectors.clear(); } Intersector* IntersectorGroup::clone(osgUtil::IntersectionVisitor& iv) { IntersectorGroup* ig = new IntersectorGroup; // now copy across all intersectors that arn't disabled. for(Intersectors::iterator itr = _intersectors.begin(); itr != _intersectors.end(); ++itr) { if (!(*itr)->disabled()) { ig->addIntersector( (*itr)->clone(iv) ); } } return ig; } bool IntersectorGroup::enter(const osg::Node& node) { if (disabled()) return false; bool foundIntersections = false; for(Intersectors::iterator itr = _intersectors.begin(); itr != _intersectors.end(); ++itr) { if ((*itr)->disabled()) (*itr)->incrementDisabledCount(); else if ((*itr)->enter(node)) foundIntersections = true; else (*itr)->incrementDisabledCount(); } if (!foundIntersections) { // need to call leave to clean up the DisabledCount's. leave(); return false; } // we have found at least one suitable intersector, so return true return true; } void IntersectorGroup::leave() { for(Intersectors::iterator itr = _intersectors.begin(); itr != _intersectors.end(); ++itr) { if ((*itr)->disabled()) (*itr)->decrementDisabledCount(); } } void IntersectorGroup::intersect(osgUtil::IntersectionVisitor& iv, osg::Drawable* drawable) { if (disabled()) return; unsigned int numTested = 0; for(Intersectors::iterator itr = _intersectors.begin(); itr != _intersectors.end(); ++itr) { if (!(*itr)->disabled()) { (*itr)->intersect(iv, drawable); ++numTested; } } // OSG_NOTICE<<"Number testing "<reset(); } } bool IntersectorGroup::containsIntersections() { for(Intersectors::iterator itr = _intersectors.begin(); itr != _intersectors.end(); ++itr) { if ((*itr)->containsIntersections()) return true; } return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // IntersectionVisitor // IntersectionVisitor::IntersectionVisitor(Intersector* intersector, ReadCallback* readCallback) { // override the default node visitor mode. setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); _useKdTreesWhenAvailable = true; _dummyTraversal = false; _lodSelectionMode = USE_HIGHEST_LEVEL_OF_DETAIL; _eyePointDirty = true; LineSegmentIntersector* ls = dynamic_cast(intersector); if (ls) { setReferenceEyePoint(ls->getStart()); setReferenceEyePointCoordinateFrame(ls->getCoordinateFrame()); } else { setReferenceEyePoint(osg::Vec3(0.0f,0.0f,0.0f)); setReferenceEyePointCoordinateFrame(Intersector::VIEW); } setIntersector(intersector); setReadCallback(readCallback); } void IntersectionVisitor::setIntersector(Intersector* intersector) { // keep reference around just in case intersector is already in the _intersectorStack, otherwise the clear could delete it. osg::ref_ptr temp = intersector; _intersectorStack.clear(); if (intersector) _intersectorStack.push_back(intersector); } void IntersectionVisitor::reset() { if (!_intersectorStack.empty()) { osg::ref_ptr intersector = _intersectorStack.front(); intersector->reset(); _intersectorStack.clear(); _intersectorStack.push_back(intersector); } } void IntersectionVisitor::apply(osg::Node& node) { // OSG_NOTICE<<"apply(Node&)"< billboard_matrix = new osg::RefMatrix; if (getViewMatrix()) { if (getModelMatrix()) billboard_matrix->mult( *getModelMatrix(), *getViewMatrix() ); else billboard_matrix->set( *getViewMatrix() ); } else if (getModelMatrix()) billboard_matrix->set( *getModelMatrix() ); billboard.computeMatrix(*billboard_matrix,eye_local,pos); if (getViewMatrix()) billboard_matrix->postMult( osg::Matrix::inverse(*getViewMatrix()) ); pushModelMatrix(billboard_matrix.get()); // now push an new intersector clone transform to the new local coordinates push_clone(); intersect( billboard.getDrawable(i) ); // now push an new intersector clone transform to the new local coordinates pop_clone(); popModelMatrix(); } #else for(unsigned int i=0; i0) { #if 1 // Identify the range value for the highest res child float targetRangeValue; if( plod.getRangeMode() == osg::LOD::DISTANCE_FROM_EYE_POINT ) targetRangeValue = 1e6; // Init high to find min value else targetRangeValue = 0; // Init low to find max value const osg::LOD::RangeList rl = plod.getRangeList(); osg::LOD::RangeList::const_iterator rit; for( rit = rl.begin(); rit != rl.end(); rit++ ) { if( plod.getRangeMode() == osg::LOD::DISTANCE_FROM_EYE_POINT ) { if( rit->first < targetRangeValue ) targetRangeValue = rit->first; } else { if( rit->first > targetRangeValue ) targetRangeValue = rit->first; } } // Perform an intersection test only on children that display // at the maximum resolution. unsigned int childIndex; for( rit = rl.begin(), childIndex = 0; rit != rl.end(); rit++, childIndex++ ) { if( rit->first != targetRangeValue ) // This is not one of the highest res children continue; osg::ref_ptr child( NULL ); if( plod.getNumChildren() > childIndex ) child = plod.getChild( childIndex ); if( (!child.valid()) && (_readCallback.valid()) ) { // Child is NULL; attempt to load it, if we have a readCallback... unsigned int validIndex( childIndex ); if (plod.getNumFileNames() <= childIndex) validIndex = plod.getNumFileNames()-1; child = _readCallback->readNodeFile( plod.getDatabasePath() + plod.getFileName( validIndex ) ); } if ( !child.valid() && plod.getNumChildren()>0) { // Child is still NULL, so just use the one at the end of the list. child = plod.getChild( plod.getNumChildren()-1 ); } if (child.valid()) { child->accept(*this); } } #else // older code than above block, that assumes that the PagedLOD is ordered correctly // i.e. low res children first, no duplicate ranges. osg::ref_ptr highestResChild; if (plod.getNumFileNames() != plod.getNumChildren() && _readCallback.valid()) { highestResChild = _readCallback->readNodeFile( plod.getDatabasePath() + plod.getFileName(plod.getNumFileNames()-1) ); } if ( !highestResChild.valid() && plod.getNumChildren()>0) { highestResChild = plod.getChild( plod.getNumChildren()-1 ); } if (highestResChild.valid()) { highestResChild->accept(*this); } #endif } leave(); } void IntersectionVisitor::apply(osg::Transform& transform) { if (!enter(transform)) return; osg::ref_ptr matrix = _modelStack.empty() ? new osg::RefMatrix() : new osg::RefMatrix(*_modelStack.back()); transform.computeLocalToWorldMatrix(*matrix,this); pushModelMatrix(matrix.get()); // now push an new intersector clone transform to the new local coordinates push_clone(); traverse(transform); // pop the clone. pop_clone(); popModelMatrix(); // tidy up an cached cull variables in the current intersector. leave(); } void IntersectionVisitor::apply(osg::Projection& projection) { if (!enter(projection)) return; pushProjectionMatrix(new osg::RefMatrix(projection.getMatrix()) ); // now push an new intersector clone transform to the new local coordinates push_clone(); traverse(projection); // pop the clone. pop_clone(); popProjectionMatrix(); leave(); } void IntersectionVisitor::apply(osg::Camera& camera) { // OSG_NOTICE<<"apply(Camera&)"<