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

Revision 2280, 17.3 KB checked in by mattausch, 17 years ago (diff)

removed dependency on ogre in gtpvisibility

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