source: trunk/VUT/Ogre/src/OgreOcclusionQueriesQueryManager.cpp @ 316

Revision 316, 16.3 KB checked in by mattausch, 19 years ago (diff)

queries are realized as templates

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