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

Revision 2360, 11.0 KB checked in by mattausch, 17 years ago (diff)
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#if 0   
192        Octree *octant = static_cast<Octree *>(node);
193
194        // node not visited in this frame => no change
195        if (octant->lastVisited() != mFrameId)
196                return;
197       
198        // leaf node: terminate recursion
199        if (IsLeaf(node))
200        {
201                octant->setNumLeaves(1);       
202                octant->setNumVisibleLeaves(octant->isOctreeVisible() ? 1 : 0);
203                return;
204        }
205
206        int numVisibleLeaves = 0;
207        int numLeaves = 0;
208
209        Octree *nextChild;
210       
211        for (int i = 0; i < 8; ++ i)
212        {
213                int x = (i & 4) / 4;
214                int y = (i & 2) / 2;
215                int z = i & 1;
216
217                nextChild = octant->mChildren[x][y][z];
218
219                if (!nextChild)
220                        continue;
221               
222                // recursive traversal
223                DetermineVisibilityRatio(nextChild);
224               
225                // this leaf is not fully visible
226                numLeaves += nextChild->getNumLeaves();
227                numVisibleLeaves += nextChild->getNumVisibleLeaves();
228        }
229
230        octant->setNumLeaves(numLeaves);
231        octant->setNumVisibleLeaves(numVisibleLeaves);
232#endif
233}
234//-----------------------------------------------------------------------
235void OctreeHierarchyInterface::RenderNode(GtpVisibility::HierarchyNode *node)
236{
237#ifdef GTP_VISIBILITY_MODIFIED_OGRE
238        Octree *octant = static_cast<Octree *>(node);
239
240        if (octant->lastRendered() != mFrameId)
241        {
242                octant->setLastRendered(mFrameId);
243                OctreeSceneManager *ocm =
244                        static_cast<OctreeSceneManager *>(mSceneManager);
245
246                ocm->_renderOctant(mCamera,
247                                                   octant,
248                                                   mOnlyShadowCasters,
249                                                   mLeavePassesInQueue);
250
251                mVisibleNodes.push_back(node);
252        }
253#endif 
254}
255//-----------------------------------------------------------------------
256void OctreeHierarchyInterface::RenderNodeRecursive(GtpVisibility::HierarchyNode *node)
257{
258#ifdef GTP_VISIBILITY_MODIFIED_OGRE
259        Octree *octant = static_cast<Octree *>(node);
260
261        if (octant->lastRendered() != mFrameId)
262        {
263                octant->setLastRendered(mFrameId);
264
265                OctreeSceneManager *ocm =
266                        static_cast<OctreeSceneManager *>(mSceneManager);
267
268                ocm->_renderOctantRecursive(mCamera,
269                                                                        octant,
270                                                                        mOnlyShadowCasters,
271                                                                        mLeavePassesInQueue);
272
273                mVisibleNodes.push_back(node);
274        }
275#endif 
276}
277//-----------------------------------------------------------------------
278bool OctreeHierarchyInterface::IsNodeVisible(GtpVisibility::HierarchyNode *node) const
279{
280#ifdef GTP_VISIBILITY_MODIFIED_OGRE
281        return static_cast<Octree *>(node)->isOctreeVisible();
282#else
283        return true;
284#endif
285}
286//-----------------------------------------------------------------------
287bool OctreeHierarchyInterface::IsNodeFullyVisible(GtpVisibility::HierarchyNode *node) const
288{
289        return static_cast<Octree *>(node)->isOctreeFullyVisible();
290}
291//-----------------------------------------------------------------------
292float OctreeHierarchyInterface::GetNodeVisibilityRatio(GtpVisibility::HierarchyNode *node) const
293{
294#if 0
295        return static_cast<Octree *>(node)->getVisibilityRatio();
296#else
297        return 1.0f;
298#endif
299}
300//-----------------------------------------------------------------------
301unsigned int OctreeHierarchyInterface::LastVisited(GtpVisibility::HierarchyNode *node) const
302{
303#ifdef GTP_VISIBILITY_MODIFIED_OGRE
304        return static_cast<Octree *>(node)->lastVisited();
305#else
306        return 0;
307#endif
308}
309//-----------------------------------------------------------------------
310AxisAlignedBox *OctreeHierarchyInterface::GetBoundingBox(GtpVisibility::HierarchyNode *node)
311{
312        // reuse box if node is the same
313        // only create renderable bounding box for new node
314        if (node != mSavedNode)
315        {
316                mSavedNode = node;
317            //static_cast<Octree *>(node)->_getCullBounds(&mBox);
318                mBox = static_cast<Octree *>(node)->_getWorldAABB();
319        }
320
321        return &mBox;
322}
323//-----------------------------------------------------------------------
324void OctreeHierarchyInterface::VisualizeCulledNode(GtpVisibility::HierarchyNode *node,
325                                                                                                   GtpVisibility::CullingType type) const
326{
327        WireBoundingBox *box = static_cast<Octree *>(node)->getWireBoundingBox();
328
329        if (type == GtpVisibility::FRUSTUM_CULLED)
330        {
331                box->setMaterial("FrustumCulledNodesMaterial");
332        }
333        else // type == GtpVisibility::QUERY_CULLED
334        {
335                box->setMaterial("QueryCulledNodesMaterial");
336        }
337
338        static_cast<OctreeSceneManager *>(mSceneManager)->getBoxes()->push_back(box);
339}
340//-----------------------------------------------------------------------
341void OctreeHierarchyInterface::GetNodeGeometryList(GtpVisibility::HierarchyNode *node,
342                                                                                                   GeometryVector *geometryList,
343                                                                                                   bool includeChildren)
344{
345        NodeList::const_iterator nodeIt, nodeIt_end;
346        nodeIt_end = static_cast<Octree *>(node)->mNodes.end();
347
348        for (nodeIt = static_cast<Octree *>(node)->mNodes.begin(); nodeIt != nodeIt_end; ++nodeIt)
349        {
350                SceneNodeHierarchyInterface::GetNodeGeometryList(*nodeIt, geometryList, includeChildren);
351        }
352}
353//-----------------------------------------------------------------------
354void OctreeHierarchyInterface::CollectLeaves(GtpVisibility::HierarchyNode *root,
355                                                                                         GtpVisibility::HierarchyNodeContainer &nodes)
356{
357        std::stack<GtpVisibility::HierarchyNode *> tStack;
358        tStack.push(root);
359
360        Octree *child;
361
362        while (!tStack.empty())
363        {
364                GtpVisibility::HierarchyNode *node = tStack.top();
365                tStack.pop();
366
367                if (IsLeaf(node))
368                {
369                        nodes.push_back(node);
370                }
371                else
372                {
373                        Octree *octree = static_cast<Octree *>(node);
374                       
375                        for (int z = 0; z < 2; ++ z)
376                        {       
377                                for (int y = 0; y < 2; ++ y)
378                                {
379                                        for (int x = 0; x < 2; ++ x)
380                                        {
381                                                if ((child = octree->mChildren[x][y][z]) != NULL)
382                                                {
383                                                        tStack.push(child);
384                                                }
385                                        }
386                                }
387                        }
388                }
389        }
390}
391
392//-----------------------------------------------------------------------
393GtpVisibility::HierarchyNode *OctreeHierarchyInterface::GetParent(GtpVisibility::HierarchyNode *node)
394{
395        Octree *octree = static_cast<Octree *>(node);
396
397        return octree->getParent();
398}
399
400} // namespace Ogre
Note: See TracBrowser for help on using the repository browser.