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

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