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

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