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

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

added bounding boxes to xml description

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