source: GTP/trunk/Lib/Vis/OnlineCullingCHC/OGRE/src/OgreOctreeHierarchyInterface.cpp @ 2332

Revision 2332, 11.2 KB checked in by mattausch, 17 years ago (diff)

implemented part of rendering estimation of wimmer et al. for view space / object space subdivision.
warning: not working with undersampling estimation + local visibility based subdivision.

Line 
1#include "OgreOctreeHierarchyInterface.h"
2#include <OgreOctree.h>
3#include <OgreLogManager.h>
4#include <OgreStringConverter.h>
5
6
7namespace Ogre {
8
9//-----------------------------------------------------------------------
10OctreeHierarchyInterface::OctreeHierarchyInterface(OctreeSceneManager *sm,
11                                                                                                   RenderSystem *rsys):
12SceneNodeHierarchyInterface(sm, rsys)
13{}
14//-----------------------------------------------------------------------
15void OctreeHierarchyInterface::TraverseNode(GtpVisibility::HierarchyNode *node)
16{
17        ++ mNumTraversedNodes;
18
19        Octree *octree = static_cast<Octree *>(node);
20
21        // if we come across some renderable geometry => render it
22        if (!octree->mNodes.empty())
23        {
24                RenderNode(node);
25        }
26       
27       
28        // if not all subtrees are empty
29        if (!IsLeaf(node))
30        {
31                Octree *nextChild;
32
33                for (int z = 0; z < 2; ++ z)
34                {       
35                        for (int y = 0; y < 2; ++ y)
36                        {
37                                for (int x = 0; x < 2; ++ x)
38                                {
39                                        nextChild = octree->mChildren[x][y][z];
40       
41                                        if (nextChild)
42                        GetQueue()->push(nextChild);
43                                }
44            }
45        }
46        }
47}
48//-----------------------------------------------------------------------
49GtpVisibility::HierarchyNode *OctreeHierarchyInterface::GetRandomLeaf(GtpVisibility::HierarchyNode *root)
50{
51        if (IsLeaf(root))
52                return root;
53
54        Octree *octree = static_cast<Octree *>(root);
55
56        // random decision
57        Octree *child = NULL;
58       
59        std::vector<Octree *> nodes;
60        nodes.reserve(8);
61
62        for (int z = 0; z < 2; ++ z)
63        {       
64                for (int y = 0; y < 2; ++ y)
65                {
66                        for (int x = 0; x < 2; ++ x)
67                        {
68                                if ((child = octree->mChildren[x][y][z]) != NULL)
69                                {
70                                        nodes.push_back(child);
71                                }
72                        }
73                }
74        }
75
76        if (nodes.empty())
77                return NULL;
78
79        int r = (int)(((float)rand() / RAND_MAX) * ((float)nodes.size() - 0.5f));
80
81        return GetRandomLeaf(nodes[r]);
82}
83//-----------------------------------------------------------------------
84bool OctreeHierarchyInterface::IsLeaf(GtpVisibility::HierarchyNode *node) const
85{
86        Octree *octree = static_cast<Octree *>(node);
87
88        // HACK: if there are subtrees, they are empty => we are not interested in them
89        return octree->numNodes() == (int)octree->mNodes.size();
90}
91//-----------------------------------------------------------------------
92bool OctreeHierarchyInterface::HasGeometry(GtpVisibility::HierarchyNode *node) const
93{
94        return !(static_cast<Octree *>(node))->mNodes.empty();
95}
96//-----------------------------------------------------------------------
97float OctreeHierarchyInterface::GetSquaredDistance(GtpVisibility::HierarchyNode *node) const
98{
99        const Vector3 bmin = static_cast<Octree *>(node)->mBox.getMinimum();
100        const Vector3 bmax = static_cast<Octree *>(node)->mBox.getMaximum();
101
102        const Vector3 pos = (bmax - bmin) * 0.5f + bmin;
103       
104        return (mCameraPosition - pos).squaredLength();
105}
106//-----------------------------------------------------------------------
107void OctreeHierarchyInterface::SetNodeVisible(GtpVisibility::HierarchyNode *node,
108                                                                                          const bool visible) const
109{
110#ifdef GTP_VISIBILITY_MODIFIED_OGRE
111        static_cast<Octree *>(node)->setOctreeVisible(visible);
112#endif
113}
114//-----------------------------------------------------------------------
115void OctreeHierarchyInterface::SetLastVisited(GtpVisibility::HierarchyNode *node,
116                                                                                          const unsigned int frameId) const
117{
118#ifdef GTP_VISIBILITY_MODIFIED_OGRE
119        static_cast<Octree *>(node)->setLastVisited(frameId);
120#endif
121}
122//-----------------------------------------------------------------------
123void OctreeHierarchyInterface::PullUpVisibility(GtpVisibility::HierarchyNode *node) const
124{               
125#ifdef GTP_VISIBILITY_MODIFIED_OGRE
126        Octree *octant = static_cast<Octree *>(node);
127
128        while (octant && !octant->isOctreeVisible())
129        {
130                octant->setOctreeVisible(true);
131                octant = octant->getParent();
132        }
133#endif
134}
135//-----------------------------------------------------------------------
136void OctreeHierarchyInterface::PullUpLastVisited(GtpVisibility::HierarchyNode *node, const int frameId) const
137{               
138#ifdef GTP_VISIBILITY_MODIFIED_OGRE
139        Octree *octant = static_cast<Octree *>(node);
140
141        while (octant && (octant->lastVisited() != frameId))
142        {
143                octant->setLastVisited(frameId);
144                octant = octant->getParent();
145        }
146#endif
147}
148//-----------------------------------------------------------------------
149void OctreeHierarchyInterface::DetermineFullVisibility(GtpVisibility::HierarchyNode *node) const
150{               
151        Octree *octant = static_cast<Octree *>(node);
152
153        // node not visited in this frame => no change
154        if (octant->lastVisited() != mFrameId)
155                return;
156
157        // leaf node: terminate recursion
158        if (IsLeaf(node))
159        {
160                octant->setOctreeFullyVisible(octant->isOctreeVisible());       
161                return;
162        }
163
164        octant->setOctreeFullyVisible(true);
165        Octree *nextChild;
166       
167        for (int i = 0; i < 8; ++ i)
168        {
169                int x = (i & 4) / 4;
170                int y = (i & 2) / 2;
171                int z = i & 1;
172
173                nextChild = octant->mChildren[x][y][z];
174
175                if (!nextChild)
176                        continue;
177               
178                // recursive traversal
179                DetermineFullVisibility(nextChild);
180               
181                // this leaf is not fully visible
182                if (!nextChild->isOctreeFullyVisible())
183                {
184                        octant->setOctreeFullyVisible(false);
185                }
186        }
187}
188//-----------------------------------------------------------------------
189void OctreeHierarchyInterface::DetermineVisibilityRatio(GtpVisibility::HierarchyNode *node) const
190{       
191        Octree *octant = static_cast<Octree *>(node);
192
193        // node not visited in this frame => no change
194        if (octant->lastVisited() != mFrameId)
195                return;
196       
197        // leaf node: terminate recursion
198        if (IsLeaf(node))
199        {
200                octant->setNumLeaves(1);       
201                octant->setNumVisibleLeaves(octant->isOctreeVisible() ? 1 : 0);
202                return;
203        }
204
205        int numVisibleLeaves = 0;
206        int numLeaves = 0;
207
208        Octree *nextChild;
209       
210        for (int i = 0; i < 8; ++ i)
211        {
212                int x = (i & 4) / 4;
213                int y = (i & 2) / 2;
214                int z = i & 1;
215
216                nextChild = octant->mChildren[x][y][z];
217
218                if (!nextChild)
219                        continue;
220               
221                // recursive traversal
222                DetermineVisibilityRatio(nextChild);
223               
224                // this leaf is not fully visible
225                numLeaves += nextChild->getNumLeaves();
226                numVisibleLeaves += nextChild->getNumVisibleLeaves();
227        }
228
229        octant->setNumLeaves(numLeaves);
230        octant->setNumVisibleLeaves(numVisibleLeaves);
231}
232//-----------------------------------------------------------------------
233void OctreeHierarchyInterface::RenderNode(GtpVisibility::HierarchyNode *node)
234{
235#ifdef GTP_VISIBILITY_MODIFIED_OGRE
236        Octree *octant = static_cast<Octree *>(node);
237
238        if (octant->lastRendered() != mFrameId)
239        {
240                octant->setLastRendered(mFrameId);
241                OctreeSceneManager *ocm =
242                        static_cast<OctreeSceneManager *>(mSceneManager);
243
244                ocm->_renderOctant(mCamera,
245                                                   octant,
246                                                   mOnlyShadowCasters,
247                                                   mLeavePassesInQueue);
248
249                mVisibleNodes.push_back(node);
250        }
251#endif 
252}
253//-----------------------------------------------------------------------
254void OctreeHierarchyInterface::RenderNodeRecursive(GtpVisibility::HierarchyNode *node)
255{
256#ifdef GTP_VISIBILITY_MODIFIED_OGRE
257        Octree *octant = static_cast<Octree *>(node);
258
259        if (octant->lastRendered() != mFrameId)
260        {
261                octant->setLastRendered(mFrameId);
262
263                OctreeSceneManager *ocm =
264                        static_cast<OctreeSceneManager *>(mSceneManager);
265
266                ocm->_renderOctantRecursive(mCamera,
267                                                                        octant,
268                                                                        mOnlyShadowCasters,
269                                                                        mLeavePassesInQueue);
270
271                mVisibleNodes.push_back(node);
272        }
273#endif 
274}
275//-----------------------------------------------------------------------
276bool OctreeHierarchyInterface::IsNodeVisible(GtpVisibility::HierarchyNode *node) const
277{
278#ifdef GTP_VISIBILITY_MODIFIED_OGRE
279        return static_cast<Octree *>(node)->isOctreeVisible();
280#else
281        return true;
282#endif
283}
284//-----------------------------------------------------------------------
285bool OctreeHierarchyInterface::IsNodeFullyVisible(GtpVisibility::HierarchyNode *node) const
286{
287#ifdef GTP_VISIBILITY_MODIFIED_OGRE
288        //return static_cast<Octree *>(node)->getVisibilityRatio() > 0.9f;
289        return static_cast<Octree *>(node)->isOctreeFullyVisible();
290#else
291        return true;
292#endif
293}
294//-----------------------------------------------------------------------
295float OctreeHierarchyInterface::GetNodeVisibilityRatio(GtpVisibility::HierarchyNode *node) const
296{
297#ifdef GTP_VISIBILITY_MODIFIED_OGRE
298        return static_cast<Octree *>(node)->getVisibilityRatio();
299        //return static_cast<Octree *>(node)->isOctreeFullyVisible();
300#else
301        return true;
302#endif
303}
304//-----------------------------------------------------------------------
305unsigned int OctreeHierarchyInterface::LastVisited(GtpVisibility::HierarchyNode *node) const
306{
307#ifdef GTP_VISIBILITY_MODIFIED_OGRE
308        return static_cast<Octree *>(node)->lastVisited();
309#else
310        return 0;
311#endif
312}
313//-----------------------------------------------------------------------
314AxisAlignedBox *OctreeHierarchyInterface::GetBoundingBox(GtpVisibility::HierarchyNode *node)
315{
316        // reuse box if node is the same
317        // only create renderable bounding box for new node
318        if (node != mSavedNode)
319        {
320                mSavedNode = node;
321            //static_cast<Octree *>(node)->_getCullBounds(&mBox);
322                mBox = static_cast<Octree *>(node)->_getWorldAABB();
323        }
324
325        return &mBox;
326}
327//-----------------------------------------------------------------------
328void OctreeHierarchyInterface::VisualizeCulledNode(GtpVisibility::HierarchyNode *node,
329                                                                                                   GtpVisibility::CullingType type) const
330{
331        WireBoundingBox *box = static_cast<Octree *>(node)->getWireBoundingBox();
332
333        if (type == GtpVisibility::FRUSTUM_CULLED)
334        {
335                box->setMaterial("FrustumCulledNodesMaterial");
336        }
337        else // type == GtpVisibility::QUERY_CULLED
338        {
339                box->setMaterial("QueryCulledNodesMaterial");
340        }
341
342        static_cast<OctreeSceneManager *>(mSceneManager)->getBoxes()->push_back(box);
343}
344//-----------------------------------------------------------------------
345void OctreeHierarchyInterface::GetNodeGeometryList(GtpVisibility::HierarchyNode *node,
346                                                                                                   GeometryVector *geometryList,
347                                                                                                   bool includeChildren)
348{
349        NodeList::const_iterator nodeIt, nodeIt_end;
350        nodeIt_end = static_cast<Octree *>(node)->mNodes.end();
351
352        for (nodeIt = static_cast<Octree *>(node)->mNodes.begin(); nodeIt != nodeIt_end; ++nodeIt)
353        {
354                SceneNodeHierarchyInterface::GetNodeGeometryList(*nodeIt, geometryList, includeChildren);
355        }
356}
357//-----------------------------------------------------------------------
358void OctreeHierarchyInterface::CollectLeaves(GtpVisibility::HierarchyNode *root,
359                                                                                         GtpVisibility::HierarchyNodeContainer &nodes)
360{
361        std::stack<GtpVisibility::HierarchyNode *> tStack;
362        tStack.push(root);
363
364        Octree *child;
365
366        while (!tStack.empty())
367        {
368                GtpVisibility::HierarchyNode *node = tStack.top();
369                tStack.pop();
370
371                if (IsLeaf(node))
372                {
373                        nodes.push_back(node);
374                }
375                else
376                {
377                        Octree *octree = static_cast<Octree *>(node);
378                       
379                        for (int z = 0; z < 2; ++ z)
380                        {       
381                                for (int y = 0; y < 2; ++ y)
382                                {
383                                        for (int x = 0; x < 2; ++ x)
384                                        {
385                                                if ((child = octree->mChildren[x][y][z]) != NULL)
386                                                {
387                                                        tStack.push(child);
388                                                }
389                                        }
390                                }
391                        }
392                }
393        }
394}
395
396//-----------------------------------------------------------------------
397GtpVisibility::HierarchyNode *OctreeHierarchyInterface::GetParent(GtpVisibility::HierarchyNode *node)
398{
399        Octree *octree = static_cast<Octree *>(node);
400
401        return octree->getParent();
402}
403
404} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.