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

Revision 2557, 14.2 KB checked in by mattausch, 17 years ago (diff)

started with new hybrid visibility method

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