source: trunk/VUT/Ogre/src/OgreOcclusionQueriesQueryManager.cpp @ 171

Revision 171, 12.9 KB checked in by mattausch, 19 years ago (diff)

fixed visibilityQueries

Line 
1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
5#include <OgreSubEntity.h>
6
7
8namespace Ogre {
9
10/**
11   These functions necessary to enable sorting of node / mesh / patch info.
12*/
13//-----------------------------------------------------------------------
14inline bool nodeinfo_eq(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
15{
16        return info1.GetNode() == info2.GetNode();
17}
18//-----------------------------------------------------------------------
19inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
20{
21        return info1.GetMesh() == info2.GetMesh();
22}
23//-----------------------------------------------------------------------
24inline bool nodeinfo_lower(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
25{
26        return info1.GetNode() < info2.GetNode();
27}
28//-----------------------------------------------------------------------
29inline bool meshinfo_lower(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
30{
31        return info1.GetMesh() < info2.GetMesh();
32}
33
34
35
36//-----------------------------------------------------------------------
37OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
38                                                        PlatformHierarchyInterface *hierarchyInterface,
39                                                        Viewport *vp,
40                                                        bool renderPatches,
41                                                        bool useItemBufferForGeometry):
42PlatformQueryManager(hierarchyInterface, vp, renderPatches),
43mUseItemBuffer(useItemBufferForGeometry)
44{
45}
46//-----------------------------------------------------------------------
47void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
48                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
49                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
50                                InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
51                            bool relativeVisibility)
52{
53         // we need access to the scene manager and the rendersystem
54        PlatformHierarchyInterface *pfHierarchyInterface =
55                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
56
57        // disable overlays, reset them later
58        bool overlayEnabled = mViewport->getOverlaysEnabled();
59
60        //-- render scene with item buffer (i.e., objects with their id as color codes)
61        if (mUseItemBuffer)
62        {
63                PlatformQueryManager::ComputeCameraVisibility(camera, visibleNodes,
64                            visibleGeometry, visiblePatches, relativeVisibility);
65
66                mViewport->setOverlaysEnabled(false);
67        }
68        else
69        {
70                // const_cast allowed because camera is not changed in renderScene
71                Camera *pCam = const_cast<Camera *>(&camera);
72                mViewport->setOverlaysEnabled(false);
73
74                //-- Render scene to get conservative visibility and fill depth buffer
75                pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
76        }
77
78       
79        /*      Two query lists for projected pixels and for visibile pixels:
80                We test queries after a rendering pass
81                to get exact visibility with regard to the current camera.
82                We issue all queries at once to avoid starvation & stalls.
83        */
84        GtpVisibility::QueryList queryList[2];
85       
86        // rendered hierarchy nodes from previous render
87        GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes();
88        GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end();
89
90        // vector for storing entities of meshes
91        GtpVisibility::GeometryList geometryList;
92       
93        // store geometry of the hierarchy node in a geometry list (only once!)
94        for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
95        {
96                mHierarchyInterface->GetNodeGeometryList(*nodeIt, &geometryList, false);
97        }
98
99        // geometry list iterator
100        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end = geometryList.end();
101
102
103        // to obtain the correct number of projected pixels, depth write must be disabled
104        bool enableDepthWrite = false;
105        // this option must be provided by the scene manager
106        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
107
108
109        /* relative visiblity:
110           1) get visible pixels count of objects
111           2) clear frame buffer
112           3) get projected visible pixels count:
113              test all objects again without depth write (set as option in scene manager)
114           4) calculate ratio between visible vs. projected pixels
115        */
116               
117        // for relative visibility we need 2 rendering passes
118        int n = relativeVisibility ? 2 : 1;
119       
120        for (int i = 0; i < n; ++i)
121        {
122                //-- queries for hierarchy nodes
123                for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
124                {
125                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
126                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false));
127                }
128
129                //-- queries for geometry: if item buffer, capture only projected visibility
130                if (!(mUseItemBuffer && (i == 0)))
131                {
132                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
133                        {
134                                queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt));
135                        }
136                }
137
138                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
139        }
140
141       
142        //-- collect results
143        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
144        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
145       
146        CollectNodeVisibility(visQueryIt, projQueryIt, nodeList, visibleNodes, relativeVisibility);
147
148        if (mUseItemBuffer)
149        {
150                if (relativeVisibility)
151                {
152                        CollectRelativeGeometryVisibilityForItemBuffer(projQueryIt, &geometryList, visibleGeometry);
153                }
154    }
155        else
156        {
157                CollectGeometryVisibility(visQueryIt, projQueryIt, &geometryList,
158                        visibleGeometry, relativeVisibility);
159            //CollectPatchVisibility(patchList, visiblePatches);
160        }
161
162
163        //-- reset options
164        enableDepthWrite = true;
165        // this option must be provided by the scene manager
166        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
167        // reset old overlay status
168        mViewport->setOverlaysEnabled(overlayEnabled);
169
170        mWasInitialised = false;
171}
172//-----------------------------------------------------------------------
173void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
174                               InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
175                               InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
176                                   InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
177                               bool relativeVisibility)
178{
179        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes,
180                visibleGeometry, visiblePatches, relativeVisibility);
181
182        // remove duplicates (duplicates occur if an object is on the edge of the viewport)
183        // before duplicates can be deleted we have to add up their visibility
184        RemoveDuplicateNodes(visibleNodes);
185       
186        if (!mUseItemBuffer)
187        {
188                RemoveDuplicateGeometry(visibleGeometry);
189        }
190}
191//-----------------------------------------------------------------------
192void  OcclusionQueriesQueryManager::CollectNodeVisibility(
193                                                GtpVisibility::QueryList::iterator &visQueryIt,
194                                                GtpVisibility::QueryList::iterator &projQueryIt,
195                                                GtpVisibility::HierarchyNodeList *nodeList, 
196                                                InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
197                                                bool relativeVisibility)
198{
199        GtpVisibility::HierarchyNodeList::iterator nodeIt;
200
201        //-- queries for nodes
202        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++nodeIt)
203        {
204                unsigned int visiblePixels = 0;
205                (*visQueryIt)->GetQueryResult(visiblePixels, true);
206       
207                unsigned int projectedPixels = 0;
208
209                if (relativeVisibility)
210                {
211                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
212               
213                        ++projQueryIt;
214                }
215
216                ++visQueryIt;
217               
218                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
219                if (visiblePixels > 0)
220                {
221                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels,
222                                projectedPixels));
223                }
224        }
225}
226//-----------------------------------------------------------------------
227void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
228                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
229                                                                        GtpVisibility::GeometryList *geometryList,
230                                                                        InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry)
231{
232        GtpVisibility::GeometryList::iterator geometryIt;
233
234        //-- queries for geometry
235        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
236        {
237                unsigned int projectedPixels = 0;
238
239                (*projQueryIt)->GetQueryResult(projectedPixels, true);
240
241                ++projQueryIt;
242                int id = (*geometryIt)->getSubEntity(0)->getId();
243
244                if ((id > 0) && (id < (int)visibleGeometry->size()))
245                {
246                        (*visibleGeometry)[id].AddVisibility(0, projectedPixels);
247                }
248        }
249}
250//-----------------------------------------------------------------------
251void OcclusionQueriesQueryManager::CollectRelativePatchVisibilityForItemBuffer(
252                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
253                                                                        GtpVisibility::PatchList *patchList,
254                                                                        InfoContainer<GtpVisibility::PatchInfo> *visiblePatches)
255{
256        GtpVisibility::PatchList::iterator patchIt;
257
258        //-- queries for geometry
259        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
260        {
261                unsigned int projectedPixels = 0;
262
263                (*projQueryIt)->GetQueryResult(projectedPixels, true);
264
265                ++projQueryIt;
266                int id = (*patchIt)->getId();
267
268                if ((id > 0) && (id < (int)visiblePatches->size()))
269                {
270                        (*visiblePatches)[id].AddVisibility(0, projectedPixels);
271                }
272        }
273}
274//-----------------------------------------------------------------------
275void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
276                                                        GtpVisibility::QueryList::iterator &visQueryIt,
277                                                        GtpVisibility::QueryList::iterator &projQueryIt,
278                                                        GtpVisibility::GeometryList *geometryList,
279                                                        InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
280                                                        bool relativeVisibility)
281{
282        GtpVisibility::GeometryList::iterator geometryIt;
283
284        //-- queries for geometry
285        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
286        {
287                unsigned int visiblePixels = 0;
288                (*visQueryIt)->GetQueryResult(visiblePixels, true);
289               
290                unsigned int projectedPixels = 0;
291
292                if (relativeVisibility)
293                {
294                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
295                        ++ projQueryIt;
296                }
297
298                ++ visQueryIt;
299
300                // WARNING: approximate depth ordering during rendering =>
301                // geometry maybe occluded
302                if (visiblePixels > 0)
303                {                       
304                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
305                                projectedPixels));
306                }
307        }
308}
309//-----------------------------------------------------------------------
310void  OcclusionQueriesQueryManager::CollectPatchVisibility(
311                                                        GtpVisibility::QueryList::iterator &visQueryIt,
312                                                        GtpVisibility::QueryList::iterator &projQueryIt,
313                                                        GtpVisibility::PatchList *patchList,
314                                                        InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
315                                                        bool relativeVisibility)
316{
317        GtpVisibility::PatchList::iterator patchIt;
318
319        //-- queries for patch
320        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
321        {
322                unsigned int visiblePixels = 0;
323                (*visQueryIt)->GetQueryResult(visiblePixels, true);
324               
325                unsigned int projectedPixels = 0;
326
327                if (relativeVisibility)
328                {
329                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
330                        ++ projQueryIt;
331                }
332
333                ++ visQueryIt;
334
335                // WARNING: approximate depth ordering during rendering =>
336                // patch maybe occluded
337                if (visiblePixels > 0)
338                {                       
339                        visiblePatches->push_back(GtpVisibility::PatchInfo(*patchIt, visiblePixels,
340                                projectedPixels));
341                }
342        }
343}
344//-----------------------------------------------------------------------
345void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
346                                        InfoContainer<GtpVisibility::NodeInfo> *visibleNodes)
347{
348        sort(visibleNodes->begin(), visibleNodes->end(), nodeinfo_lower);
349        InfoContainer<GtpVisibility::NodeInfo>::iterator visibleNodesIt,
350                visibleNodesIt_end = visibleNodes->end();
351       
352        GtpVisibility::NodeInfo *nodeInfo = NULL;
353
354        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
355                ++visibleNodesIt)
356        {
357                if (!nodeInfo || (nodeInfo->GetNode() != (*visibleNodesIt).GetNode()))
358                {
359                        nodeInfo = &(*visibleNodesIt);
360                }
361                else // add visibility
362                {                       
363                        nodeInfo->AddVisibility(*visibleNodesIt);
364                }
365        }
366       
367        // physically delete duplicates
368        visibleNodes->erase( std::unique(visibleNodes->begin(),
369                visibleNodes->end(), nodeinfo_eq), visibleNodes->end());
370}
371//-----------------------------------------------------------------------
372void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
373                                InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry)
374{
375        sort(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_lower);
376       
377        InfoContainer<GtpVisibility::MeshInfo>::iterator visibleGeomIt,
378                        visibleGeomIt_end = visibleGeometry->end();
379
380        GtpVisibility::MeshInfo *geomInfo = NULL;
381
382        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
383                ++visibleGeomIt)
384        {
385                if (!geomInfo || (geomInfo->GetMesh() != (*visibleGeomIt).GetMesh()))
386                {
387                        geomInfo = &(*visibleGeomIt);
388                }
389                else // info points to same mesh, just add visibility
390                {
391                        geomInfo->AddVisibility(*visibleGeomIt);
392                }
393        }
394
395        // physically delete duplicates
396        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end(),
397                meshinfo_eq), visibleGeometry->end());
398}
399
400} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.