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

Revision 175, 16.9 KB checked in by mattausch, 19 years ago (diff)

added trees

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