OcclusionQueryNode: ensure a valid query geometry

If the query geometry is invalid then don't do any occlusion queries and
never traverse the subgraphs.
This commit is contained in:
Daniel Trstenjak 2019-01-29 11:37:28 +01:00 committed by Robert Osfield
parent 9905b90a18
commit 5624a22fe4
2 changed files with 35 additions and 8 deletions

View File

@ -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;

View File

@ -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<Vec3Array> 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() );