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

Revision 1602, 15.5 KB checked in by mattausch, 18 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
8namespace Ogre {
9
10//-----------------------------------------------------------------------
11OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
12                                                        GtpVisibility::HierarchyInterface *hierarchyInterface,
13                                                        Viewport *vp,
14                                                        int queryModes,
15                                                        int itemBufferMode):
16PlatformQueryManager(hierarchyInterface, vp, queryModes),
17mItemBufferMode(itemBufferMode)
18{
19}
20//-----------------------------------------------------------------------
21void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
22                                                                                                                   GtpVisibility::NodeInfoContainer *visibleNodes,
23                                                                                                                   GtpVisibility::MeshInfoContainer *visibleGeometry,
24                                                                                                                   GtpVisibility::PatchInfoContainer *visiblePatches,
25                                                                                                                   bool relativeVisibility)
26{
27        // we need access to the scene manager and the rendersystem
28        PlatformHierarchyInterface *pfHierarchyInterface =
29                //dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
30                static_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
31
32        // disable overlays, reset them later
33        bool overlayEnabled = mViewport->getOverlaysEnabled();
34
35        ///////////
36        //-- render scene with item buffer (i.e., objects with their id as color codes)
37//mItemBufferMode = 0;
38        if ((mItemBufferMode && mQueryModes) != 0)
39        {
40                int savedQueryModes = mQueryModes;
41                mQueryModes = mItemBufferMode;
42               
43                PlatformQueryManager::ComputeCameraVisibility(camera, visibleNodes,
44                            visibleGeometry, visiblePatches, relativeVisibility);
45               
46                // overlays cause false visibility
47                mViewport->setOverlaysEnabled(false);
48                mQueryModes = savedQueryModes;
49        }
50        else
51        {
52                // const_cast allowed because camera is not changed in renderScene
53                Camera *pCam = const_cast<Camera *>(&camera);
54                mViewport->setOverlaysEnabled(false);
55
56                //-- Render scene to get conservative visibility and fill depth buffer
57                pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
58        }
59
60       
61        /*      Two query lists for projected pixels and for visibile pixels:
62                We test queries after a rendering pass
63                to get exact visibility with regard to the current camera.
64                We issue all queries at once to avoid starvation & stalls.
65        */
66        GtpVisibility::QueryList queryList[2];
67       
68        // rendered visibile hierarchy nodes from previous rendering
69        GtpVisibility::NodeVector *visNodes = mHierarchyInterface->GetVisibleNodes();
70        GtpVisibility::NodeVector::iterator visNodesIt, visNodesIt_end = visNodes->end();
71
72    GtpVisibility::NodeVector nodeList;
73
74        if (mQueryModes & NODE_VISIBILITY)
75        {
76                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)
77                {
78                        nodeList.push_back((*visNodesIt));
79                }
80        }
81
82        GtpVisibility::NodeVector::iterator nodeIt, nodeIt_end = nodeList.end();
83
84        // vector for storing entities of meshes
85        GtpVisibility::GeometryVector geometryList;
86       
87        // store geometry of the hierarchy nodes in a geometry list
88        if (mQueryModes & GEOMETRY_VISIBILITY)
89        {       
90                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
91                {
92                        mHierarchyInterface->GetNodeGeometryList(*visNodesIt, &geometryList, false);
93                }
94        }
95       
96        // geometry list iterator
97        GtpVisibility::GeometryVector::iterator geometryIt, geometryIt_end = geometryList.end();
98
99        // vector for storing subentities of meshes
100        GtpVisibility::PatchVector patchList;
101
102        // store patchges of the geometries in a patch list
103        if (mQueryModes & PATCH_VISIBILITY)
104        {
105                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
106                {
107                        GetNodePatchList(*visNodesIt, &patchList);
108                }
109        }
110
111        GtpVisibility::PatchVector::iterator patchIt, patchIt_end = patchList.end();
112
113        // to obtain the correct number of projected pixels, depth write must be disabled
114        bool enableDepthWrite = false;
115        // this option must be provided by the scene manager
116        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
117
118
119        /* relative visiblity:
120           1) get visible pixels count of objects
121           2) clear frame buffer
122           3) get projected visible pixels count:
123              test all objects again without depth write (set as option in scene manager)
124           4) calculate ratio between visible vs. projected pixels
125        */
126               
127        // for relative visibility we need 2 rendering passes
128        int n = relativeVisibility ? 2 : 1;
129        if (mItemBufferMode > 0)
130                LogManager::getSingleton().logMessage("item buffer");
131
132        for (int i = 0; i < n; ++i)
133        {
134                //-- queries for hierarchy nodes
135                for (nodeIt = nodeList.begin(); nodeIt != nodeIt_end; ++nodeIt)         
136                {
137                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
138                        queryList[i].push_back(mHierarchyInterface->IssueNodeOcclusionQuery(*nodeIt, false));
139                }
140
141                //-- queries for geometry: if item buffer, capture only projected visibility
142                if ((mItemBufferMode != GEOMETRY_VISIBILITY) || (i == 1))
143                {                       
144                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
145                        {
146                                queryList[i].push_back(pfHierarchyInterface->IssueMeshOcclusionQuery(*geometryIt));
147                        }
148                }
149               
150                //-- queries for patches: if item buffer, capture only projected visibility
151                if ((mItemBufferMode != PATCH_VISIBILITY) || (i == 1))
152                {
153                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
154                        {
155                                queryList[i].push_back(pfHierarchyInterface->IssuePatchOcclusionQuery(*patchIt));
156                        }
157                }
158
159                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
160        }
161
162       
163        //-- collect results
164        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
165        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
166       
167        // collect occlusion queries for hierarchy nodes
168        CollectNodeVisibility(visQueryIt, projQueryIt, &nodeList, visibleNodes, relativeVisibility);
169
170
171        // collect occlusion queries for geometry
172        if ((mItemBufferMode == GEOMETRY_VISIBILITY) && relativeVisibility)
173        {
174                // if visibility was established using the item buffer,
175                // the array is organized different (e.g., ordered by id, all possible objects)
176                CollectRelativeGeometryVisibilityForItemBuffer(projQueryIt, &geometryList, visibleGeometry);
177        }
178        else if (mItemBufferMode != GEOMETRY_VISIBILITY)
179        {
180                CollectGeometryVisibility(visQueryIt, projQueryIt, &geometryList, visibleGeometry,
181                                                                  relativeVisibility);
182        }
183
184
185        // collect occlusion queries for patches
186        if ((mItemBufferMode == PATCH_VISIBILITY) && relativeVisibility)
187        {
188                CollectRelativePatchVisibilityForItemBuffer(projQueryIt, &patchList, visiblePatches);
189        }
190        else if (mItemBufferMode != PATCH_VISIBILITY)
191        {
192                CollectPatchVisibility(visQueryIt, projQueryIt, &patchList, visiblePatches, relativeVisibility);
193        }       
194
195               
196        //-- reset options
197        enableDepthWrite = true;
198        // this option must be provided by the scene manager
199        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
200        // reset old overlay status
201        mViewport->setOverlaysEnabled(overlayEnabled);
202
203        mWasInitialised = false;
204}
205//-----------------------------------------------------------------------
206void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
207                               GtpVisibility::NodeInfoContainer *visibleNodes,
208                               GtpVisibility::MeshInfoContainer *visibleGeometry,
209                                   GtpVisibility::PatchInfoContainer *visiblePatches,
210                               bool relativeVisibility)
211{
212        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes,
213                visibleGeometry, visiblePatches, relativeVisibility);
214
215        // adds up their visibility and removes duplicates
216        // (duplicates occur if an object is on the edge of the viewport)
217        RemoveDuplicateNodes(visibleNodes);
218       
219        if (mItemBufferMode != GEOMETRY_VISIBILITY)
220        {
221                RemoveDuplicateGeometry(visibleGeometry);
222        }
223       
224        if (mItemBufferMode != PATCH_VISIBILITY)
225        {
226                RemoveDuplicatePatches(visiblePatches);
227        }
228}
229//------------------------------------------------------------------------
230void  OcclusionQueriesQueryManager::CollectNodeVisibility(
231                                                GtpVisibility::QueryList::iterator &visQueryIt,
232                                                GtpVisibility::QueryList::iterator &projQueryIt,
233                                                GtpVisibility::NodeVector *nodeList, 
234                                                GtpVisibility::NodeInfoContainer *visibleNodes,
235                                                bool relativeVisibility)
236{
237        GtpVisibility::NodeVector::iterator nodeIt;
238
239        //-- queries for nodes
240        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++nodeIt)
241        {
242                unsigned int visiblePixels = 0;
243                (*visQueryIt)->GetQueryResult(visiblePixels, true);
244       
245                unsigned int projectedPixels = 0;
246
247                if (relativeVisibility)
248                {
249                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
250               
251                        ++projQueryIt;
252                }
253
254                ++visQueryIt;
255               
256                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
257                if (visiblePixels > 0)
258                {
259                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels,
260                                projectedPixels));
261                }
262        }
263}
264//-----------------------------------------------------------------------
265void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
266                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
267                                                                        GtpVisibility::GeometryVector *geometryList,
268                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry)
269{
270        GtpVisibility::GeometryVector::iterator geometryIt;
271
272        //-- queries for geometry
273        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
274        {
275                unsigned int projectedPixels = 0;
276
277                (*projQueryIt)->GetQueryResult(projectedPixels, true);
278
279                ++projQueryIt;
280                int id = (*geometryIt)->getSubEntity(0)->getId();
281
282                if ((id > 0) && (id < (int)visibleGeometry->size()))
283                {
284                        (*visibleGeometry)[id].AddVisibility(0, projectedPixels);
285                }
286        }
287}
288//-----------------------------------------------------------------------
289void OcclusionQueriesQueryManager::CollectRelativePatchVisibilityForItemBuffer(
290                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
291                                                                        GtpVisibility::PatchVector *patchList,
292                                                                        GtpVisibility::PatchInfoContainer *visiblePatches)
293{
294        GtpVisibility::PatchVector::iterator patchIt;
295
296        //-- queries for geometry
297        for (patchIt = patchList->begin(); patchIt != patchList->end(); ++ patchIt)
298        {
299                unsigned int projectedPixels = 0;
300
301                (*projQueryIt)->GetQueryResult(projectedPixels, true);
302
303                ++projQueryIt;
304                int id = (*patchIt)->getId();
305
306                if ((id > 0) && (id < (int)visiblePatches->size()))
307                {
308                        (*visiblePatches)[id].AddVisibility(0, projectedPixels);
309                }
310        }
311}
312//-----------------------------------------------------------------------
313void  OcclusionQueriesQueryManager::CollectGeometryVisibility(
314                                                        GtpVisibility::QueryList::iterator &visQueryIt,
315                                                        GtpVisibility::QueryList::iterator &projQueryIt,
316                                                        GtpVisibility::GeometryVector *geometryList,
317                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
318                                                        bool relativeVisibility)
319{
320        GtpVisibility::GeometryVector::iterator geometryIt;
321
322        //-- queries for geometry
323        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
324        {
325                unsigned int visiblePixels = 0;
326                (*visQueryIt)->GetQueryResult(visiblePixels, true);
327               
328                unsigned int projectedPixels = 0;
329
330                if (relativeVisibility)
331                {
332                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
333                        ++ projQueryIt;
334                }
335
336                ++ visQueryIt;
337
338                // WARNING: approximate depth ordering during rendering =>
339                // geometry maybe occluded
340                if (visiblePixels > 0)
341                {                       
342                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
343                                projectedPixels));
344                }
345        }
346}
347//-----------------------------------------------------------------------
348void  OcclusionQueriesQueryManager::CollectPatchVisibility(
349                                                        GtpVisibility::QueryList::iterator &visQueryIt,
350                                                        GtpVisibility::QueryList::iterator &projQueryIt,
351                                                        GtpVisibility::PatchVector *patchList,
352                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
353                                                        bool relativeVisibility)
354{
355        GtpVisibility::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(GtpVisibility::PatchInfo(*patchIt, visiblePixels,
378                                projectedPixels));
379                }
380        }
381}
382//-----------------------------------------------------------------------
383void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
384                                        GtpVisibility::NodeInfoContainer *visibleNodes)
385{
386        stable_sort(visibleNodes->begin(), visibleNodes->end()/*, nodeinfo_lt*/);
387
388        GtpVisibility::NodeInfoContainer::iterator visibleNodesIt,
389                visibleNodesIt_end = visibleNodes->end();
390       
391        GtpVisibility::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                                GtpVisibility::MeshInfoContainer *visibleGeometry)
413{
414        stable_sort(visibleGeometry->begin(), visibleGeometry->end());
415       
416        GtpVisibility::MeshInfoContainer::iterator visibleGeomIt,
417                        visibleGeomIt_end = visibleGeometry->end();
418
419        GtpVisibility::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                                GtpVisibility::PatchInfoContainer *visiblePatches)
441{
442        stable_sort(visiblePatches->begin(), visiblePatches->end());
443       
444        GtpVisibility::PatchInfoContainer::iterator visiblePatchIt,
445                        visiblePatchIt_end = visiblePatches->end();
446
447        GtpVisibility::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                                                                                                        GtpVisibility::PatchVector *patchList)
469{
470        GtpVisibility::GeometryVector geomList;
471        mHierarchyInterface->GetNodeGeometryList(node, &geomList, false);
472
473        // geometry list iterator
474        GtpVisibility::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.