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

Revision 370, 15.4 KB checked in by mattausch, 19 years ago (diff)

fixed specular bug in trees
added batched query manager
added t information to ray bsp leaves

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