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

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