From 8dc1143263aaf85126b934bbfc5d249d66251809 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 26 Jun 2008 18:34:01 +0000 Subject: [PATCH] From Paul Martz, "The method IntersectionVisitor::apply(osg::PagedLOD&) appears to attempt to identify a "highest res" child of the PagedLOD and only allow intersection on that child. The implementation appears to be flawed in two cases: 1) The "highest res" child is assumed to be the child with index "getNumFileNames()-1" or "getNumChildren()-1". As a result, PagedLODs that do not sort children from furthest to nearest will intersect with the wrong child. (see attached "case1.osg" to reproduce this problem.) 2) The code assumes there is only one highest res child. As a result. PagedLODs with multiple children at the same highest res range can only intersect one of those children. ("case2.osg" demonstrates this issue; you can only pick the quad on the right.) I've attached a modified IntersectionVisitor.cpp that attempts to resolve these issues. It identifies a highest res range based on the range mode, then continues traversal on all valid children corresponding to that range description. Only in the case of a malformed PagedLOD does the code fall back to getting the last child in the list. " --- src/osgUtil/IntersectionVisitor.cpp | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/osgUtil/IntersectionVisitor.cpp b/src/osgUtil/IntersectionVisitor.cpp index 61ef0387e..9c4350eb6 100644 --- a/src/osgUtil/IntersectionVisitor.cpp +++ b/src/osgUtil/IntersectionVisitor.cpp @@ -248,6 +248,72 @@ void IntersectionVisitor::apply(osg::PagedLOD& plod) if (plod.getNumFileNames()>0) { +#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()) @@ -264,6 +330,7 @@ void IntersectionVisitor::apply(osg::PagedLOD& plod) { highestResChild->accept(*this); } +#endif } leave();