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

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

implemented function for exact visibility queries

RevLine 
[154]1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
[171]5#include <OgreSubEntity.h>
[925]6#include "OgrePlatformHierarchyInterface.h"
[2171]7#include "OgreOcclusionCullingSceneManager.h"
8#include "VisibilityEnvironment.h"
[154]9
[2171]10
11
[154]12namespace Ogre {
[171]13
14//-----------------------------------------------------------------------
15OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
[925]16                                                        GtpVisibility::HierarchyInterface *hierarchyInterface,
[171]17                                                        Viewport *vp,
[174]18                                                        int queryModes,
19                                                        int itemBufferMode):
20PlatformQueryManager(hierarchyInterface, vp, queryModes),
21mItemBufferMode(itemBufferMode)
[154]22{
23}
24//-----------------------------------------------------------------------
[2171]25void OcclusionQueriesQueryManager::ComputeCameraVisibility(
26                                                                                        const Camera &camera,
27                                                                                        GtpVisibility::NodeInfoContainer *visibleNodes,
28                                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
29                                                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
30                                                                                        bool relativeVisibility)
[154]31{
[174]32        // we need access to the scene manager and the rendersystem
[154]33        PlatformHierarchyInterface *pfHierarchyInterface =
[726]34                static_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
[154]35
36        // disable overlays, reset them later
37        bool overlayEnabled = mViewport->getOverlaysEnabled();
[2171]38
[1602]39        ///////////
[171]40        //-- render scene with item buffer (i.e., objects with their id as color codes)
[2171]41
42        //mItemBufferMode = 0;
43        if (0 &&
44                (mItemBufferMode && mQueryModes) != 0)
[171]45        {
[174]46                int savedQueryModes = mQueryModes;
47                mQueryModes = mItemBufferMode;
48               
[2171]49                PlatformQueryManager::ComputeCameraVisibility(camera,
50                                                                                                          visibleNodes,
51                                                                                                          visibleGeometry,
52                                                                                                          visiblePatches,
53                                                                                                          relativeVisibility);
[174]54               
55                // overlays cause false visibility
[171]56                mViewport->setOverlaysEnabled(false);
[174]57                mQueryModes = savedQueryModes;
[171]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
[2171]65                ////////////////////////
[171]66                //-- Render scene to get conservative visibility and fill depth buffer
[2171]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);
[171]93        }
94
95       
[2171]96        /*      Two query lists for projected pixels and for visibile pixels:
[154]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       
[174]103        // rendered visibile hierarchy nodes from previous rendering
[370]104        GtpVisibility::NodeVector *visNodes = mHierarchyInterface->GetVisibleNodes();
105        GtpVisibility::NodeVector::iterator visNodesIt, visNodesIt_end = visNodes->end();
[171]106
[370]107    GtpVisibility::NodeVector nodeList;
[174]108
[175]109        if (mQueryModes & NODE_VISIBILITY)
[174]110        {
111                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)
112                {
113                        nodeList.push_back((*visNodesIt));
114                }
115        }
116
[370]117        GtpVisibility::NodeVector::iterator nodeIt, nodeIt_end = nodeList.end();
[174]118
[154]119        // vector for storing entities of meshes
[370]120        GtpVisibility::GeometryVector geometryList;
[154]121       
[174]122        // store geometry of the hierarchy nodes in a geometry list
[175]123        if (mQueryModes & GEOMETRY_VISIBILITY)
[174]124        {       
[2171]125                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++ visNodesIt)       
[174]126                {
127                        mHierarchyInterface->GetNodeGeometryList(*visNodesIt, &geometryList, false);
128                }
[171]129        }
[174]130       
[171]131        // geometry list iterator
[370]132        GtpVisibility::GeometryVector::iterator geometryIt, geometryIt_end = geometryList.end();
[171]133
[173]134        // vector for storing subentities of meshes
[370]135        GtpVisibility::PatchVector patchList;
[174]136
137        // store patchges of the geometries in a patch list
[175]138        if (mQueryModes & PATCH_VISIBILITY)
[174]139        {
140                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
141                {
142                        GetNodePatchList(*visNodesIt, &patchList);
143                }
144        }
145
[370]146        GtpVisibility::PatchVector::iterator patchIt, patchIt_end = patchList.end();
[171]147
[154]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
[171]153
[154]154        /* relative visiblity:
[171]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
[154]160        */
[171]161               
[154]162        // for relative visibility we need 2 rendering passes
163        int n = relativeVisibility ? 2 : 1;
[175]164        if (mItemBufferMode > 0)
[2171]165                LogManager::getSingleton().logMessage("using item buffer");
[175]166
[2171]167        for (int i = 0; i < n; ++ i)
[154]168        {
169                //-- queries for hierarchy nodes
[174]170                for (nodeIt = nodeList.begin(); nodeIt != nodeIt_end; ++nodeIt)         
[154]171                {
172                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
[175]173                        queryList[i].push_back(mHierarchyInterface->IssueNodeOcclusionQuery(*nodeIt, false));
[154]174                }
175
[2171]176                ////////////////////////////
[171]177                //-- queries for geometry: if item buffer, capture only projected visibility
[2171]178
[174]179                if ((mItemBufferMode != GEOMETRY_VISIBILITY) || (i == 1))
[175]180                {                       
[2171]181                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++ geometryIt)
[174]182                        {
[175]183                                queryList[i].push_back(pfHierarchyInterface->IssueMeshOcclusionQuery(*geometryIt));
[174]184                        }
[173]185                }
186               
[2171]187                ////////////////////////
[173]188                //-- queries for patches: if item buffer, capture only projected visibility
[2171]189
[174]190                if ((mItemBufferMode != PATCH_VISIBILITY) || (i == 1))
[154]191                {
[173]192                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
[171]193                        {
[175]194                                queryList[i].push_back(pfHierarchyInterface->IssuePatchOcclusionQuery(*patchIt));
[171]195                        }
[154]196                }
197
198                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
199        }
200
[2171]201        ///////////////
[171]202        //-- collect results
[2171]203
[171]204        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
205        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
206       
[174]207        // collect occlusion queries for hierarchy nodes
[2171]208        CollectNodeVisibility(visQueryIt,
209                                                  projQueryIt,
210                                                  &nodeList,
211                                                  visibleNodes,
212                                                  relativeVisibility);
[171]213
[174]214
215        // collect occlusion queries for geometry
216        if ((mItemBufferMode == GEOMETRY_VISIBILITY) && relativeVisibility)
[171]217        {
[174]218                // if visibility was established using the item buffer,
219                // the array is organized different (e.g., ordered by id, all possible objects)
[2171]220                CollectRelativeGeometryVisibilityForItemBuffer(projQueryIt,
221                                                                                                           &geometryList,
222                                                                                                           visibleGeometry);
[174]223        }
[175]224        else if (mItemBufferMode != GEOMETRY_VISIBILITY)
[171]225        {
[2171]226                CollectGeometryVisibility(visQueryIt,
227                                                                  projQueryIt,
228                                                                  &geometryList,
229                                                                  visibleGeometry,
[174]230                                                                  relativeVisibility);
231        }
232
233
234        // collect occlusion queries for patches
235        if ((mItemBufferMode == PATCH_VISIBILITY) && relativeVisibility)
236        {
[2171]237                CollectRelativePatchVisibilityForItemBuffer(projQueryIt,
238                                                                                                        &patchList,
239                                                                                                        visiblePatches);
[174]240        }
[175]241        else if (mItemBufferMode != PATCH_VISIBILITY)
[174]242        {
[2171]243                CollectPatchVisibility(visQueryIt,
244                                                           projQueryIt,
245                                                           &patchList,
246                                                           visiblePatches,
247                                                           relativeVisibility);
[173]248        }       
[174]249
[2171]250        ////////////
251        //-- reset state
252
[154]253        enableDepthWrite = true;
254        // this option must be provided by the scene manager
255        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
256        // reset old overlay status
[2066]257        mViewport->setOverlaysEnabled(overlayEnabled);
258
259        mWasInitialised = false;
[171]260}
261//-----------------------------------------------------------------------
[2171]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);
[154]274
[175]275        // adds up their visibility and removes duplicates
276        // (duplicates occur if an object is on the edge of the viewport)
[171]277        RemoveDuplicateNodes(visibleNodes);
[2171]278
[174]279        if (mItemBufferMode != GEOMETRY_VISIBILITY)
[154]280        {
[171]281                RemoveDuplicateGeometry(visibleGeometry);
282        }
[2171]283
[174]284        if (mItemBufferMode != PATCH_VISIBILITY)
285        {
286                RemoveDuplicatePatches(visiblePatches);
287        }
[171]288}
[645]289//------------------------------------------------------------------------
[2171]290void OcclusionQueriesQueryManager::CollectNodeVisibility(
[171]291                                                GtpVisibility::QueryList::iterator &visQueryIt,
292                                                GtpVisibility::QueryList::iterator &projQueryIt,
[370]293                                                GtpVisibility::NodeVector *nodeList, 
[316]294                                                GtpVisibility::NodeInfoContainer *visibleNodes,
[171]295                                                bool relativeVisibility)
296{
[370]297        GtpVisibility::NodeVector::iterator nodeIt;
[171]298
299        //-- queries for nodes
[2171]300        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++ nodeIt)
[171]301        {
[154]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);
[2171]310                        ++ projQueryIt;
[154]311                }
312
[2171]313                ++ visQueryIt;
[154]314               
315                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
316                if (visiblePixels > 0)
317                {
[2171]318                        visibleNodes->push_back(
319                                GtpVisibility::NodeInfo(*nodeIt, visiblePixels, projectedPixels));
[154]320                }
[2066]321        }
322}
[171]323//-----------------------------------------------------------------------
324void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
[2066]325                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
326                                                                        GtpVisibility::GeometryVector *geometryList,
327                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry)
328{
329        GtpVisibility::GeometryVector::iterator geometryIt;
330
[171]331        //-- queries for geometry
332        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
[154]333        {
[171]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                }
[2066]345        }
346}
[171]347//-----------------------------------------------------------------------
348void OcclusionQueriesQueryManager::CollectRelativePatchVisibilityForItemBuffer(
[2066]349                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
350                                                                        GtpVisibility::PatchVector *patchList,
351                                                                        GtpVisibility::PatchInfoContainer *visiblePatches)
352{
353        GtpVisibility::PatchVector::iterator patchIt;
354
[171]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                }
[2066]369        }
370}
[171]371//-----------------------------------------------------------------------
372void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
373                                                        GtpVisibility::QueryList::iterator &visQueryIt,
374                                                        GtpVisibility::QueryList::iterator &projQueryIt,
[370]375                                                        GtpVisibility::GeometryVector *geometryList,
[316]376                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
[171]377                                                        bool relativeVisibility)
[2066]378{
379        GtpVisibility::GeometryVector::iterator geometryIt;
380
[171]381        //-- queries for geometry
382        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
383        {
[154]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);
[171]392                        ++ projQueryIt;
[154]393                }
394
[171]395                ++ visQueryIt;
[154]396
[155]397                // WARNING: approximate depth ordering during rendering =>
[154]398                // geometry maybe occluded
399                if (visiblePixels > 0)
[2066]400                {                       
[154]401                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
402                                projectedPixels));
403                }
[2066]404        }
[154]405}
406//-----------------------------------------------------------------------
[171]407void  OcclusionQueriesQueryManager::CollectPatchVisibility(
408                                                        GtpVisibility::QueryList::iterator &visQueryIt,
409                                                        GtpVisibility::QueryList::iterator &projQueryIt,
[370]410                                                        GtpVisibility::PatchVector *patchList,
[316]411                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
[171]412                                                        bool relativeVisibility)
[2066]413{
414        GtpVisibility::PatchVector::iterator patchIt;
415
[171]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)
[2066]435                {                       
[171]436                        visiblePatches->push_back(GtpVisibility::PatchInfo(*patchIt, visiblePixels,
437                                projectedPixels));
438                }
[2066]439        }
[154]440}
441//-----------------------------------------------------------------------
[171]442void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
[316]443                                        GtpVisibility::NodeInfoContainer *visibleNodes)
[154]444{
[2171]445        sort(visibleNodes->begin(), visibleNodes->end());
[316]446
447        GtpVisibility::NodeInfoContainer::iterator visibleNodesIt,
[154]448                visibleNodesIt_end = visibleNodes->end();
449       
450        GtpVisibility::NodeInfo *nodeInfo = NULL;
451
452        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
453                ++visibleNodesIt)
454        {
[316]455                if (!nodeInfo || (nodeInfo->GetSource() != (*visibleNodesIt).GetSource()))
[154]456                {
457                        nodeInfo = &(*visibleNodesIt);
458                }
459                else // add visibility
460                {                       
461                        nodeInfo->AddVisibility(*visibleNodesIt);
462                }
463        }
464       
465        // physically delete duplicates
[318]466        visibleNodes->erase(std::unique(visibleNodes->begin(), visibleNodes->end()),
[316]467                                                visibleNodes->end());
[171]468}
469//-----------------------------------------------------------------------
470void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
[316]471                                GtpVisibility::MeshInfoContainer *visibleGeometry)
[171]472{
[2171]473        sort(visibleGeometry->begin(), visibleGeometry->end());
[171]474       
[316]475        GtpVisibility::MeshInfoContainer::iterator visibleGeomIt,
[171]476                        visibleGeomIt_end = visibleGeometry->end();
[154]477
478        GtpVisibility::MeshInfo *geomInfo = NULL;
479
480        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
481                ++visibleGeomIt)
482        {
[316]483                if (!geomInfo || (geomInfo->GetSource() != (*visibleGeomIt).GetSource()))
[154]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
[318]494        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end()),
[316]495                                                   visibleGeometry->end());
[154]496}
[173]497//-----------------------------------------------------------------------
498void  OcclusionQueriesQueryManager::RemoveDuplicatePatches(
[316]499                                GtpVisibility::PatchInfoContainer *visiblePatches)
[173]500{
[2171]501        sort(visiblePatches->begin(), visiblePatches->end());
[173]502       
[316]503        GtpVisibility::PatchInfoContainer::iterator visiblePatchIt,
[173]504                        visiblePatchIt_end = visiblePatches->end();
[154]505
[173]506        GtpVisibility::PatchInfo *patchInfo = NULL;
507
508        for (visiblePatchIt = visiblePatches->begin(); visiblePatchIt != visiblePatchIt_end;
509                ++visiblePatchIt)
510        {
[316]511                if (!patchInfo || (patchInfo->GetSource() != (*visiblePatchIt).GetSource()))
[173]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
[318]522        visiblePatches->erase(std::unique(visiblePatches->begin(), visiblePatches->end()),
[316]523                                                  visiblePatches->end());
[2066]524}
[174]525//-----------------------------------------------------------------------
[2066]526void OcclusionQueriesQueryManager::GetNodePatchList(GtpVisibility::HierarchyNode *node,
[370]527                                                                                                        GtpVisibility::PatchVector *patchList)
[174]528{
[370]529        GtpVisibility::GeometryVector geomList;
[174]530        mHierarchyInterface->GetNodeGeometryList(node, &geomList, false);
531
532        // geometry list iterator
[370]533        GtpVisibility::GeometryVector::iterator geomIt, geomIt_end = geomList.end();
[174]534
535        for (geomIt = geomList.begin(); geomIt != geomIt_end; ++geomIt)
536        {
[2066]537                for     (int i = 0; i < (int)(*geomIt)->getNumSubEntities(); ++i)
538                {
539                        patchList->push_back((*geomIt)->getSubEntity(i));
[174]540                }
541        }
[173]542}
[174]543
[154]544} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.