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