source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreOcclusionQueriesQueryManager.cpp @ 2171

Revision 2171, 16.7 KB checked in by mattausch, 17 years ago (diff)

implemented function for exact visibility queries

Line 
1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
5#include <OgreSubEntity.h>
6#include "OgrePlatformHierarchyInterface.h"
7#include "OgreOcclusionCullingSceneManager.h"
8#include "VisibilityEnvironment.h"
9
10
11
12namespace Ogre {
13
14//-----------------------------------------------------------------------
15OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
16                                                        GtpVisibility::HierarchyInterface *hierarchyInterface,
17                                                        Viewport *vp,
18                                                        int queryModes,
19                                                        int itemBufferMode):
20PlatformQueryManager(hierarchyInterface, vp, queryModes),
21mItemBufferMode(itemBufferMode)
22{
23}
24//-----------------------------------------------------------------------
25void OcclusionQueriesQueryManager::ComputeCameraVisibility(
26                                                                                        const Camera &camera,
27                                                                                        GtpVisibility::NodeInfoContainer *visibleNodes,
28                                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
29                                                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
30                                                                                        bool relativeVisibility)
31{
32        // we need access to the scene manager and the rendersystem
33        PlatformHierarchyInterface *pfHierarchyInterface =
34                static_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
35
36        // disable overlays, reset them later
37        bool overlayEnabled = mViewport->getOverlaysEnabled();
38
39        ///////////
40        //-- render scene with item buffer (i.e., objects with their id as color codes)
41
42        //mItemBufferMode = 0;
43        if (0 &&
44                (mItemBufferMode && mQueryModes) != 0)
45        {
46                int savedQueryModes = mQueryModes;
47                mQueryModes = mItemBufferMode;
48               
49                PlatformQueryManager::ComputeCameraVisibility(camera,
50                                                                                                          visibleNodes,
51                                                                                                          visibleGeometry,
52                                                                                                          visiblePatches,
53                                                                                                          relativeVisibility);
54               
55                // overlays cause false visibility
56                mViewport->setOverlaysEnabled(false);
57                mQueryModes = savedQueryModes;
58        }
59        else
60        {
61                // const_cast allowed because camera is not changed in renderScene
62                Camera *pCam = const_cast<Camera *>(&camera);
63                mViewport->setOverlaysEnabled(false);
64
65                ////////////////////////
66                //-- Render scene to get conservative visibility and fill depth buffer
67
68                OcclusionCullingSceneManager *occlusionSceneMgr =
69                        static_cast<OcclusionCullingSceneManager *>(pfHierarchyInterface->GetSceneManager());
70
71                // no visibility manager available => no visibility scene manager, return
72                GtpVisibility::VisibilityManager *visManager = NULL;   
73               
74                if (!occlusionSceneMgr->getOption("VisibilityManager", &visManager))
75                {
76                        Ogre::LogManager::getSingleton().logMessage("no vismanager found");
77                        return;
78                }
79
80                // use stop and wait culling for from view point queries because probably
81                // no temporal coherence
82                GtpVisibility::VisibilityEnvironment::CullingManagerType occlusionType =
83                        visManager->GetCullingManagerType();
84
85                visManager->SetCullingManager(GtpVisibility::VisibilityEnvironment::STOP_AND_WAIT_CULLING);
86
87                if (1)
88                        occlusionSceneMgr->RenderDepthForQuery(pCam, mViewport);
89                else
90                        pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
91
92                visManager->SetCullingManager(occlusionType);
93        }
94
95       
96        /*      Two query lists for projected pixels and for visibile pixels:
97                We test queries after a rendering pass
98                to get exact visibility with regard to the current camera.
99                We issue all queries at once to avoid starvation & stalls.
100        */
101        GtpVisibility::QueryList queryList[2];
102       
103        // rendered visibile hierarchy nodes from previous rendering
104        GtpVisibility::NodeVector *visNodes = mHierarchyInterface->GetVisibleNodes();
105        GtpVisibility::NodeVector::iterator visNodesIt, visNodesIt_end = visNodes->end();
106
107    GtpVisibility::NodeVector nodeList;
108
109        if (mQueryModes & NODE_VISIBILITY)
110        {
111                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)
112                {
113                        nodeList.push_back((*visNodesIt));
114                }
115        }
116
117        GtpVisibility::NodeVector::iterator nodeIt, nodeIt_end = nodeList.end();
118
119        // vector for storing entities of meshes
120        GtpVisibility::GeometryVector geometryList;
121       
122        // store geometry of the hierarchy nodes in a geometry list
123        if (mQueryModes & GEOMETRY_VISIBILITY)
124        {       
125                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++ visNodesIt)       
126                {
127                        mHierarchyInterface->GetNodeGeometryList(*visNodesIt, &geometryList, false);
128                }
129        }
130       
131        // geometry list iterator
132        GtpVisibility::GeometryVector::iterator geometryIt, geometryIt_end = geometryList.end();
133
134        // vector for storing subentities of meshes
135        GtpVisibility::PatchVector patchList;
136
137        // store patchges of the geometries in a patch list
138        if (mQueryModes & PATCH_VISIBILITY)
139        {
140                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
141                {
142                        GetNodePatchList(*visNodesIt, &patchList);
143                }
144        }
145
146        GtpVisibility::PatchVector::iterator patchIt, patchIt_end = patchList.end();
147
148        // to obtain the correct number of projected pixels, depth write must be disabled
149        bool enableDepthWrite = false;
150        // this option must be provided by the scene manager
151        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
152
153
154        /* relative visiblity:
155           1) get visible pixels count of objects
156           2) clear frame buffer
157           3) get projected visible pixels count:
158              test all objects again without depth write (set as option in scene manager)
159           4) calculate ratio between visible vs. projected pixels
160        */
161               
162        // for relative visibility we need 2 rendering passes
163        int n = relativeVisibility ? 2 : 1;
164        if (mItemBufferMode > 0)
165                LogManager::getSingleton().logMessage("using item buffer");
166
167        for (int i = 0; i < n; ++ i)
168        {
169                //-- queries for hierarchy nodes
170                for (nodeIt = nodeList.begin(); nodeIt != nodeIt_end; ++nodeIt)         
171                {
172                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
173                        queryList[i].push_back(mHierarchyInterface->IssueNodeOcclusionQuery(*nodeIt, false));
174                }
175
176                ////////////////////////////
177                //-- queries for geometry: if item buffer, capture only projected visibility
178
179                if ((mItemBufferMode != GEOMETRY_VISIBILITY) || (i == 1))
180                {                       
181                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++ geometryIt)
182                        {
183                                queryList[i].push_back(pfHierarchyInterface->IssueMeshOcclusionQuery(*geometryIt));
184                        }
185                }
186               
187                ////////////////////////
188                //-- queries for patches: if item buffer, capture only projected visibility
189
190                if ((mItemBufferMode != PATCH_VISIBILITY) || (i == 1))
191                {
192                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
193                        {
194                                queryList[i].push_back(pfHierarchyInterface->IssuePatchOcclusionQuery(*patchIt));
195                        }
196                }
197
198                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
199        }
200
201        ///////////////
202        //-- collect results
203
204        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
205        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
206       
207        // collect occlusion queries for hierarchy nodes
208        CollectNodeVisibility(visQueryIt,
209                                                  projQueryIt,
210                                                  &nodeList,
211                                                  visibleNodes,
212                                                  relativeVisibility);
213
214
215        // collect occlusion queries for geometry
216        if ((mItemBufferMode == GEOMETRY_VISIBILITY) && relativeVisibility)
217        {
218                // if visibility was established using the item buffer,
219                // the array is organized different (e.g., ordered by id, all possible objects)
220                CollectRelativeGeometryVisibilityForItemBuffer(projQueryIt,
221                                                                                                           &geometryList,
222                                                                                                           visibleGeometry);
223        }
224        else if (mItemBufferMode != GEOMETRY_VISIBILITY)
225        {
226                CollectGeometryVisibility(visQueryIt,
227                                                                  projQueryIt,
228                                                                  &geometryList,
229                                                                  visibleGeometry,
230                                                                  relativeVisibility);
231        }
232
233
234        // collect occlusion queries for patches
235        if ((mItemBufferMode == PATCH_VISIBILITY) && relativeVisibility)
236        {
237                CollectRelativePatchVisibilityForItemBuffer(projQueryIt,
238                                                                                                        &patchList,
239                                                                                                        visiblePatches);
240        }
241        else if (mItemBufferMode != PATCH_VISIBILITY)
242        {
243                CollectPatchVisibility(visQueryIt,
244                                                           projQueryIt,
245                                                           &patchList,
246                                                           visiblePatches,
247                                                           relativeVisibility);
248        }       
249
250        ////////////
251        //-- reset state
252
253        enableDepthWrite = true;
254        // this option must be provided by the scene manager
255        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
256        // reset old overlay status
257        mViewport->setOverlaysEnabled(overlayEnabled);
258
259        mWasInitialised = false;
260}
261//-----------------------------------------------------------------------
262void OcclusionQueriesQueryManager::ComputeFromPointVisibility(
263                                                                const Vector3 &point,
264                                                                GtpVisibility::NodeInfoContainer *visibleNodes,
265                                                                GtpVisibility::MeshInfoContainer *visibleGeometry,
266                                                                GtpVisibility::PatchInfoContainer *visiblePatches,
267                                                                bool relativeVisibility)
268{
269        PlatformQueryManager::ComputeFromPointVisibility(point,
270                                                                                                         visibleNodes,
271                                                                                                         visibleGeometry,
272                                                                                                         visiblePatches,
273                                                                                                         relativeVisibility);
274
275        // adds up their visibility and removes duplicates
276        // (duplicates occur if an object is on the edge of the viewport)
277        RemoveDuplicateNodes(visibleNodes);
278
279        if (mItemBufferMode != GEOMETRY_VISIBILITY)
280        {
281                RemoveDuplicateGeometry(visibleGeometry);
282        }
283
284        if (mItemBufferMode != PATCH_VISIBILITY)
285        {
286                RemoveDuplicatePatches(visiblePatches);
287        }
288}
289//------------------------------------------------------------------------
290void OcclusionQueriesQueryManager::CollectNodeVisibility(
291                                                GtpVisibility::QueryList::iterator &visQueryIt,
292                                                GtpVisibility::QueryList::iterator &projQueryIt,
293                                                GtpVisibility::NodeVector *nodeList, 
294                                                GtpVisibility::NodeInfoContainer *visibleNodes,
295                                                bool relativeVisibility)
296{
297        GtpVisibility::NodeVector::iterator nodeIt;
298
299        //-- queries for nodes
300        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++ nodeIt)
301        {
302                unsigned int visiblePixels = 0;
303                (*visQueryIt)->GetQueryResult(visiblePixels, true);
304       
305                unsigned int projectedPixels = 0;
306
307                if (relativeVisibility)
308                {
309                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
310                        ++ projQueryIt;
311                }
312
313                ++ visQueryIt;
314               
315                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
316                if (visiblePixels > 0)
317                {
318                        visibleNodes->push_back(
319                                GtpVisibility::NodeInfo(*nodeIt, visiblePixels, projectedPixels));
320                }
321        }
322}
323//-----------------------------------------------------------------------
324void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
325                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
326                                                                        GtpVisibility::GeometryVector *geometryList,
327                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry)
328{
329        GtpVisibility::GeometryVector::iterator geometryIt;
330
331        //-- queries for geometry
332        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
333        {
334                unsigned int projectedPixels = 0;
335
336                (*projQueryIt)->GetQueryResult(projectedPixels, true);
337
338                ++projQueryIt;
339                int id = (*geometryIt)->getSubEntity(0)->getId();
340
341                if ((id > 0) && (id < (int)visibleGeometry->size()))
342                {
343                        (*visibleGeometry)[id].AddVisibility(0, projectedPixels);
344                }
345        }
346}
347//-----------------------------------------------------------------------
348void OcclusionQueriesQueryManager::CollectRelativePatchVisibilityForItemBuffer(
349                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
350                                                                        GtpVisibility::PatchVector *patchList,
351                                                                        GtpVisibility::PatchInfoContainer *visiblePatches)
352{
353        GtpVisibility::PatchVector::iterator patchIt;
354
355        //-- queries for geometry
356        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
357        {
358                unsigned int projectedPixels = 0;
359
360                (*projQueryIt)->GetQueryResult(projectedPixels, true);
361
362                ++projQueryIt;
363                int id = (*patchIt)->getId();
364
365                if ((id > 0) && (id < (int)visiblePatches->size()))
366                {
367                        (*visiblePatches)[id].AddVisibility(0, projectedPixels);
368                }
369        }
370}
371//-----------------------------------------------------------------------
372void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
373                                                        GtpVisibility::QueryList::iterator &visQueryIt,
374                                                        GtpVisibility::QueryList::iterator &projQueryIt,
375                                                        GtpVisibility::GeometryVector *geometryList,
376                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
377                                                        bool relativeVisibility)
378{
379        GtpVisibility::GeometryVector::iterator geometryIt;
380
381        //-- queries for geometry
382        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
383        {
384                unsigned int visiblePixels = 0;
385                (*visQueryIt)->GetQueryResult(visiblePixels, true);
386               
387                unsigned int projectedPixels = 0;
388
389                if (relativeVisibility)
390                {
391                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
392                        ++ projQueryIt;
393                }
394
395                ++ visQueryIt;
396
397                // WARNING: approximate depth ordering during rendering =>
398                // geometry maybe occluded
399                if (visiblePixels > 0)
400                {                       
401                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
402                                projectedPixels));
403                }
404        }
405}
406//-----------------------------------------------------------------------
407void  OcclusionQueriesQueryManager::CollectPatchVisibility(
408                                                        GtpVisibility::QueryList::iterator &visQueryIt,
409                                                        GtpVisibility::QueryList::iterator &projQueryIt,
410                                                        GtpVisibility::PatchVector *patchList,
411                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
412                                                        bool relativeVisibility)
413{
414        GtpVisibility::PatchVector::iterator patchIt;
415
416        //-- queries for patch
417        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
418        {
419                unsigned int visiblePixels = 0;
420                (*visQueryIt)->GetQueryResult(visiblePixels, true);
421               
422                unsigned int projectedPixels = 0;
423
424                if (relativeVisibility)
425                {
426                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
427                        ++ projQueryIt;
428                }
429
430                ++ visQueryIt;
431
432                // WARNING: approximate depth ordering during rendering =>
433                // patch maybe occluded
434                if (visiblePixels > 0)
435                {                       
436                        visiblePatches->push_back(GtpVisibility::PatchInfo(*patchIt, visiblePixels,
437                                projectedPixels));
438                }
439        }
440}
441//-----------------------------------------------------------------------
442void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
443                                        GtpVisibility::NodeInfoContainer *visibleNodes)
444{
445        sort(visibleNodes->begin(), visibleNodes->end());
446
447        GtpVisibility::NodeInfoContainer::iterator visibleNodesIt,
448                visibleNodesIt_end = visibleNodes->end();
449       
450        GtpVisibility::NodeInfo *nodeInfo = NULL;
451
452        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
453                ++visibleNodesIt)
454        {
455                if (!nodeInfo || (nodeInfo->GetSource() != (*visibleNodesIt).GetSource()))
456                {
457                        nodeInfo = &(*visibleNodesIt);
458                }
459                else // add visibility
460                {                       
461                        nodeInfo->AddVisibility(*visibleNodesIt);
462                }
463        }
464       
465        // physically delete duplicates
466        visibleNodes->erase(std::unique(visibleNodes->begin(), visibleNodes->end()),
467                                                visibleNodes->end());
468}
469//-----------------------------------------------------------------------
470void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
471                                GtpVisibility::MeshInfoContainer *visibleGeometry)
472{
473        sort(visibleGeometry->begin(), visibleGeometry->end());
474       
475        GtpVisibility::MeshInfoContainer::iterator visibleGeomIt,
476                        visibleGeomIt_end = visibleGeometry->end();
477
478        GtpVisibility::MeshInfo *geomInfo = NULL;
479
480        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
481                ++visibleGeomIt)
482        {
483                if (!geomInfo || (geomInfo->GetSource() != (*visibleGeomIt).GetSource()))
484                {
485                        geomInfo = &(*visibleGeomIt);
486                }
487                else // info points to same mesh, just add visibility
488                {
489                        geomInfo->AddVisibility(*visibleGeomIt);
490                }
491        }
492
493        // physically delete duplicates
494        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end()),
495                                                   visibleGeometry->end());
496}
497//-----------------------------------------------------------------------
498void  OcclusionQueriesQueryManager::RemoveDuplicatePatches(
499                                GtpVisibility::PatchInfoContainer *visiblePatches)
500{
501        sort(visiblePatches->begin(), visiblePatches->end());
502       
503        GtpVisibility::PatchInfoContainer::iterator visiblePatchIt,
504                        visiblePatchIt_end = visiblePatches->end();
505
506        GtpVisibility::PatchInfo *patchInfo = NULL;
507
508        for (visiblePatchIt = visiblePatches->begin(); visiblePatchIt != visiblePatchIt_end;
509                ++visiblePatchIt)
510        {
511                if (!patchInfo || (patchInfo->GetSource() != (*visiblePatchIt).GetSource()))
512                {
513                        patchInfo = &(*visiblePatchIt);
514                }
515                else // info points to same mesh, just add visibility
516                {
517                        patchInfo->AddVisibility(*visiblePatchIt);
518                }
519        }
520
521        // physically delete duplicates
522        visiblePatches->erase(std::unique(visiblePatches->begin(), visiblePatches->end()),
523                                                  visiblePatches->end());
524}
525//-----------------------------------------------------------------------
526void OcclusionQueriesQueryManager::GetNodePatchList(GtpVisibility::HierarchyNode *node,
527                                                                                                        GtpVisibility::PatchVector *patchList)
528{
529        GtpVisibility::GeometryVector geomList;
530        mHierarchyInterface->GetNodeGeometryList(node, &geomList, false);
531
532        // geometry list iterator
533        GtpVisibility::GeometryVector::iterator geomIt, geomIt_end = geomList.end();
534
535        for (geomIt = geomList.begin(); geomIt != geomIt_end; ++geomIt)
536        {
537                for     (int i = 0; i < (int)(*geomIt)->getNumSubEntities(); ++i)
538                {
539                        patchList->push_back((*geomIt)->getSubEntity(i));
540                }
541        }
542}
543
544} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.