source: OGRE/trunk/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

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//-----------------------------------------------------------------------
11OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(
12                                                        PlatformHierarchyInterface *hierarchyInterface,
13                                                        Viewport *vp,
14                                                        int queryModes,
15                                                        int itemBufferMode):
16PlatformQueryManager(hierarchyInterface, vp, queryModes),
17mItemBufferMode(itemBufferMode)
18{
19}
20//-----------------------------------------------------------------------
21void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
22                            GtpVisibility::NodeInfoContainer *visibleNodes,
23                            GtpVisibility::MeshInfoContainer *visibleGeometry,
24                                GtpVisibility::PatchInfoContainer *visiblePatches,
25                            bool relativeVisibility)
26{
27        // we need access to the scene manager and the rendersystem
28        PlatformHierarchyInterface *pfHierarchyInterface =
29                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
30
31        // disable overlays, reset them later
32        bool overlayEnabled = mViewport->getOverlaysEnabled();
33
34        //-- render scene with item buffer (i.e., objects with their id as color codes)
35//mItemBufferMode = 0;
36        if ((mItemBufferMode && mQueryModes) != 0)
37        {
38                int savedQueryModes = mQueryModes;
39                mQueryModes = mItemBufferMode;
40               
41                PlatformQueryManager::ComputeCameraVisibility(camera, visibleNodes,
42                            visibleGeometry, visiblePatches, relativeVisibility);
43               
44                // overlays cause false visibility
45                mViewport->setOverlaysEnabled(false);
46                mQueryModes = savedQueryModes;
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:
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       
66        // rendered visibile hierarchy nodes from previous rendering
67        GtpVisibility::NodeVector *visNodes = mHierarchyInterface->GetVisibleNodes();
68        GtpVisibility::NodeVector::iterator visNodesIt, visNodesIt_end = visNodes->end();
69
70    GtpVisibility::NodeVector nodeList;
71
72        if (mQueryModes & NODE_VISIBILITY)
73        {
74                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)
75                {
76                        nodeList.push_back((*visNodesIt));
77                }
78        }
79
80        GtpVisibility::NodeVector::iterator nodeIt, nodeIt_end = nodeList.end();
81
82        // vector for storing entities of meshes
83        GtpVisibility::GeometryVector geometryList;
84       
85        // store geometry of the hierarchy nodes in a geometry list
86        if (mQueryModes & GEOMETRY_VISIBILITY)
87        {       
88                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
89                {
90                        mHierarchyInterface->GetNodeGeometryList(*visNodesIt, &geometryList, false);
91                }
92        }
93       
94        // geometry list iterator
95        GtpVisibility::GeometryVector::iterator geometryIt, geometryIt_end = geometryList.end();
96
97        // vector for storing subentities of meshes
98        GtpVisibility::PatchVector patchList;
99
100        // store patchges of the geometries in a patch list
101        if (mQueryModes & PATCH_VISIBILITY)
102        {
103                for (visNodesIt = visNodes->begin(); visNodesIt != visNodesIt_end; ++visNodesIt)       
104                {
105                        GetNodePatchList(*visNodesIt, &patchList);
106                }
107        }
108
109        GtpVisibility::PatchVector::iterator patchIt, patchIt_end = patchList.end();
110
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
116
117        /* relative visiblity:
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
123        */
124               
125        // for relative visibility we need 2 rendering passes
126        int n = relativeVisibility ? 2 : 1;
127        if (mItemBufferMode > 0)
128                LogManager::getSingleton().logMessage("item buffer");
129
130        for (int i = 0; i < n; ++i)
131        {
132                //-- queries for hierarchy nodes
133                for (nodeIt = nodeList.begin(); nodeIt != nodeIt_end; ++nodeIt)         
134                {
135                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
136                        queryList[i].push_back(mHierarchyInterface->IssueNodeOcclusionQuery(*nodeIt, false));
137                }
138
139                //-- queries for geometry: if item buffer, capture only projected visibility
140                if ((mItemBufferMode != GEOMETRY_VISIBILITY) || (i == 1))
141                {                       
142                        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
143                        {
144                                queryList[i].push_back(pfHierarchyInterface->IssueMeshOcclusionQuery(*geometryIt));
145                        }
146                }
147               
148                //-- queries for patches: if item buffer, capture only projected visibility
149                if ((mItemBufferMode != PATCH_VISIBILITY) || (i == 1))
150                {
151                        for (patchIt = patchList.begin(); patchIt != patchIt_end; ++patchIt)
152                        {
153                                queryList[i].push_back(pfHierarchyInterface->IssuePatchOcclusionQuery(*patchIt));
154                        }
155                }
156
157                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
158        }
159
160       
161        //-- collect results
162        GtpVisibility::QueryList::iterator visQueryIt = queryList[0].begin();
163        GtpVisibility::QueryList::iterator projQueryIt = queryList[1].begin();
164       
165        // collect occlusion queries for hierarchy nodes
166        CollectNodeVisibility(visQueryIt, projQueryIt, &nodeList, visibleNodes, relativeVisibility);
167
168
169        // collect occlusion queries for geometry
170        if ((mItemBufferMode == GEOMETRY_VISIBILITY) && relativeVisibility)
171        {
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        }
176        else if (mItemBufferMode != GEOMETRY_VISIBILITY)
177        {
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        }
188        else if (mItemBufferMode != PATCH_VISIBILITY)
189        {
190                CollectPatchVisibility(visQueryIt, projQueryIt, &patchList, visiblePatches, relativeVisibility);
191        }       
192
193               
194        //-- reset options
195        enableDepthWrite = true;
196        // this option must be provided by the scene manager
197        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
198        // reset old overlay status
199        mViewport->setOverlaysEnabled(overlayEnabled);
200
201        mWasInitialised = false;
202}
203//-----------------------------------------------------------------------
204void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
205                               GtpVisibility::NodeInfoContainer *visibleNodes,
206                               GtpVisibility::MeshInfoContainer *visibleGeometry,
207                                   GtpVisibility::PatchInfoContainer *visiblePatches,
208                               bool relativeVisibility)
209{
210        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes,
211                visibleGeometry, visiblePatches, relativeVisibility);
212
213        // adds up their visibility and removes duplicates
214        // (duplicates occur if an object is on the edge of the viewport)
215        RemoveDuplicateNodes(visibleNodes);
216       
217        if (mItemBufferMode != GEOMETRY_VISIBILITY)
218        {
219                RemoveDuplicateGeometry(visibleGeometry);
220        }
221       
222        if (mItemBufferMode != PATCH_VISIBILITY)
223        {
224                RemoveDuplicatePatches(visiblePatches);
225        }
226}
227//------j-----------------------------------------------------------------
228void  OcclusionQueriesQueryManager::CollectNodeVisibility(
229                                                GtpVisibility::QueryList::iterator &visQueryIt,
230                                                GtpVisibility::QueryList::iterator &projQueryIt,
231                                                GtpVisibility::NodeVector *nodeList, 
232                                                GtpVisibility::NodeInfoContainer *visibleNodes,
233                                                bool relativeVisibility)
234{
235        GtpVisibility::NodeVector::iterator nodeIt;
236
237        //-- queries for nodes
238        for (nodeIt = nodeList->begin(); nodeIt != nodeList->end(); ++nodeIt)
239        {
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                {
257                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels,
258                                projectedPixels));
259                }
260        }
261}
262//-----------------------------------------------------------------------
263void OcclusionQueriesQueryManager::CollectRelativeGeometryVisibilityForItemBuffer(
264                                                                        GtpVisibility::QueryList::iterator &projQueryIt,
265                                                                        GtpVisibility::GeometryVector *geometryList,
266                                                                        GtpVisibility::MeshInfoContainer *visibleGeometry)
267{
268        GtpVisibility::GeometryVector::iterator geometryIt;
269
270        //-- queries for geometry
271        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
272        {
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,
289                                                                        GtpVisibility::PatchVector *patchList,
290                                                                        GtpVisibility::PatchInfoContainer *visiblePatches)
291{
292        GtpVisibility::PatchVector::iterator patchIt;
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,
314                                                        GtpVisibility::GeometryVector *geometryList,
315                                                        GtpVisibility::MeshInfoContainer *visibleGeometry,
316                                                        bool relativeVisibility)
317{
318        GtpVisibility::GeometryVector::iterator geometryIt;
319
320        //-- queries for geometry
321        for (geometryIt = geometryList->begin(); geometryIt != geometryList->end(); ++ geometryIt)
322        {
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);
331                        ++ projQueryIt;
332                }
333
334                ++ visQueryIt;
335
336                // WARNING: approximate depth ordering during rendering =>
337                // geometry maybe occluded
338                if (visiblePixels > 0)
339                {                       
340                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
341                                projectedPixels));
342                }
343        }
344}
345//-----------------------------------------------------------------------
346void  OcclusionQueriesQueryManager::CollectPatchVisibility(
347                                                        GtpVisibility::QueryList::iterator &visQueryIt,
348                                                        GtpVisibility::QueryList::iterator &projQueryIt,
349                                                        GtpVisibility::PatchVector *patchList,
350                                                        GtpVisibility::PatchInfoContainer *visiblePatches,
351                                                        bool relativeVisibility)
352{
353        GtpVisibility::PatchVector::iterator patchIt;
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        }
379}
380//-----------------------------------------------------------------------
381void  OcclusionQueriesQueryManager::RemoveDuplicateNodes(
382                                        GtpVisibility::NodeInfoContainer *visibleNodes)
383{
384        stable_sort(visibleNodes->begin(), visibleNodes->end()/*, nodeinfo_lt*/);
385
386        GtpVisibility::NodeInfoContainer::iterator visibleNodesIt,
387                visibleNodesIt_end = visibleNodes->end();
388       
389        GtpVisibility::NodeInfo *nodeInfo = NULL;
390
391        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
392                ++visibleNodesIt)
393        {
394                if (!nodeInfo || (nodeInfo->GetSource() != (*visibleNodesIt).GetSource()))
395                {
396                        nodeInfo = &(*visibleNodesIt);
397                }
398                else // add visibility
399                {                       
400                        nodeInfo->AddVisibility(*visibleNodesIt);
401                }
402        }
403       
404        // physically delete duplicates
405        visibleNodes->erase(std::unique(visibleNodes->begin(), visibleNodes->end()),
406                                                visibleNodes->end());
407}
408//-----------------------------------------------------------------------
409void  OcclusionQueriesQueryManager::RemoveDuplicateGeometry(
410                                GtpVisibility::MeshInfoContainer *visibleGeometry)
411{
412        stable_sort(visibleGeometry->begin(), visibleGeometry->end());
413       
414        GtpVisibility::MeshInfoContainer::iterator visibleGeomIt,
415                        visibleGeomIt_end = visibleGeometry->end();
416
417        GtpVisibility::MeshInfo *geomInfo = NULL;
418
419        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
420                ++visibleGeomIt)
421        {
422                if (!geomInfo || (geomInfo->GetSource() != (*visibleGeomIt).GetSource()))
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
433        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end()),
434                                                   visibleGeometry->end());
435}
436//-----------------------------------------------------------------------
437void  OcclusionQueriesQueryManager::RemoveDuplicatePatches(
438                                GtpVisibility::PatchInfoContainer *visiblePatches)
439{
440        stable_sort(visiblePatches->begin(), visiblePatches->end());
441       
442        GtpVisibility::PatchInfoContainer::iterator visiblePatchIt,
443                        visiblePatchIt_end = visiblePatches->end();
444
445        GtpVisibility::PatchInfo *patchInfo = NULL;
446
447        for (visiblePatchIt = visiblePatches->begin(); visiblePatchIt != visiblePatchIt_end;
448                ++visiblePatchIt)
449        {
450                if (!patchInfo || (patchInfo->GetSource() != (*visiblePatchIt).GetSource()))
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
461        visiblePatches->erase(std::unique(visiblePatches->begin(), visiblePatches->end()),
462                                                  visiblePatches->end());
463}
464//-----------------------------------------------------------------------
465void OcclusionQueriesQueryManager::GetNodePatchList(GtpVisibility::HierarchyNode *node,
466                                                                                                        GtpVisibility::PatchVector *patchList)
467{
468        GtpVisibility::GeometryVector geomList;
469        mHierarchyInterface->GetNodeGeometryList(node, &geomList, false);
470
471        // geometry list iterator
472        GtpVisibility::GeometryVector::iterator geomIt, geomIt_end = geomList.end();
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        }
481}
482
483} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.