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

Revision 2280, 17.3 KB checked in by mattausch, 17 years ago (diff)

removed dependency on ogre in gtpvisibility

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