source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Bvh.cpp @ 2782

Revision 2782, 19.4 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include <queue>
2#include <stack>
3#include <fstream>
4#include <iostream>
5#include <iomanip>
6
7#include "Bvh.h"
8#include "Camera.h"
9#include "Plane3.h"
10#include "glInterface.h"
11#include "Triangle3.h"
12#include "SceneEntity.h"
13#include "Geometry.h"
14#include "RenderState.h"
15
16
17namespace CHCDemoEngine
18{
19
20#define INVALID_TEST ((unsigned int)-1)
21
22using namespace std;
23
24
25
26/*
273 x---------x 2
28  |\         \
29  | \         \
30  |  \         \
31  |     4 x---------x 5
32  |   |         |
330 x   |     x 1 |
34   \  |         |
35    \ |         |
36     \|         |
37        7 x---------x 6             
38*/
39
40static unsigned int sIndices[] =       
41{7, // degenerated
42 7, 6, 4, 5, 3, 2, 0, 1,
43 1, 4, // degenerated
44 4, 3, 7, 0, 6, 1, 5, 2,
45 2 // degenerated
46};
47
48
49const static int sNumIndicesPerBox = 20;
50
51/*      Order of vertices
52        0 = (0, 0, 0)
53        1 = (1, 0, 0)
54        2 = (1, 1, 0)
55        3 = (0, 1, 0)
56        4 = (0, 1, 1)
57        5 = (1, 1, 1)
58        6 = (1, 0, 1)
59        7 = (0, 0, 1)
60*/
61
62static Plane3 sNearPlane;
63static Camera::Frustum sFrustum;
64
65/// these values are valid for all nodes
66static int sClipPlaneAABBVertexIndices[12];
67
68
69BvhNode::BvhNode(BvhNode *parent):
70mParent(parent),
71mAxis(-1),
72mDepth(0),
73mPlaneMask(0),
74mPreferredPlane(0),
75mLastRenderedFrame(-999),
76mFirst(-1),
77mLast(-1),
78mNumTestNodes(1),
79mTestNodesIdx(-1),
80mIndicesPtr(-1),
81mIndices(NULL),
82mId(0),
83mIsMaxDepthForVirtualLeaf(false),
84mIsVirtualLeaf(false)
85{
86}
87
88
89BvhNode::~BvhNode()
90{
91}
92
93
94void BvhNode::ResetVisibility()
95{
96        mVisibility.Reset();
97
98        mLastRenderedFrame = -999;
99}
100
101
102void BvhNode::VisibilityInfo::Reset()
103{
104        mIsVisible = false;
105        mAssumedVisibleFrameId = 0;
106        mLastVisitedFrame = -1;
107        mTimesInvisible = 0;
108        mIsFrustumCulled = false;
109        mIsNew = true;
110}
111
112
113BvhLeaf::~BvhLeaf()
114{
115}
116
117
118/***********************************************************/
119/*                class Bvh implementation                 */
120/***********************************************************/
121
122
123Bvh::Bvh()
124{
125        Init();
126}
127
128
129Bvh::Bvh(const SceneEntityContainer &entities)
130{
131        Init();
132
133        mGeometrySize = entities.size();
134        mGeometry = new SceneEntity*[mGeometrySize];
135       
136        mBox.Initialize();
137
138        SceneEntityContainer::const_iterator it, it_end = entities.end();
139
140        int i = 0;
141        for (it = entities.begin(); it != it_end; ++ it, ++ i)
142        {
143                mGeometry[i] = (*it);
144                mBox.Include((*it)->GetBoundingBox());
145        }
146
147        cout << "scene box: " << mBox << endl;
148}
149
150
151Bvh::~Bvh()
152{
153        if (mVertices) delete []mVertices;
154        if (mIndices) delete [] mIndices;
155        if (mTestIndices) delete [] mTestIndices;
156        if (mGeometry) delete [] mGeometry;
157
158        if (mRoot) delete mRoot;
159}
160
161
162void Bvh::Init()
163{
164        mCamera = NULL;
165        mRoot = NULL;
166        mVertices = NULL;
167        mIndices = NULL;
168        mTestIndices = NULL;
169        mCurrentIndicesPtr = 0;
170        mNumNodes = 0;
171        mMaxDepthForTestingChildren = 4;
172        mAreaRatioThreshold = 1.4f;
173        mVboId = -1;
174}
175
176
177void Bvh::PullUpLastVisited(BvhNode *node, const int frameId) const
178{               
179        BvhNode *parent = node->GetParent();
180
181        while (parent && (parent->GetLastVisitedFrame() != frameId))
182        {
183                parent->SetLastVisitedFrame(frameId);
184                parent = parent->GetParent();
185        }
186}
187
188
189void Bvh::MakeParentsVisible(BvhNode *node)
190{
191        BvhNode *parent = node->GetParent();
192
193        while (parent && (!parent->IsVisible()))
194        {
195                parent->SetVisible(true);
196                parent = parent->GetParent();
197        }
198}
199
200
201void Bvh::CollectLeaves(BvhNode *node, BvhLeafContainer &leaves)
202{
203        stack<BvhNode *> tStack;
204        tStack.push(node);
205
206        while (!tStack.empty())
207        {
208                BvhNode *node = tStack.top();
209
210                tStack.pop();
211
212                if (!node->IsLeaf())
213                {
214                        BvhInterior *interior = static_cast<BvhInterior *>(node);
215
216                        tStack.push(interior->mFront);
217                        tStack.push(interior->mBack);
218                }
219                else
220                {
221                        leaves.push_back(static_cast<BvhLeaf *>(node));
222                }
223        }
224}
225
226
227void Bvh::CollectNodes(BvhNode *node, BvhNodeContainer &nodes)
228{
229        stack<BvhNode *> tStack;
230
231        tStack.push(node);
232
233        while (!tStack.empty())
234        {
235                BvhNode *node = tStack.top();
236                tStack.pop();
237
238                nodes.push_back(node);
239
240                if (!node->IsLeaf())
241                {
242                        BvhInterior *interior = static_cast<BvhInterior *>(node);
243
244                        tStack.push(interior->mFront);
245                        tStack.push(interior->mBack);
246                }
247        }
248}
249
250
251typedef pair<BvhNode *, int> tPair;
252
253void Bvh::CollectNodes(BvhNode *root, BvhNodeContainer &nodes, int depth)
254{
255        stack<tPair> tStack;
256        tStack.push(tPair(root, 0));
257
258        while (!tStack.empty())
259        {
260                BvhNode *node = tStack.top().first;
261                const int d = tStack.top().second;
262
263                tStack.pop();
264
265                // found depth => take this node
266                if ((d == depth) || (node->IsLeaf()))
267                {
268                        nodes.push_back(node);
269                }
270                else
271                {
272                        BvhInterior *interior = static_cast<BvhInterior *>(node);
273
274                        tStack.push(tPair(interior->mFront, d + 1));
275                        tStack.push(tPair(interior->mBack, d + 1));
276                }
277        }
278}
279
280
281SceneEntity **Bvh::GetGeometry(BvhNode *node, int &geometrySize)
282{
283        geometrySize = node->CountPrimitives();
284        return mGeometry + node->mFirst;
285}
286
287
288bool Bvh::TestPlane(BvhNode *node, int i, bool &bIntersect)
289{
290        // do the test only if necessary
291        if (!(node->mPlaneMask & (1 << i)))
292                return true;
293                       
294        ////////
295        //-- test the n-vertex
296               
297        if ((node->mBox.GetDistance(sClipPlaneAABBVertexIndices[i * 2 + 0], sFrustum.mClipPlanes[i]) > 0.0f))
298        {
299                // outside
300                node->mPreferredPlane = i;
301                return false;
302        }
303
304        ////////////
305        //-- test the p-vertex
306
307        if (node->mBox.GetDistance(sClipPlaneAABBVertexIndices[i * 2 + 1], sFrustum.mClipPlanes[i]) <= 0.0f)
308        {
309                // completely inside: children don't need to check against this plane no more
310                node->mPlaneMask^= 1 << i;
311        }
312        else
313        {
314                bIntersect = true;
315        }
316       
317        return true;
318}
319
320
321int     Bvh::IsWithinViewFrustum(BvhNode *node)
322{
323        bool bIntersect = false;
324
325        if (node->GetParent())
326                node->mPlaneMask = node->GetParent()->mPlaneMask;
327
328
329        //for (int i = 0; i < 6; ++ i)
330        //      if (!TestPlane(node, i, bIntersect)) return 0;
331       
332
333        ////////
334        //-- apply frustum culling for the planes [mPreferredPlane - 5]
335
336        for (int i = node->mPreferredPlane; i < 6; ++ i)
337                if (!TestPlane(node, i, bIntersect)) return 0;
338       
339        //////////
340        //-- do the view frustum culling for the planes [0 - m_iPreferredPlane)
341
342        for (int i = 0; i < node->mPreferredPlane; ++ i)
343                if (!TestPlane(node, i, bIntersect)) return 0;
344       
345        return bIntersect ? -1 : 1;
346}
347
348
349void Bvh::InitFrame()
350{
351        // = 0011 1111 which means that at the beginning, all six planes have to frustum culled
352        mRoot->mPlaneMask = 0x3f;
353
354        mCamera->CalcFrustum(sFrustum);
355        sFrustum.CalcNPVertexIndices(sClipPlaneAABBVertexIndices);
356
357        // store near plane
358        sNearPlane = Plane3(mCamera->GetDirection(), mCamera->GetPosition());
359}
360
361
362void Bvh::CalcDistance(BvhNode *node) const
363{
364        node->mDistance = node->GetBox().GetMinVisibleDistance(sNearPlane);
365}
366
367
368void Bvh::RenderBoundingBox(BvhNode *node, RenderState *state)
369{
370        //RenderBoundingBoxImmediate(node->GetBox());
371        static BvhNodeContainer dummy(1);
372        dummy[0] = node;
373        RenderBoundingBoxes(dummy, state);
374}
375
376
377
378int Bvh::RenderBoundingBoxes(const BvhNodeContainer &nodes, RenderState *state)
379{
380        int renderedBoxes = PrepareBoundingBoxesWithDrawArrays(nodes);
381        RenderBoundingBoxesWithDrawArrays(renderedBoxes, state);
382
383        return renderedBoxes;
384}
385
386
387int Bvh::PrepareBoundingBoxesWithDrawArrays(const BvhNodeContainer &nodes)
388{
389        //////
390        //-- for the first time we come here ...
391
392        if (!mIndices)
393        {       // create list of indices
394                CreateIndices();
395        }
396
397        if (mVboId == -1)
398        {       
399                // prepare the vbo
400                PrepareVertices();
401        }
402
403        ///////////////
404
405        int numNodes = 0;
406
407        BvhNodeContainer::const_iterator nit, nit_end = nodes.end();
408
409        for (nit = nodes.begin(); nit != nit_end; ++ nit)
410        {
411                BvhNode *node = *nit;
412
413        const int numIndices = node->mNumTestNodes * sNumIndicesPerBox;
414               
415                // copy indices
416                memcpy(mIndices + numNodes * sNumIndicesPerBox,
417                           mTestIndices + node->mIndicesPtr,
418#if 0 //ALIGN_INDICES
419                           ((numIndices / 32) * 32 + 32) * sizeof(unsigned int));
420#else
421                           numIndices * sizeof(unsigned int));
422#endif
423                numNodes += node->mNumTestNodes;
424        }
425
426        return numNodes;
427}
428
429
430void Bvh::RenderBoundingBoxesWithDrawArrays(int numNodes, RenderState *state)
431{
432        //////
433        //-- Rendering the vbo
434
435        if (state->GetCurrentVboId() != mVboId)
436        {
437                glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
438                // set the vertex pointer to the vertex buffer
439                glVertexPointer(3, GL_FLOAT, 0, (char *)NULL); 
440
441                state->SetCurrentVboId(mVboId);
442        }
443
444        // we do use the last or the first index (they are generate and only used to connect strips)
445        int numElements = numNodes * sNumIndicesPerBox - 1;
446        // don't render first degenerate index
447        glDrawElements(GL_TRIANGLE_STRIP, numElements, GL_UNSIGNED_INT, mIndices + 1);
448}
449
450
451#define ALIGN_INDICES 1
452
453void Bvh::CreateIndices()
454{
455        // collect bvh nodes
456        BvhNodeContainer nodes;
457        CollectNodes(mRoot, nodes);
458
459        cout << "creating new indices" << endl;
460
461        int numMaxIndices = 0;
462
463        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
464
465        for (lit = nodes.begin(); lit != lit_end; ++ lit)
466        {
467                int offset = (*lit)->mNumTestNodes * sNumIndicesPerBox;
468#if ALIGN_INDICES
469                // align with 32
470                offset = (offset / 32) * 32 + 32;
471#endif
472                numMaxIndices += offset;
473        }
474
475
476        cout << "creating global indices buffer" << endl;
477
478        if (mIndices) delete [] mIndices;
479        if (mTestIndices) delete [] mTestIndices;
480
481        // global buffer: create it once so we don't have
482        // to allocate memory from the chunks of the node
483        mIndices = new unsigned int[numMaxIndices];
484
485        // create new index buffer for the individual nodes
486        mTestIndices = new unsigned int[numMaxIndices];
487       
488        mCurrentIndicesPtr = 0;
489
490        for (lit = nodes.begin(); lit != lit_end; ++ lit)
491        {
492                BvhNode *node = *lit;
493               
494                // resize array
495                node->mIndicesPtr = mCurrentIndicesPtr;
496
497                int numIndices = 0;
498
499                // the bounding box of the test nodes are rendered instead of the root node
500                // => store their indices
501                for (int i = 0; i < node->mNumTestNodes; ++ i, numIndices += sNumIndicesPerBox)
502                {
503                        BvhNode *testNode = mTestNodes[node->mTestNodesIdx + i];
504
505                        // add indices to root node
506                        for (int j = 0; j < sNumIndicesPerBox; ++ j)
507                        {
508                                mTestIndices[mCurrentIndicesPtr + numIndices + j] = sIndices[j] + testNode->GetId() * 8;
509                        }
510                }
511
512                // align with 32
513#if ALIGN_INDICES
514                const int offset = (numIndices / 32) * 32 + 32;
515#else
516                const int offset = numIndices;
517#endif
518                mCurrentIndicesPtr += offset;
519        }
520}
521
522
523void Bvh::ComputeIds()
524{
525        // collect all nodes
526        BvhNodeContainer nodes;
527        CollectNodes(mRoot, nodes);
528
529        // assign ids to all nodes of the "regular" hierarchy
530        int i = 0;
531        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
532
533        for (lit = nodes.begin(); lit != lit_end; ++ lit, ++ i)
534        {
535                (*lit)->SetId(i);
536        }
537}
538
539
540void Bvh::PrepareVertices()
541{
542        // collect all nodes
543        BvhNodeContainer nodes;
544
545        nodes.reserve(GetNumNodes());
546        CollectNodes(mRoot, nodes);
547
548        const unsigned int bufferSize = 8 * (int)nodes.size();
549        mVertices = new Vector3[bufferSize];
550       
551        int i = 0;
552       
553        // store bounding box vertices
554        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
555
556        for (lit = nodes.begin(); lit != lit_end; ++ lit, i += 8)
557        {
558                BvhNode *node = *lit;
559
560                for (int j = 0; j < 8; ++ j)
561                        ((Vector3 *)mVertices)[node->GetId() * 8 + j] = node->GetBox().GetVertex(j);
562        }
563
564        glGenBuffersARB(1, &mVboId);
565        glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
566        glVertexPointer(3, GL_FLOAT, 0, (char *)NULL);
567       
568        glBufferDataARB(GL_ARRAY_BUFFER_ARB,
569                            bufferSize * sizeof(Vector3),
570                            mVertices,
571                                        GL_STATIC_DRAW_ARB);
572
573        //glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
574
575        // data handled by graphics driver from now on
576        DEL_PTR(mVertices);
577
578        cout << "***** created vbos for tighter bounds *********" << endl;
579}
580
581
582void Bvh::SetMaxDepthForTestingChildren(int maxDepth)
583{
584        if (maxDepth != mMaxDepthForTestingChildren)
585        {
586                mMaxDepthForTestingChildren = maxDepth;
587                RecomputeBounds();
588        }
589}
590
591
592void Bvh::SetAreaRatioThresholdForTestingChildren(float ratio)
593{
594        if (ratio != mAreaRatioThreshold)
595        {
596                mAreaRatioThreshold = ratio;
597                RecomputeBounds();
598        }
599}
600
601
602void Bvh::RecomputeBounds()
603{
604        // clear old list
605        mTestNodes.clear();
606
607        // collect all nodes
608        BvhNodeContainer nodes;
609        CollectNodes(mRoot, nodes);
610
611        cout << "recomputing bounds, children will be tested in depth " << mMaxDepthForTestingChildren << endl;
612
613        int success = 0;
614        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
615
616        for (lit = nodes.begin(); lit != lit_end; ++ lit)
617        {
618                BvhNode *node = *lit;
619
620                // recreate list of nodes that will be tested as a proxy ...
621                if (CreateNodeRenderList(node))
622                        ++ success;
623        }
624
625        float p = 100.0f * (float)success / nodes.size();
626        cout << "created tighter bounds for " << p << " percent of the nodes" << endl;
627
628        // recreate indices used for indirect mode rendering
629        if (mIndices)
630                CreateIndices();
631}
632
633       
634bool Bvh::CreateNodeRenderList(BvhNode *node)
635{
636        BvhNodeContainer children;
637
638        // collect nodes that will be tested instead of the leaf node
639        // in order to get a tighter bounding box test
640        CollectNodes(node, children, mMaxDepthForTestingChildren);
641       
642
643        // using the tighter bounds is not feasable in case
644        // that the tighter bounds represent nearly the same projected area
645        // as the old bounding box. Find this out using either volume or area
646        // heuristics
647
648        float vol = 0;
649        float area = 0;
650
651        BvhNodeContainer::const_iterator cit;
652
653        for (cit = children.begin(); cit != children.end(); ++ cit)
654                area += (*cit)->GetBox().SurfaceArea();
655
656        const float areaRatio = area / node->GetBox().SurfaceArea();
657       
658        bool success;
659
660        if (areaRatio < mAreaRatioThreshold)
661                success = true;
662        else
663        {
664                // hack: only store node itself
665                children.clear();
666                children.push_back(node);
667
668                success = false;
669        }
670
671        // the new test nodes are added at the end of the vector
672        node->mTestNodesIdx = (int)mTestNodes.size();
673
674        // use the found nodes as nodes during the occlusion tests
675        for (cit = children.begin(); cit != children.end(); ++ cit)
676        {
677                BvhNode *child = *cit;
678                mTestNodes.push_back(child);
679        }
680
681        node->mNumTestNodes = (int)children.size();
682
683        return success;
684}
685
686
687void Bvh::ResetNodeClassifications()
688{
689        BvhNodeContainer nodes;
690
691        nodes.reserve(GetNumNodes());
692        CollectNodes(mRoot, nodes);
693
694        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
695
696        for (lit = nodes.begin(); lit != lit_end; ++ lit)
697        {
698                (*lit)->ResetVisibility();
699        }
700}
701
702
703void Bvh::ComputeBvhStats()
704{
705        std::stack<BvhNode *> nodeStack;
706        nodeStack.push(mRoot);
707
708        while (!nodeStack.empty())
709        {
710                BvhNode *node = nodeStack.top();
711                nodeStack.pop();
712
713                if (node->IsVirtualLeaf())
714                {
715                        BvhLeaf *leaf = static_cast<BvhLeaf *>(node);
716
717                        mBvhStats.mTriangles += CountTriangles(leaf);
718                        mBvhStats.mLeafSA += leaf->mBox.SurfaceArea();
719                        mBvhStats.mLeafVol += leaf->mBox.GetVolume();
720                }
721                else
722                {
723                        mBvhStats.mInteriorSA += node->mBox.SurfaceArea();
724                        mBvhStats.mInteriorVol += node->mBox.GetVolume();
725
726                        BvhInterior *interior = static_cast<BvhInterior *>(node);
727                       
728                        nodeStack.push(interior->mBack);
729                        nodeStack.push(interior->mFront);
730                }
731        }
732
733        mBvhStats.mGeometryRatio = mGeometrySize / (float)GetNumLeaves();
734        mBvhStats.mTriangleRatio = mBvhStats.mTriangles / (float)GetNumLeaves();
735}
736
737
738void Bvh::PrintBvhStats() const
739{
740        cout << "bvh stats:" << endl;
741        cout << "interiorNodesSA = " << mBvhStats.mInteriorSA / mRoot->mBox.SurfaceArea() << endl;
742        cout << "leafNodesSA = " << mBvhStats.mLeafSA / mRoot->mBox.SurfaceArea() << endl;
743        cout << "interiorNodesVolume = " << mBvhStats.mInteriorVol / mRoot->mBox.GetVolume() << endl;
744        cout << "leafNodesVolume = " << mBvhStats.mLeafVol / mRoot->mBox.GetVolume() << endl;
745
746        cout << "geometry per leaf: " <<  mBvhStats.mGeometryRatio << endl;
747        cout << "triangles per leaf: " <<  mBvhStats.mTriangleRatio << endl;
748}
749
750
751int Bvh::CountTriangles(BvhNode *node) const
752{
753        int numTriangles = 0;
754
755        for (int i = node->mFirst; i <= node->mLast; ++ i)
756        {
757                numTriangles += mGeometry[i]->GetGeometry()->GetNumTriangles();
758        }
759
760        return numTriangles;
761}
762
763
764float Bvh::GetArea(BvhNode *node) const
765{
766        return node->mArea;
767}
768
769
770void Bvh::UpdateNumLeaves(BvhNode *node) const
771{
772        if (node->IsLeaf())
773        {
774                node->mNumLeaves = 1;
775        }
776        else
777        {
778                BvhNode *f = static_cast<BvhInterior *>(node)->GetFront();
779                BvhNode *b = static_cast<BvhInterior *>(node)->GetBack();
780
781                UpdateNumLeaves(f);
782                UpdateNumLeaves(b);
783
784                node->mNumLeaves = f->mNumLeaves + b->mNumLeaves;
785        }
786}
787
788
789void Bvh::CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves)
790{
791        stack<BvhNode *> tStack;
792        tStack.push(node);
793
794        while (!tStack.empty())
795        {
796                BvhNode *node = tStack.top();
797                tStack.pop();
798
799                if (node->mIsVirtualLeaf)
800                {
801                        leaves.push_back(node);
802                }
803                else if (!node->IsLeaf())
804                {
805                        BvhInterior *interior = static_cast<BvhInterior *>(node);
806
807                        tStack.push(interior->mFront);
808                        tStack.push(interior->mBack);
809                }
810        }
811}
812
813
814void Bvh::SetVirtualLeaves(int numTriangles)
815{
816        // first invalidate old leaves
817        BvhNodeContainer leaves;
818
819        CollectVirtualLeaves(mRoot, leaves);
820
821        BvhNodeContainer::const_iterator bit, bit_end = leaves.end();
822
823        for (bit = leaves.begin(); bit != bit_end; ++ bit)
824        {
825                (*bit)->mIsVirtualLeaf = false;
826        }
827
828        mNumVirtualNodes = 0;
829
830        // assign new virtual leaves based on specified number of triangles per leaf
831        std::stack<BvhNode *> nodeStack;
832        nodeStack.push(mRoot);
833
834        while (!nodeStack.empty())
835        {
836                BvhNode *node = nodeStack.top();
837                nodeStack.pop();
838
839                ++ mNumVirtualNodes;
840
841                if (node->IsLeaf())
842                {
843                        BvhLeaf *leaf = static_cast<BvhLeaf *>(node);
844                        leaf->mIsVirtualLeaf = true;
845                }
846                else
847                {
848                        BvhInterior *interior = static_cast<BvhInterior *>(node);
849
850                        BvhNode *f = interior->mFront;
851                        BvhNode *b = interior->mBack;
852
853                        if (node->mIsMaxDepthForVirtualLeaf || (CountTriangles(node) <= numTriangles))
854                        {
855                                 node->mIsVirtualLeaf = true;
856                        }
857                        else
858                        {
859                                nodeStack.push(interior->mBack);
860                                nodeStack.push(interior->mFront);
861                        }
862                }
863        }
864}
865
866
867void Bvh::PostProcess()
868{
869        std::stack<BvhNode *> nodeStack;
870        nodeStack.push(mRoot);
871
872        while (!nodeStack.empty())
873        {
874                BvhNode *node = nodeStack.top();
875                nodeStack.pop();
876
877                if (node->IsLeaf())
878                {
879                        node->mIsMaxDepthForVirtualLeaf = true;
880                }
881                else
882                {
883                        BvhInterior *interior = static_cast<BvhInterior *>(node);
884
885                        BvhNode *f = interior->mFront;
886                        BvhNode *b = interior->mBack;
887
888                        // point reached where we cannot subdivide further on object level
889                        if ((f->mFirst == b->mFirst) && (f->mLast == b->mLast))
890                        {
891                                node->mIsMaxDepthForVirtualLeaf = true;
892                        }
893                        else
894                        {
895                                nodeStack.push(f);
896                                nodeStack.push(b);
897                        }
898                }
899        }
900}
901
902
903void Bvh::RenderBoundingBoxImmediate(const AxisAlignedBox3 &box)
904{
905        const Vector3 l = box.Min();
906        const Vector3 u = box.Max();
907
908        glBegin(GL_TRIANGLE_STRIP);
909        {
910                ///////////
911                //-- render AABB as triangle strips
912
913                glVertex3f(l.x, l.y, u.z);
914                glVertex3f(u.x, l.y, u.z);
915                glVertex3f(l.x, u.y, u.z);
916                glVertex3f(u.x, u.y, u.z);
917                glVertex3f(l.x, u.y, l.z);
918                glVertex3f(u.x, u.y, l.z);
919                glVertex3f(l.x, l.y, l.z);
920                glVertex3f(u.x, l.y, l.z);
921
922                glPrimitiveRestartNV();
923
924                //-- render second half of AABB
925                glVertex3f(l.x, u.y, u.z);
926                glVertex3f(l.x, u.y, l.z);
927                glVertex3f(l.x, l.y, u.z);
928                glVertex3f(l.x, l.y, l.z);
929                glVertex3f(u.x, l.y, u.z);
930                glVertex3f(u.x, l.y, l.z);
931                glVertex3f(u.x, u.y, u.z);
932                glVertex3f(u.x, u.y, l.z);
933        }
934        glEnd();
935}
936
937}
Note: See TracBrowser for help on using the repository browser.