/* -*-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 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::notify(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) { // overide the default node visitor mode. setTraversalMode(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN); setIntersector(intersector); setReadCallback(readCallback); } void IntersectionVisitor::setIntersector(Intersector* intersector) { // keep refernce around just in case intersector is already in the _intersectorStack, otherwsie 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::notify(osg::NOTICE)<<"apply(Node&)"<0) { osg::ref_ptr highestResChild; if (plod.getNumFileNames() != plod.getNumChildren() && _readCallback.valid()) { highestResChild = _readCallback->readNodeFile( plod.getDatabasePath() + plod.getFileName(plod.getNumFileNames()-1) ); } else if (plod.getNumChildren()>0) { highestResChild = plod.getChild( plod.getNumChildren()-1 ); } if (highestResChild.valid()) { highestResChild->accept(*this); } } 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 variabes 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::notify(osg::NOTICE)<<"apply(Camera&)"<