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

Revision 2255, 17.9 KB checked in by mattausch, 18 years ago (diff)

improved scenemanager config

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