From d50eacd07e265882b36ebe590f78b68459a27c67 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 26 Feb 2010 10:13:28 +0000 Subject: [PATCH] From Paul Martz, "The changes are very similar to Magne's, except they now take the near plane into account. The changes are: * Change OcclusionQueryNode::getPassed to take a NodeVisitor rather than the distance from BS center to the eye point. Change where CullVisitor calls this method to use the new parameters. * getPassed now exits early and returns true to avoid blinking / blink-in of geometry for the first frame or for out-of-range LOD children coming back into view. * getPassed now considers the distance from the near plane to the bounding sphere (rather than eye point to bounding sphere) when determining if the viewer is "inside" the bounding sphere or not." --- include/osg/OcclusionQueryNode | 2 +- src/osg/OcclusionQueryNode.cpp | 30 ++++++++++++++++++++++++++---- src/osgUtil/CullVisitor.cpp | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/include/osg/OcclusionQueryNode b/include/osg/OcclusionQueryNode index 9a398189c..57aa3c7b1 100644 --- a/include/osg/OcclusionQueryNode +++ b/include/osg/OcclusionQueryNode @@ -88,7 +88,7 @@ public: // These methods are public so that osgUtil::CullVisitor can access them. // Not intended for application use. - bool getPassed( const osg::Camera* camera, float distanceToEyePoint ); + bool getPassed( const osg::Camera* camera, osg::NodeVisitor& nv ); void traverseQuery( const osg::Camera* camera, osg::NodeVisitor& nv ); void traverseDebug( osg::NodeVisitor& nv ); diff --git a/src/osg/OcclusionQueryNode.cpp b/src/osg/OcclusionQueryNode.cpp index 94acf72fd..7b39e9972 100644 --- a/src/osg/OcclusionQueryNode.cpp +++ b/src/osg/OcclusionQueryNode.cpp @@ -552,13 +552,25 @@ OcclusionQueryNode::OcclusionQueryNode( const OcclusionQueryNode& oqn, const osg bool -OcclusionQueryNode::getPassed( const osg::Camera* camera, float distanceToEyePoint ) +OcclusionQueryNode::getPassed( const osg::Camera* camera, osg::NodeVisitor& nv ) { if ( !_enabled ) // Queries are not enabled. The caller should be osgUtil::CullVisitor, // return true to traverse the subgraphs. return true; + { + // Two situations where we want to simply do a regular traversal: + // 1) it's the first frame for this camers + // 2) we haven't rendered for an abnormally long time (probably because we're an out-of-range LOD child) + // In these cases, assume we're visible to avoid blinking. + OpenThreads::ScopedLock lock( _frameCountMutex ); + const int& lastQueryFrame( _frameCountMap[ camera ] ); + if( ( lastQueryFrame == 0 ) || + ( (nv.getTraversalNumber() - lastQueryFrame) > (_queryFrameCount + 1) ) ) + return true; + } + if (_queryGeode->getDrawable( 0 ) == NULL) { osg::notify( osg::FATAL ) << @@ -568,11 +580,21 @@ OcclusionQueryNode::getPassed( const osg::Camera* camera, float distanceToEyePoi } QueryGeometry* qg = static_cast< QueryGeometry* >( _queryGeode->getDrawable( 0 ) ); - // If the distance to the bounding sphere shell is positive, retrieve - // the results. Others (we're inside the BS shell) we are considered + // Get the near plane for the upcoming distance calculation. + float nearPlane; + const osg::Matrix& proj( camera->getProjectionMatrix() ); + if( ( proj(3,3) != 1. ) || ( proj(2,3) != 0. ) || ( proj(1,3) != 0. ) || ( proj(0,3) != 0.) ) + nearPlane = proj(3,2) / (proj(2,2)-1.); // frustum / perspective + else + nearPlane = (proj(3,2)+1.) / proj(2,2); // ortho + + // If the distance from the near plane to the bounding sphere shell is positive, retrieve + // the results. Otherwise (near plane inside the BS shell) we are considered // to have passed and don't need to retrieve the query. const osg::BoundingSphere& bs = getBound(); - float distance = distanceToEyePoint - bs._radius; + float distanceToEyePoint = nv.getDistanceToEyePoint( bs._center, false ); + + float distance = distanceToEyePoint - nearPlane - bs._radius; _passed = ( distance <= 0.f ); if (!_passed) { diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 525961759..53650c630 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1446,7 +1446,7 @@ void CullVisitor::apply(osg::OcclusionQueryNode& node) osg::Camera* camera = getCurrentCamera(); // If previous query indicates visible, then traverse as usual. - if (node.getPassed( camera, getDistanceToEyePoint( node.getBound()._center, false ) )) + if (node.getPassed( camera, *this )) handle_cull_callbacks_and_traverse(node); // Traverse the query subtree if OcclusionQueryNode needs to issue another query.