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

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

added trees

RevLine 
[154]1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
[171]5#include <OgreSubEntity.h>
[154]6
7
8namespace Ogre {
[171]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();
[154]17}
18//-----------------------------------------------------------------------
[171]19inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
20{
21        return info1.GetMesh() == info2.GetMesh();
22}
23//-----------------------------------------------------------------------
[173]24inline bool patchinfo_eq(const GtpVisibility::PatchInfo &info1, const GtpVisibility::PatchInfo &info2)
25{
26        return info1.GetPatch() == info2.GetPatch();
27}
28//-----------------------------------------------------------------------
[171]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}
[173]38//-----------------------------------------------------------------------
39inline bool patchinfo_lower(const GtpVisibility::PatchInfo &info1, const GtpVisibility::PatchInfo &info2)
40{
41        return info1.GetPatch() < info2.GetPatch();
42}
[171]43
44
45//-----------------------------------------------------------------------
46OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
47                                                        PlatformHierarchyInterface *hierarchyInterface,
48                                                        Viewport *vp,
[174]49                                                        int queryModes,
50                                                        int itemBufferMode):
51PlatformQueryManager(hierarchyInterface, vp, queryModes),
52mItemBufferMode(itemBufferMode)
[154]53{
54}
55//-----------------------------------------------------------------------
56void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
57                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
58                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
[159]59                                InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
[154]60                            bool relativeVisibility)
61{
[174]62        // we need access to the scene manager and the rendersystem
[154]63        PlatformHierarchyInterface *pfHierarchyInterface =
64                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
65
66        // disable overlays, reset them later
67        bool overlayEnabled = mViewport->getOverlaysEnabled();
68
[171]69        //-- render scene with item buffer (i.e., objects with their id as color codes)
[175]70//mItemBufferMode = 0;
[174]71        if ((mItemBufferMode && mQueryModes) != 0)
[171]72        {
[174]73                int savedQueryModes = mQueryModes;
74                mQueryModes = mItemBufferMode;
75               
[171]76                PlatformQueryManager::ComputeCameraVisibility(camera, visibleNodes,
77                            visibleGeometry, visiblePatches, relativeVisibility);
[174]78               
79                // overlays cause false visibility
[171]80                mViewport->setOverlaysEnabled(false);
[174]81                mQueryModes = savedQueryModes;
[171]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:
[154]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       
[174]101        // rendered visibile hierarchy nodes from previous rendering
102        GtpVisibility::HierarchyNodeList *visNodes = mHierarchyInterface->GetVisibleNodes();
103        GtpVisibility::HierarchyNodeList::iterator visNodesIt, visNodesIt_end = visNodes->end();
[171]104
[174]105    GtpVisibility::HierarchyNodeList nodeList;
106
[175]107        if (mQueryModes & NODE_VISIBILITY)
[174]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
[154]117        // vector for storing entities of meshes
118        GtpVisibility::GeometryList geometryList;
119       
[174]120        // store geometry of the hierarchy nodes in a geometry list
[175]121        if (mQueryModes & GEOMETRY_VISIBILITY)
[174]122        {       
123                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
124                {
125                        mHierarchyInterface->GetNodeGeometryList(*visNodesIt, &geometryList, false);
126                }
[171]127        }
[174]128       
[171]129        // geometry list iterator
130        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end = geometryList.end();
131
[173]132        // vector for storing subentities of meshes
133        GtpVisibility::PatchList patchList;
[174]134
135        // store patchges of the geometries in a patch list
[175]136        if (mQueryModes & PATCH_VISIBILITY)
[174]137        {
138                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
139                {
140                        GetNodePatchList(*visNodesIt, &patchList);
141                }
142        }
143
[173]144        GtpVisibility::PatchList::iterator patchIt, patchIt_end = patchList.end();
[171]145
[154]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
[171]151
[154]152        /* relative visiblity:
[171]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
[154]158        */
[171]159               
[154]160        // for relative visibility we need 2 rendering passes
161        int n = relativeVisibility ? 2 : 1;
[175]162        if (mItemBufferMode > 0)
163                LogManager::getSingleton().logMessage("item buffer");
164
[171]165        for (int i = 0; i < n; ++i)
[154]166        {
167                //-- queries for hierarchy nodes
[174]168                for (nodeIt = nodeList.begin(); nodeIt != nodeIt_end; ++nodeIt)         
[154]169                {
170                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
[175]171                        queryList[i].push_back(mHierarchyInterface->IssueNodeOcclusionQuery(*nodeIt, false));
[154]172                }
173
[171]174                //-- queries for geometry: if item buffer, capture only projected visibility
[174]175                if ((mItemBufferMode != GEOMETRY_VISIBILITY) || (i == 1))
[175]176                {                       
[174]177                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
178                        {
[175]179                                queryList[i].push_back(pfHierarchyInterface->IssueMeshOcclusionQuery(*geometryIt));
[174]180                        }
[173]181                }
182               
183                //-- queries for patches: if item buffer, capture only projected visibility
[174]184                if ((mItemBufferMode != PATCH_VISIBILITY) || (i == 1))
[154]185                {
[173]186                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
[171]187                        {
[175]188                                queryList[i].push_back(pfHierarchyInterface->IssuePatchOcclusionQuery(*patchIt));
[171]189                        }
[154]190                }
191
192                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
193        }
194
[171]195       
196        //-- collect results
197        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
198        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
199       
[174]200        // collect occlusion queries for hierarchy nodes
201        CollectNodeVisibility(visQueryIt, projQueryIt, &nodeList, visibleNodes, relativeVisibility);
[171]202
[174]203
204        // collect occlusion queries for geometry
205        if ((mItemBufferMode == GEOMETRY_VISIBILITY) && relativeVisibility)
[171]206        {
[174]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        }
[175]211        else if (mItemBufferMode != GEOMETRY_VISIBILITY)
[171]212        {
[174]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        }
[175]223        else if (mItemBufferMode != PATCH_VISIBILITY)
[174]224        {
[173]225                CollectPatchVisibility(visQueryIt, projQueryIt, &patchList, visiblePatches, relativeVisibility);
226        }       
[174]227
[173]228               
[171]229        //-- reset options
[154]230        enableDepthWrite = true;
231        // this option must be provided by the scene manager
232        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
233        // reset old overlay status
[171]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);
[154]247
[175]248        // adds up their visibility and removes duplicates
249        // (duplicates occur if an object is on the edge of the viewport)
[171]250        RemoveDuplicateNodes(visibleNodes);
[154]251       
[174]252        if (mItemBufferMode != GEOMETRY_VISIBILITY)
[154]253        {
[171]254                RemoveDuplicateGeometry(visibleGeometry);
255        }
[174]256       
257        if (mItemBufferMode != PATCH_VISIBILITY)
258        {
259                RemoveDuplicatePatches(visiblePatches);
260        }
[171]261}
[175]262//------j-----------------------------------------------------------------
[171]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        {
[154]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                {
[171]292                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels,
293                                projectedPixels));
[154]294                }
295        }
[171]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;
[154]304
[171]305        //-- queries for geometry
306        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
[154]307        {
[171]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        {
[154]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);
[171]366                        ++ projQueryIt;
[154]367                }
368
[171]369                ++ visQueryIt;
[154]370
[155]371                // WARNING: approximate depth ordering during rendering =>
[154]372                // geometry maybe occluded
373                if (visiblePixels > 0)
374                {                       
375                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
376                                projectedPixels));
377                }
378        }
379}
380//-----------------------------------------------------------------------
[171]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        }
[154]414}
415//-----------------------------------------------------------------------
[171]416void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
417                                        InfoContainer<GtpVisibility::NodeInfo> *visibleNodes)
[154]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());
[171]441}
442//-----------------------------------------------------------------------
443void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
444                                InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry)
445{
[154]446        sort(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_lower);
[171]447       
[154]448        InfoContainer<GtpVisibility::MeshInfo>::iterator visibleGeomIt,
[171]449                        visibleGeomIt_end = visibleGeometry->end();
[154]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}
[173]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();
[154]478
[173]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());
[174]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        }
[173]515}
[174]516
[154]517} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.