File: OcclusionQueryNode

package info (click to toggle)
openscenegraph-3.4 3.4.1+dfsg1-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 36,912 kB
  • sloc: cpp: 392,492; ansic: 23,625; java: 1,020; yacc: 548; makefile: 449; objc: 288; xml: 155; lex: 151
file content (206 lines) | stat: -rw-r--r-- 7,507 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
//
// 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;

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

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

    // 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