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

Revision 931, 15.5 KB checked in by mattausch, 18 years ago (diff)

added bounding boxes to xml description

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