From 71997fa747f46e54847b2843227d003fb49bb872 Mon Sep 17 00:00:00 2001 From: Daniel Trstenjak Date: Tue, 29 Jan 2019 11:37:28 +0100 Subject: [PATCH] OcclusionQueryNode: ensure a valid query geometry If the query geometry is invalid then don't do any occlusion queries and never traverse the subgraphs. --- include/osg/OcclusionQueryNode | 3 +++ src/osg/OcclusionQueryNode.cpp | 40 +++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/include/osg/OcclusionQueryNode b/include/osg/OcclusionQueryNode index a2c09cabe..f2fb2c229 100644 --- a/include/osg/OcclusionQueryNode +++ b/include/osg/OcclusionQueryNode @@ -198,6 +198,9 @@ protected: bool _enabled; + // If the box of the query geometry is valid. + mutable bool _validQueryGeometry; + // Tracks the last frame number that we performed a query. // User can set how many times (See setQueryFrameCount). typedef std::map< const osg::Camera*, unsigned int > FrameCountMap; diff --git a/src/osg/OcclusionQueryNode.cpp b/src/osg/OcclusionQueryNode.cpp index 65a3e206a..f73dccf79 100644 --- a/src/osg/OcclusionQueryNode.cpp +++ b/src/osg/OcclusionQueryNode.cpp @@ -442,6 +442,7 @@ QueryGeometry::discardDeletedQueryObjects( unsigned int contextID ) OcclusionQueryNode::OcclusionQueryNode() : _enabled( true ), + _validQueryGeometry( false ), _passed(false), _visThreshold( 500 ), _queryFrameCount( 5 ), @@ -459,6 +460,7 @@ OcclusionQueryNode::~OcclusionQueryNode() OcclusionQueryNode::OcclusionQueryNode( const OcclusionQueryNode& oqn, const CopyOp& copyop ) : Group( oqn, copyop ), + _validQueryGeometry( false ), _passed( false ) { _enabled = oqn._enabled; @@ -481,6 +483,14 @@ bool OcclusionQueryNode::getPassed( const Camera* camera, NodeVisitor& nv ) return _passed; } + if ( !_validQueryGeometry ) + { + // The box of the query geometry is invalid, return false to not traverse + // the subgraphs. + _passed = false; + return _passed; + } + { // Two situations where we want to simply do a regular traversal: // 1) it's the first frame for this camera @@ -540,6 +550,9 @@ bool OcclusionQueryNode::getPassed( const Camera* camera, NodeVisitor& nv ) void OcclusionQueryNode::traverseQuery( const Camera* camera, NodeVisitor& nv ) { + if (!_validQueryGeometry) + return; + bool issueQuery; { const int curFrame = nv.getTraversalNumber(); @@ -577,17 +590,28 @@ BoundingSphere OcclusionQueryNode::computeBound() const ComputeBoundsVisitor cbv; nonConstThis->accept( cbv ); BoundingBox bb = cbv.getBoundingBox(); + const bool bbValid = bb.valid(); + _validQueryGeometry = bbValid; osg::ref_ptr v = new Vec3Array; v->resize( 8 ); - (*v)[0] = Vec3( bb._min.x(), bb._min.y(), bb._min.z() ); - (*v)[1] = Vec3( bb._max.x(), bb._min.y(), bb._min.z() ); - (*v)[2] = Vec3( bb._max.x(), bb._min.y(), bb._max.z() ); - (*v)[3] = Vec3( bb._min.x(), bb._min.y(), bb._max.z() ); - (*v)[4] = Vec3( bb._max.x(), bb._max.y(), bb._min.z() ); - (*v)[5] = Vec3( bb._min.x(), bb._max.y(), bb._min.z() ); - (*v)[6] = Vec3( bb._min.x(), bb._max.y(), bb._max.z() ); - (*v)[7] = Vec3( bb._max.x(), bb._max.y(), bb._max.z() ); + + // Having (0,0,0) as vertices for the case of the invalid query geometry + // still isn't quite the right thing. But the query geometry is public + // accessible and therefore a user might expect eight vertices, so + // it seems safer to keep eight vertices in the geometry. + + if (bbValid) + { + (*v)[0] = Vec3( bb._min.x(), bb._min.y(), bb._min.z() ); + (*v)[1] = Vec3( bb._max.x(), bb._min.y(), bb._min.z() ); + (*v)[2] = Vec3( bb._max.x(), bb._min.y(), bb._max.z() ); + (*v)[3] = Vec3( bb._min.x(), bb._min.y(), bb._max.z() ); + (*v)[4] = Vec3( bb._max.x(), bb._max.y(), bb._min.z() ); + (*v)[5] = Vec3( bb._min.x(), bb._max.y(), bb._min.z() ); + (*v)[6] = Vec3( bb._min.x(), bb._max.y(), bb._max.z() ); + (*v)[7] = Vec3( bb._max.x(), bb._max.y(), bb._max.z() ); + } Geometry* geom = static_cast< Geometry* >( nonConstThis->_queryGeode->getDrawable( 0 ) ); geom->setVertexArray( v.get() );