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

Revision 2513, 14.3 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        if (1)
220        {       
221                // collect occlusion queries for hierarchy nodes
222                CollectNodeVisibility(visQueryIt,
223                        projQueryIt,
224                        &nodeList,
225                        visibleNodes,
226                        relativeVisibility);
227        }
228
229        if (1)
230        {       
231                CollectGeometryVisibility(visQueryIt,
232                        projQueryIt,
233                        &geometryList,
234                        visibleGeometry,
235                        relativeVisibility);
236        }
237
238        if (1)
239        {
240                // collect occlusion queries for patches
241                CollectPatchVisibility(visQueryIt,
242                        projQueryIt,
243                        &patchList,
244                        visiblePatches,
245                        relativeVisibility);
246        }
247
248
249        ////////////
250        //-- reset state
251
252        enableDepthWrite = true;
253        // this option must be provided by the scene manager
254        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
255        // reset old overlay status
256        mViewport->setOverlaysEnabled(overlayEnabled);
257
258        mWasInitialised = false;
259}
260//-----------------------------------------------------------------------
261void OcclusionQueriesQueryManager::ComputeFromPointVisibility(
262                                                                const Vector3 &point,
263                                                                NodeInfoContainer *visibleNodes,
264                                                                MeshInfoContainer *visibleGeometry,
265                                                                PatchInfoContainer *visiblePatches,
266                                                                const bool relativeVisibility,
267                                                                const bool approximateVisibility)
268{
269        PlatformQueryManager::ComputeFromPointVisibility(point,
270                                                                                                         visibleNodes,
271                                                                                                         visibleGeometry,
272                                                                                                         visiblePatches,
273                                                                                                         relativeVisibility,
274                                                                                                         approximateVisibility);
275
276        // adds up their visibility and removes duplicates
277        // (duplicates occur if an object is on the edge of the viewport)
278        RemoveDuplicateNodes(visibleNodes);
279        RemoveDuplicateGeometry(visibleGeometry);
280        RemoveDuplicatePatches(visiblePatches);
281}
282//------------------------------------------------------------------------
283void OcclusionQueriesQueryManager::CollectNodeVisibility(
284                                                GtpVisibility::QueryList::iterator &visQueryIt,
285                                                GtpVisibility::QueryList::iterator &projQueryIt,
286                                                GtpVisibility::NodeVector *nodeList, 
287                                                NodeInfoContainer *visibleNodes,
288                                                bool relativeVisibility)
289{
290        GtpVisibility::NodeVector::iterator nodeIt;
291
292        //-- queries for nodes
293        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++ nodeIt)
294        {
295                if (!(*visQueryIt))
296                {
297                        ++ visQueryIt;
298                        if (relativeVisibility)
299                                ++ projQueryIt;
300                        continue;
301                }
302
303                unsigned int visiblePixels = 0;
304                (*visQueryIt)->GetQueryResult(visiblePixels, true);
305       
306                unsigned int projectedPixels = 0;
307
308                if (relativeVisibility)
309                {
310                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
311                        ++ projQueryIt;
312                }
313
314                ++ visQueryIt;
315               
316                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
317                if (visiblePixels > 0)
318                {
319                        visibleNodes->push_back(NodeInfo(*nodeIt, visiblePixels, projectedPixels));
320                }
321        }
322}
323//-----------------------------------------------------------------------
324void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
325                                                        GtpVisibility::QueryList::iterator &visQueryIt,
326                                                        GtpVisibility::QueryList::iterator &projQueryIt,
327                                                        GeometryVector *geometryList,
328                                                        MeshInfoContainer *visibleGeometry,
329                                                        bool relativeVisibility)
330{
331        GeometryVector::iterator geometryIt;
332
333        //-- queries for geometry
334        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
335        {
336                unsigned int visiblePixels = 0;
337                (*visQueryIt)->GetQueryResult(visiblePixels, true);
338               
339                unsigned int projectedPixels = 0;
340
341                if (relativeVisibility)
342                {
343                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
344                        ++ projQueryIt;
345                }
346
347                ++ visQueryIt;
348
349                // WARNING: approximate depth ordering during rendering =>
350                // visibility approximate
351                if (visiblePixels > 0)
352                {                       
353                        visibleGeometry->push_back(MeshInfo(*geometryIt, visiblePixels, projectedPixels));
354                }
355        }
356}
357//-----------------------------------------------------------------------
358void  OcclusionQueriesQueryManager::CollectPatchVisibility(
359                                                        GtpVisibility::QueryList::iterator &visQueryIt,
360                                                        GtpVisibility::QueryList::iterator &projQueryIt,
361                                                        PatchVector *patchList,
362                                                        PatchInfoContainer *visiblePatches,
363                                                        bool relativeVisibility)
364{
365        PatchVector::iterator patchIt;
366
367        //-- queries for patch
368        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
369        {
370                unsigned int visiblePixels = 0;
371                (*visQueryIt)->GetQueryResult(visiblePixels, true);
372               
373                unsigned int projectedPixels = 0;
374
375                if (relativeVisibility)
376                {
377                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
378                        ++ projQueryIt;
379                }
380
381                ++ visQueryIt;
382
383                // WARNING: approximate depth ordering during rendering =>
384                // patch maybe occluded
385                if (visiblePixels > 0)
386                {                       
387                        visiblePatches->push_back(
388                                PatchInfo(*patchIt, visiblePixels, projectedPixels));
389                }
390        }
391}
392//-----------------------------------------------------------------------
393void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
394                                        NodeInfoContainer *visibleNodes)
395{
396        sort(visibleNodes->begin(), visibleNodes->end());
397
398        NodeInfoContainer::iterator visibleNodesIt,
399                visibleNodesIt_end = visibleNodes->end();
400       
401        NodeInfo *nodeInfo = NULL;
402
403        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
404                ++visibleNodesIt)
405        {
406                if (!nodeInfo || (nodeInfo->GetSource() != (*visibleNodesIt).GetSource()))
407                {
408                        nodeInfo = &(*visibleNodesIt);
409                }
410                else // add visibility
411                {                       
412                        nodeInfo->AddVisibility(*visibleNodesIt);
413                }
414        }
415       
416        // physically delete duplicates
417        visibleNodes->erase(std::unique(visibleNodes->begin(), visibleNodes->end()),
418                                                visibleNodes->end());
419}
420//-----------------------------------------------------------------------
421void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
422                                MeshInfoContainer *visibleGeometry)
423{
424        sort(visibleGeometry->begin(), visibleGeometry->end());
425       
426        MeshInfoContainer::iterator visibleGeomIt,
427                        visibleGeomIt_end = visibleGeometry->end();
428
429        MeshInfo *geomInfo = NULL;
430
431        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
432                ++visibleGeomIt)
433        {
434                if (!geomInfo || (geomInfo->GetSource() != (*visibleGeomIt).GetSource()))
435                {
436                        geomInfo = &(*visibleGeomIt);
437                }
438                else // info points to same mesh, just add visibility
439                {
440                        geomInfo->AddVisibility(*visibleGeomIt);
441                }
442        }
443
444        // physically delete duplicates
445        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end()),
446                                                   visibleGeometry->end());
447}
448//-----------------------------------------------------------------------
449void  OcclusionQueriesQueryManager::RemoveDuplicatePatches(
450                                PatchInfoContainer *visiblePatches)
451{
452        sort(visiblePatches->begin(), visiblePatches->end());
453       
454        PatchInfoContainer::iterator visiblePatchIt,
455                        visiblePatchIt_end = visiblePatches->end();
456
457        PatchInfo *patchInfo = NULL;
458
459        for (visiblePatchIt = visiblePatches->begin(); visiblePatchIt != visiblePatchIt_end;
460                ++visiblePatchIt)
461        {
462                if (!patchInfo || (patchInfo->GetSource() != (*visiblePatchIt).GetSource()))
463                {
464                        patchInfo = &(*visiblePatchIt);
465                }
466                else // info points to same mesh, just add visibility
467                {
468                        patchInfo->AddVisibility(*visiblePatchIt);
469                }
470        }
471
472        // physically delete duplicates
473        visiblePatches->erase(std::unique(visiblePatches->begin(), visiblePatches->end()),
474                                                  visiblePatches->end());
475}
476//-----------------------------------------------------------------------
477void OcclusionQueriesQueryManager::GetNodePatchList(GtpVisibility::HierarchyNode *node,
478                                                                                                        PatchVector *patchList)
479{
480        GeometryVector geomList;
481        mHierarchyInterface->GetNodeGeometryList(node, &geomList, false);
482
483        // geometry list iterator
484        GeometryVector::iterator geomIt, geomIt_end = geomList.end();
485
486        for (geomIt = geomList.begin(); geomIt != geomIt_end; ++geomIt)
487        {
488                for     (int i = 0; i < (int)(*geomIt)->getNumSubEntities(); ++i)
489                {
490                        patchList->push_back((*geomIt)->getSubEntity(i));
491                }
492        }
493}
494
495} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.