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

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