5624a22fe4
If the query geometry is invalid then don't do any occlusion queries and never traverse the subgraphs.
227 lines
8.1 KiB
Plaintext
227 lines
8.1 KiB
Plaintext
//
|
|
// Copyright (C) 2007 Skew Matrix Software LLC (http://www.skew-matrix.com)
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
#ifndef OSG_OCCLUSION_QUERY_NODE
|
|
#define OSG_OCCLUSION_QUERY_NODE 1
|
|
|
|
#include <osg/Export>
|
|
#include <osg/CopyOp>
|
|
#include <osg/Group>
|
|
#include <osg/Geometry>
|
|
|
|
|
|
namespace osg {
|
|
|
|
// Create and return a StateSet appropriate for performing an occlusion
|
|
// query test (disable lighting, texture mapping, etc). Probably some
|
|
// room for improvement here. Could disable shaders, for example.
|
|
osg::StateSet* initOQState();
|
|
|
|
// Create and return a StateSet for rendering a debug representation of query geometry.
|
|
osg::StateSet* initOQDebugState();
|
|
|
|
// TestResult -- stores (per context) results of an occlusion query
|
|
// test performed by QueryGeometry. An OcclusionQueryNode has a
|
|
// Geode owning a single QueryGeometry that
|
|
// draws the occlusion query geometry. QueryGeometry keeps a
|
|
// TestResult per context to store the result/status of each query.
|
|
// Accessed during the cull and draw traversals.
|
|
class TestResult : public osg::Referenced
|
|
{
|
|
public:
|
|
TestResult() : _init( false ), _id( 0 ), _contextID( 0 ), _active( false ), _numPixels( 0 ) {setThreadSafeRefUnref(true);}
|
|
~TestResult() {}
|
|
|
|
bool _init;
|
|
|
|
// Query ID for this context.
|
|
GLuint _id;
|
|
// Context ID owning this query ID.
|
|
unsigned int _contextID;
|
|
|
|
// Set to true when a query gets issued and set to
|
|
// false when the result is retrieved.
|
|
mutable bool _active;
|
|
|
|
// Result of last query.
|
|
GLint _numPixels;
|
|
};
|
|
|
|
// QueryGeometry -- A Drawable that performs an occlusion query,
|
|
// using its geometric data as the query geometry.
|
|
class OSG_EXPORT QueryGeometry : public osg::Geometry
|
|
{
|
|
public:
|
|
QueryGeometry( const std::string& oqnName=std::string("") );
|
|
~QueryGeometry();
|
|
|
|
void reset();
|
|
|
|
// TBD implement copy constructor
|
|
|
|
virtual void drawImplementation( osg::RenderInfo& renderInfo ) const;
|
|
|
|
struct QueryResult
|
|
{
|
|
QueryResult() : valid(false), numPixels(0) {}
|
|
QueryResult(bool v, unsigned int p) : valid(v), numPixels(p) {}
|
|
|
|
bool valid;
|
|
unsigned int numPixels;
|
|
};
|
|
|
|
/** return a QueryResult for specified Camera, where the QueryResult.valid is true when query results are available, and in which case the QueryResult.numPixels provides the num of pixels in the query result.*/
|
|
QueryResult getQueryResult( const osg::Camera* cam );
|
|
|
|
unsigned int getNumPixels( const osg::Camera* cam );
|
|
|
|
virtual void releaseGLObjects( osg::State* state = 0 ) const;
|
|
|
|
static void deleteQueryObject( unsigned int contextID, GLuint handle );
|
|
static void flushDeletedQueryObjects( unsigned int contextID, double currentTime, double& availableTime );
|
|
static void discardDeletedQueryObjects( unsigned int contextID );
|
|
|
|
protected:
|
|
typedef std::map< const osg::Camera*, osg::ref_ptr<osg::TestResult> > ResultMap;
|
|
mutable ResultMap _results;
|
|
mutable OpenThreads::Mutex _mapMutex;
|
|
|
|
// Needed for debug only
|
|
std::string _oqnName;
|
|
};
|
|
|
|
// This Node performs occlusion query testing on its children.
|
|
// You can use it directly to occlusion query test a portion
|
|
// of your scene graph, or you can use it implicitly with an
|
|
// OcclusionQueryRoot, which places OcclusionQueryNodes where
|
|
// needed and acts as a master control.
|
|
class OSG_EXPORT OcclusionQueryNode : public osg::Group
|
|
{
|
|
public:
|
|
OcclusionQueryNode();
|
|
|
|
// Copy constructor using CopyOp to manage deep vs shallow copy.
|
|
OcclusionQueryNode( const OcclusionQueryNode& oqn, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY );
|
|
|
|
META_Node( osg, OcclusionQueryNode );
|
|
|
|
virtual osg::BoundingSphere computeBound() const;
|
|
|
|
virtual void releaseGLObjects( osg::State* state = 0 ) const;
|
|
|
|
|
|
// When disabled, OQN doesn't perform occlusion queries, and simply
|
|
// renders its children.
|
|
void setQueriesEnabled( bool enable=true );
|
|
bool getQueriesEnabled() const { return _enabled; }
|
|
|
|
|
|
// Sets/gets the visibility threshold. If the test indicates that
|
|
// the number of visible pixels is less than the specified
|
|
// threshold, don't draw the actual geometry.
|
|
void setVisibilityThreshold( unsigned int pixels ) { _visThreshold = pixels; }
|
|
unsigned int getVisibilityThreshold() const { return _visThreshold; }
|
|
|
|
// Specifies how many frames to wait before issuing another query.
|
|
void setQueryFrameCount( unsigned int frames ) { _queryFrameCount = frames; }
|
|
unsigned int getQueryFrameCount() const { return _queryFrameCount; }
|
|
|
|
// Resets the queries. The next frame will issue a new query.
|
|
// This is useful for big view changes, if it shouldn't be waited for
|
|
// '_queryFrameCount' till the frame contents change.
|
|
void resetQueries();
|
|
|
|
// Indicate whether or not the bounding box used in the occlusion query test
|
|
// should be rendered. Handy for debugging and development.
|
|
// Should only be called outside of cull/draw. No thread issues.
|
|
void setDebugDisplay( bool enable );
|
|
bool getDebugDisplay() const;
|
|
|
|
|
|
// Set and get the StateSet used by the OcclusionQueryNode
|
|
// when rendering the query geometry. OQN creates its own by
|
|
// default, but if you use many OQNs you might want to use
|
|
// this method to set all OQNs to use the same StateSet
|
|
// for more efficient processing.
|
|
void setQueryStateSet( osg::StateSet* ss );
|
|
osg::StateSet* getQueryStateSet();
|
|
const osg::StateSet* getQueryStateSet() const;
|
|
|
|
// Get the QueryGeometry object used for occlusion query. Returns 0 if no QueryGeometry is created.
|
|
osg::QueryGeometry* getQueryGeometry();
|
|
const osg::QueryGeometry* getQueryGeometry() const;
|
|
|
|
// Set and get the StateSet used by the OcclusionQueryNode
|
|
// when rendering the debug query geometry (see setDebugDisplay).
|
|
void setDebugStateSet( osg::StateSet* ss );
|
|
osg::StateSet* getDebugStateSet();
|
|
const osg::StateSet* getDebugStateSet() const;
|
|
|
|
// For statistics gathering, e.g., by a NodeVisitor.
|
|
bool getPassed() const;
|
|
|
|
|
|
// These methods are public so that osgUtil::CullVisitor can access them.
|
|
// Not intended for application use.
|
|
virtual bool getPassed( const osg::Camera* camera, osg::NodeVisitor& nv );
|
|
void traverseQuery( const osg::Camera* camera, osg::NodeVisitor& nv );
|
|
void traverseDebug( osg::NodeVisitor& nv );
|
|
|
|
|
|
// Delete unused query IDs for this contextID.
|
|
static void flushDeletedQueryObjects( unsigned int contextID, double currentTime, double& availableTime );
|
|
|
|
// discard all the cached query objects which need to be deleted
|
|
// in the OpenGL context related to contextID.
|
|
// Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
|
|
// this call is useful for when an OpenGL context has been destroyed.
|
|
static void discardDeletedQueryObjects( unsigned int contextID );
|
|
|
|
protected:
|
|
virtual ~OcclusionQueryNode();
|
|
|
|
virtual void createSupportNodes();
|
|
|
|
osg::ref_ptr< osg::Geode > _queryGeode;
|
|
osg::ref_ptr< osg::Geode > _debugGeode;
|
|
|
|
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;
|
|
FrameCountMap _frameCountMap;
|
|
mutable OpenThreads::Mutex _frameCountMutex;
|
|
|
|
// For statistics gathering
|
|
bool _passed;
|
|
|
|
// User-settable variables
|
|
unsigned int _visThreshold;
|
|
unsigned int _queryFrameCount;
|
|
bool _debugBB;
|
|
|
|
|
|
// Required to ensure that computeBound() is thread-safe.
|
|
mutable OpenThreads::Mutex _computeBoundMutex;
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#endif
|