OcclusionQueryNode 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //
  2. // Copyright (C) 2007 Skew Matrix Software LLC (http://www.skew-matrix.com)
  3. //
  4. // This library is open source and may be redistributed and/or modified under
  5. // the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  6. // (at your option) any later version. The full license is in LICENSE file
  7. // included with this distribution, and on the openscenegraph.org website.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // OpenSceneGraph Public License for more details.
  13. //
  14. #ifndef OSG_OCCLUSION_QUERY_NODE
  15. #define OSG_OCCLUSION_QUERY_NODE 1
  16. #include <osg/Export>
  17. #include <osg/CopyOp>
  18. #include <osg/Group>
  19. #include <osg/Geometry>
  20. namespace osg {
  21. // Create and return a StateSet appropriate for performing an occlusion
  22. // query test (disable lighting, texture mapping, etc). Probably some
  23. // room for improvement here. Could disable shaders, for example.
  24. osg::StateSet* initOQState();
  25. // Create and return a StateSet for rendering a debug representation of query geometry.
  26. osg::StateSet* initOQDebugState();
  27. // TestResult -- stores (per context) results of an occlusion query
  28. // test performed by QueryGeometry. An OcclusionQueryNode has a
  29. // Geode owning a single QueryGeometry that
  30. // draws the occlusion query geometry. QueryGeometry keeps a
  31. // TestResult per context to store the result/status of each query.
  32. // Accessed during the cull and draw traversals.
  33. class TestResult : public osg::Referenced
  34. {
  35. public:
  36. TestResult() : _init( false ), _id( 0 ), _contextID( 0 ), _active( false ), _numPixels( 0 ) {setThreadSafeRefUnref(true);}
  37. ~TestResult() {}
  38. bool _init;
  39. // Query ID for this context.
  40. GLuint _id;
  41. // Context ID owning this query ID.
  42. unsigned int _contextID;
  43. // Set to true when a query gets issued and set to
  44. // false when the result is retrieved.
  45. mutable bool _active;
  46. // Result of last query.
  47. GLint _numPixels;
  48. };
  49. // QueryGeometry -- A Drawable that performs an occlusion query,
  50. // using its geometric data as the query geometry.
  51. class OSG_EXPORT QueryGeometry : public osg::Geometry
  52. {
  53. public:
  54. QueryGeometry( const std::string& oqnName=std::string("") );
  55. ~QueryGeometry();
  56. void reset();
  57. // TBD implement copy constructor
  58. virtual void drawImplementation( osg::RenderInfo& renderInfo ) const;
  59. struct QueryResult
  60. {
  61. QueryResult() : valid(false), numPixels(0) {}
  62. QueryResult(bool v, unsigned int p) : valid(v), numPixels(p) {}
  63. bool valid;
  64. unsigned int numPixels;
  65. };
  66. /** 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.*/
  67. QueryResult getQueryResult( const osg::Camera* cam ) const;
  68. unsigned int getNumPixels( const osg::Camera* cam ) const;
  69. virtual void releaseGLObjects( osg::State* state = 0 ) const;
  70. static void deleteQueryObject( unsigned int contextID, GLuint handle );
  71. static void flushDeletedQueryObjects( unsigned int contextID, double currentTime, double& availableTime );
  72. static void discardDeletedQueryObjects( unsigned int contextID );
  73. protected:
  74. typedef std::map< const osg::Camera*, osg::ref_ptr<osg::TestResult> > ResultMap;
  75. mutable ResultMap _results;
  76. mutable OpenThreads::Mutex _mapMutex;
  77. // Needed for debug only
  78. std::string _oqnName;
  79. };
  80. // This Node performs occlusion query testing on its children.
  81. // You can use it directly to occlusion query test a portion
  82. // of your scene graph, or you can use it implicitly with an
  83. // OcclusionQueryRoot, which places OcclusionQueryNodes where
  84. // needed and acts as a master control.
  85. class OSG_EXPORT OcclusionQueryNode : public osg::Group
  86. {
  87. public:
  88. OcclusionQueryNode();
  89. // Copy constructor using CopyOp to manage deep vs shallow copy.
  90. OcclusionQueryNode( const OcclusionQueryNode& oqn, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY );
  91. META_Node( osg, OcclusionQueryNode );
  92. virtual osg::BoundingSphere computeBound() const;
  93. virtual void releaseGLObjects( osg::State* state = 0 ) const;
  94. // When disabled, OQN doesn't perform occlusion queries, and simply
  95. // renders its children.
  96. void setQueriesEnabled( bool enable=true );
  97. bool getQueriesEnabled() const { return _enabled; }
  98. // Sets/gets the visibility threshold. If the test indicates that
  99. // the number of visible pixels is less than the specified
  100. // threshold, don't draw the actual geometry.
  101. void setVisibilityThreshold( unsigned int pixels ) { _visThreshold = pixels; }
  102. unsigned int getVisibilityThreshold() const { return _visThreshold; }
  103. // Specifies how many frames to wait before issuing another query.
  104. void setQueryFrameCount( unsigned int frames ) { _queryFrameCount = frames; }
  105. unsigned int getQueryFrameCount() const { return _queryFrameCount; }
  106. // Resets the queries. The next frame will issue a new query.
  107. // This is useful for big view changes, if it shouldn't be waited for
  108. // '_queryFrameCount' till the frame contents change.
  109. void resetQueries();
  110. // Indicate whether or not the bounding box used in the occlusion query test
  111. // should be rendered. Handy for debugging and development.
  112. // Should only be called outside of cull/draw. No thread issues.
  113. void setDebugDisplay( bool enable );
  114. bool getDebugDisplay() const;
  115. // Set and get the StateSet used by the OcclusionQueryNode
  116. // when rendering the query geometry. OQN creates its own by
  117. // default, but if you use many OQNs you might want to use
  118. // this method to set all OQNs to use the same StateSet
  119. // for more efficient processing.
  120. void setQueryStateSet( osg::StateSet* ss );
  121. osg::StateSet* getQueryStateSet();
  122. const osg::StateSet* getQueryStateSet() const;
  123. // Set and get the QueryGeometry object used for the occlusion query.
  124. // By default an axis aligned box is used as the query geometry.
  125. // Resetting to the default query geometry is done by setting it to 0.
  126. // Returns 0 if no QueryGeometry is created.
  127. void setQueryGeometry( osg::QueryGeometry* geom );
  128. const osg::QueryGeometry* getQueryGeometry() const;
  129. // Set and get the StateSet used by the OcclusionQueryNode
  130. // when rendering the debug query geometry (see setDebugDisplay).
  131. void setDebugStateSet( osg::StateSet* ss );
  132. osg::StateSet* getDebugStateSet();
  133. const osg::StateSet* getDebugStateSet() const;
  134. // For statistics gathering, e.g., by a NodeVisitor.
  135. bool getPassed() const;
  136. // These methods are public so that osgUtil::CullVisitor can access them.
  137. // Not intended for application use.
  138. virtual bool getPassed( const osg::Camera* camera, osg::NodeVisitor& nv );
  139. void traverseQuery( const osg::Camera* camera, osg::NodeVisitor& nv );
  140. void traverseDebug( osg::NodeVisitor& nv );
  141. // Delete unused query IDs for this contextID.
  142. static void flushDeletedQueryObjects( unsigned int contextID, double currentTime, double& availableTime );
  143. // discard all the cached query objects which need to be deleted
  144. // in the OpenGL context related to contextID.
  145. // Note, unlike flush no OpenGL calls are made, instead the handles are all removed.
  146. // this call is useful for when an OpenGL context has been destroyed.
  147. static void discardDeletedQueryObjects( unsigned int contextID );
  148. protected:
  149. enum QueryGeometryState {
  150. INVALID,
  151. VALID,
  152. USER_DEFINED
  153. };
  154. virtual ~OcclusionQueryNode();
  155. virtual void createSupportNodes();
  156. bool isQueryGeometryValid() const { return _queryGeometryState != INVALID; }
  157. void setQueryGeometryInternal( osg::QueryGeometry* queryGeom,
  158. osg::Geometry* debugQueryGeom,
  159. QueryGeometryState state );
  160. void updateDefaultQueryGeometry();
  161. osg::ref_ptr< osg::Geode > _queryGeode;
  162. osg::ref_ptr< osg::Geode > _debugGeode;
  163. bool _enabled;
  164. mutable QueryGeometryState _queryGeometryState;
  165. // Tracks the last frame number that we performed a query.
  166. // User can set how many times (See setQueryFrameCount).
  167. typedef std::map< const osg::Camera*, unsigned int > FrameCountMap;
  168. FrameCountMap _frameCountMap;
  169. mutable OpenThreads::Mutex _frameCountMutex;
  170. // For statistics gathering
  171. bool _passed;
  172. // User-settable variables
  173. unsigned int _visThreshold;
  174. unsigned int _queryFrameCount;
  175. bool _debugBB;
  176. // Required to ensure that computeBound() is thread-safe.
  177. mutable OpenThreads::Mutex _computeBoundMutex;
  178. };
  179. }
  180. #endif