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

Revision 159, 8.2 KB checked in by mattausch, 19 years ago (diff)

added flags for switching on/off transparents for item buffer and vertex programs for depth pass / item buffer

Line 
1#include "OgreOcclusionQueriesQueryManager.h"
2#include <OgreLogManager.h>
3#include <OgreStringConverter.h>
4#include <vector>
5
6
7namespace Ogre {
8//-----------------------------------------------------------------------
9OcclusionQueriesQueryManager::OcclusionQueriesQueryManager(PlatformHierarchyInterface *hierarchyInterface, Viewport *vp):
10PlatformQueryManager(hierarchyInterface, vp)
11{
12}
13//-----------------------------------------------------------------------
14bool OcclusionQueriesQueryManager::ShootRay(const Ray &ray, std::vector<Mesh *> *visibleMeshes, bool isGlobalLine)
15{
16    // run OGRE ray shooting query
17    return false;
18}
19//-----------------------------------------------------------------------
20void OcclusionQueriesQueryManager::ComputeCameraVisibility(const Camera &camera,
21                            InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
22                            InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
23                                InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
24                            bool relativeVisibility)
25{
26        // we need access to the scene manager and the rendersystem
27        PlatformHierarchyInterface *pfHierarchyInterface =
28                dynamic_cast<PlatformHierarchyInterface *>(mHierarchyInterface);
29
30        //-- Render scene to get conservative visibility and fill depth buffer
31
32        // const_cast allowed because camera is not changed in renderScene
33        Camera *pCam = const_cast<Camera *>(&camera);
34
35        // disable overlays, reset them later
36        bool overlayEnabled = mViewport->getOverlaysEnabled();
37        mViewport->setOverlaysEnabled(false);
38
39        //-- render the scene once to update depth buffer
40        pfHierarchyInterface->GetSceneManager()->_renderScene(pCam, mViewport, false);
41
42        /*
43                Two query lists for projected pixels and for visibile pixels:
44                We test queries after a rendering pass
45                to get exact visibility with regard to the current camera.
46                We issue all queries at once to avoid starvation & stalls.
47        */
48        GtpVisibility::QueryList queryList[2];
49       
50        // get rendered hierarchy nodes
51        GtpVisibility::HierarchyNodeList *nodeList = mHierarchyInterface->GetRenderedNodes();
52        // vector for storing entities of meshes
53        GtpVisibility::GeometryList geometryList;
54       
55        GtpVisibility::HierarchyNodeList::iterator nodeIt, nodeIt_end = nodeList->end();
56        // geometry list has still do be built
57        GtpVisibility::GeometryList::iterator geometryIt, geometryIt_end;
58
59        // to obtain the correct number of projected pixels, depth write must be disabled
60        bool enableDepthWrite = false;
61
62        // this option must be provided by the scene manager
63        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
64
65        /* relative visiblity:
66                1) get visible pixels count of objects
67                2) clear frame buffer
68                3) get projected visible pixels count:
69                   test all objects again without depth write (set as option in scene manager)
70                4) calculate ratio between visible vs. projected pixels
71        */
72        // for relative visibility we need 2 rendering passes
73        int n = relativeVisibility ? 2 : 1;
74       
75        for (int i=0; i<n; ++i)
76        {
77                //-- queries for hierarchy nodes
78                for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)               
79                {
80                        // TODO: DELETE QUERIES FROM PREVIOUS RENDER
81                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*nodeIt, false));
82                       
83                        // store geometry of the hierarchy node in a geometry list (only once!)
84                        if (i == 0)
85                        {
86                                mHierarchyInterface->GetNodeGeometryList(*nodeIt, &geometryList, false);
87                        }
88                }
89
90                geometryIt_end = geometryList.end();
91
92                //-- add queries for geometry
93                for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
94                {
95                        queryList[i].push_back(mHierarchyInterface->IssueOcclusionQuery(*geometryIt));
96                }
97
98       
99                pfHierarchyInterface->GetRenderSystem()->clearFrameBuffer(FBT_DEPTH);
100        }
101
102        enableDepthWrite = true;
103        // this option must be provided by the scene manager
104        pfHierarchyInterface->GetSceneManager()->setOption("DepthWrite", &enableDepthWrite);
105        // reset old overlay status
106        mViewport->setOverlaysEnabled(overlayEnabled);
107
108        // ---- collect results
109        GtpVisibility::QueryList::iterator visQueryIt, projQueryIt;
110
111        visQueryIt = queryList[0].begin();
112        projQueryIt = queryList[1].begin();
113
114       
115        for (nodeIt = nodeList->begin(); nodeIt != nodeIt_end; ++nodeIt)
116        {
117                unsigned int visiblePixels = 0;
118                (*visQueryIt)->GetQueryResult(visiblePixels, true);
119       
120                unsigned int projectedPixels = 0;
121
122                if (relativeVisibility)
123                {
124                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
125               
126                        ++projQueryIt;
127                }
128
129                ++visQueryIt;
130               
131                // node with visibilty 0 in queue (e.g., if node is intersected by near plane)
132                if (visiblePixels > 0)
133                {
134                        visibleNodes->push_back(GtpVisibility::NodeInfo(*nodeIt, visiblePixels, projectedPixels));
135                }
136        }
137
138        // ---- queries for geometry
139        geometryIt_end = geometryList.end();
140       
141        for (geometryIt = geometryList.begin(); geometryIt != geometryIt_end; ++geometryIt)
142        {
143                unsigned int visiblePixels = 0;
144                (*visQueryIt)->GetQueryResult(visiblePixels, true);
145               
146                unsigned int projectedPixels = 0;
147
148                if (relativeVisibility)
149                {
150                        (*projQueryIt)->GetQueryResult(projectedPixels, true);
151
152                        ++projQueryIt;
153                }
154
155                ++visQueryIt;
156
157                // WARNING: approximate depth ordering during rendering =>
158                // geometry maybe occluded
159                if (visiblePixels > 0)
160                {                       
161                        visibleGeometry->push_back(GtpVisibility::MeshInfo(*geometryIt, visiblePixels,
162                                projectedPixels));
163                }
164        }
165
166}
167//-----------------------------------------------------------------------
168inline bool nodeinfo_eq(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
169{
170        return info1.GetNode() == info2.GetNode();
171}
172//-----------------------------------------------------------------------
173inline bool meshinfo_eq(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
174{
175        return info1.GetMesh() == info2.GetMesh();
176}
177//-----------------------------------------------------------------------
178inline bool nodeinfo_lower(const GtpVisibility::NodeInfo &info1, const GtpVisibility::NodeInfo &info2)
179{
180        return info1.GetNode() < info2.GetNode();
181}
182//-----------------------------------------------------------------------
183inline bool meshinfo_lower(const GtpVisibility::MeshInfo &info1, const GtpVisibility::MeshInfo &info2)
184{
185        return info1.GetMesh() < info2.GetMesh();
186}
187//-----------------------------------------------------------------------
188void OcclusionQueriesQueryManager::ComputeFromPointVisibility(const Vector3 &point,
189                               InfoContainer<GtpVisibility::NodeInfo> *visibleNodes,
190                               InfoContainer<GtpVisibility::MeshInfo> *visibleGeometry,
191                                   InfoContainer<GtpVisibility::PatchInfo> *visiblePatches,
192                               bool relativeVisibility)
193{
194        PlatformQueryManager::ComputeFromPointVisibility(point, visibleNodes,
195                visibleGeometry, visiblePatches, relativeVisibility);
196
197        // --- remove duplicates (duplicates occur if an object is on the edge of the viewport)
198
199        // before duplicates can be deleted we have to add up their visibility
200
201        // --- visible nodes
202        sort(visibleNodes->begin(), visibleNodes->end(), nodeinfo_lower);
203        InfoContainer<GtpVisibility::NodeInfo>::iterator visibleNodesIt,
204                visibleNodesIt_end = visibleNodes->end();
205       
206        GtpVisibility::NodeInfo *nodeInfo = NULL;
207
208        for (visibleNodesIt = visibleNodes->begin(); visibleNodesIt != visibleNodesIt_end;
209                ++visibleNodesIt)
210        {
211                if (!nodeInfo || (nodeInfo->GetNode() != (*visibleNodesIt).GetNode()))
212                {
213                        nodeInfo = &(*visibleNodesIt);
214                }
215                else // add visibility
216                {                       
217                        nodeInfo->AddVisibility(*visibleNodesIt);
218                }
219
220        }
221       
222        // physically delete duplicates
223        visibleNodes->erase( std::unique(visibleNodes->begin(),
224                visibleNodes->end(), nodeinfo_eq), visibleNodes->end());
225
226        // --- visible geometry
227        sort(visibleGeometry->begin(), visibleGeometry->end(), meshinfo_lower);
228        InfoContainer<GtpVisibility::MeshInfo>::iterator visibleGeomIt,
229                visibleGeomIt_end = visibleGeometry->end();
230
231        GtpVisibility::MeshInfo *geomInfo = NULL;
232
233        int i=0;
234        for (visibleGeomIt = visibleGeometry->begin(); visibleGeomIt != visibleGeomIt_end;
235                ++visibleGeomIt)
236        {
237                if (!geomInfo || (geomInfo->GetMesh() != (*visibleGeomIt).GetMesh()))
238                {
239                        geomInfo = &(*visibleGeomIt);
240                }
241                else // info points to same mesh, just add visibility
242                {
243                        geomInfo->AddVisibility(*visibleGeomIt);
244                }
245        }
246
247        // physically delete duplicates
248        visibleGeometry->erase(std::unique(visibleGeometry->begin(), visibleGeometry->end(),
249                meshinfo_eq), visibleGeometry->end());
250}
251
252} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.