123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- //
- // 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 ) const;
- unsigned int getNumPixels( const osg::Camera* cam ) const;
- 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;
- // Set and get the QueryGeometry object used for the occlusion query.
- // By default an axis aligned box is used as the query geometry.
- // Resetting to the default query geometry is done by setting it to 0.
- // Returns 0 if no QueryGeometry is created.
- void setQueryGeometry( osg::QueryGeometry* geom );
- 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:
- enum QueryGeometryState {
- INVALID,
- VALID,
- USER_DEFINED
- };
- virtual ~OcclusionQueryNode();
- virtual void createSupportNodes();
- bool isQueryGeometryValid() const { return _queryGeometryState != INVALID; }
- void setQueryGeometryInternal( osg::QueryGeometry* queryGeom,
- osg::Geometry* debugQueryGeom,
- QueryGeometryState state );
- void updateDefaultQueryGeometry();
- osg::ref_ptr< osg::Geode > _queryGeode;
- osg::ref_ptr< osg::Geode > _debugGeode;
- bool _enabled;
- mutable QueryGeometryState _queryGeometryState;
- // 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
|