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

Revision 2557, 14.2 KB checked in by mattausch, 17 years ago (diff)

started with new hybrid visibility method

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