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

Revision 2790, 22.0 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::RenderBounds(BvhNode *node, RenderState *state, bool useTightBounds)
369{
370        // if not using tight bounds, rendering boxes in immediate mode
371        // is preferable to vertex arrays (less setup time)
372        if (!useTightBounds)
373        {
374                RenderBoundingBoxImmediate(node->GetBox());
375        }
376        else
377        {
378                static BvhNodeContainer dummy(1);
379                dummy[0] = node;
380                RenderBounds(dummy, state, useTightBounds);
381        }
382}
383
384
385int Bvh::RenderBounds(const BvhNodeContainer &nodes,
386                                          RenderState *state,
387                                          bool useTightBounds)
388{
389        // if not using tight bounds, rendering boxes in immediate mode
390        // is preferable to vertex arrays (less setup time)
391
392        int renderedBoxes;
393
394        if (!useTightBounds)
395        {
396                BvhNodeContainer::const_iterator nit, nit_end = nodes.end();
397                       
398                for (nit = nodes.begin(); nit != nit_end; ++ nit)
399                {
400                        RenderBoundingBoxImmediate((*nit)->GetBox());
401                }
402
403                renderedBoxes = (int)nodes.size();
404        }
405        else
406        {
407                renderedBoxes = PrepareBoundsWithDrawArrays(nodes);
408                RenderBoundsWithDrawArrays(renderedBoxes, state);
409        }
410
411        return renderedBoxes;
412}
413
414
415int Bvh::PrepareBoundsWithDrawArrays(const BvhNodeContainer &nodes)
416{
417        //////
418        //-- for the first time we come here ...
419
420        if (!mIndices)
421        {       // create list of indices
422                CreateIndices();
423        }
424
425        if (mVboId == -1)
426        {       
427                // prepare the vbo
428                PrepareVertices();
429        }
430
431        ///////////////
432
433        int numNodes = 0;
434
435        BvhNodeContainer::const_iterator nit, nit_end = nodes.end();
436
437        for (nit = nodes.begin(); nit != nit_end; ++ nit)
438        {
439                BvhNode *node = *nit;
440
441        const int numIndices = node->mNumTestNodes * sNumIndicesPerBox;
442               
443                // copy indices
444                memcpy(mIndices + numNodes * sNumIndicesPerBox,
445                           mTestIndices + node->mIndicesPtr,
446#if 0 //ALIGN_INDICES
447                           ((numIndices / 32) * 32 + 32) * sizeof(unsigned int));
448#else
449                           numIndices * sizeof(unsigned int));
450#endif
451                numNodes += node->mNumTestNodes;
452        }
453
454        return numNodes;
455}
456
457
458void Bvh::RenderBoundsWithDrawArrays(int numNodes, RenderState *state)
459{
460        //////
461        //-- Rendering the vbo
462
463        if (state->GetCurrentVboId() != mVboId)
464        {
465                glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
466                // set the vertex pointer to the vertex buffer
467                glVertexPointer(3, GL_FLOAT, 0, (char *)NULL); 
468
469                state->SetCurrentVboId(mVboId);
470        }
471
472        // we do use the last or the first index (they are generate and only used to connect strips)
473        int numElements = numNodes * sNumIndicesPerBox - 1;
474        // don't render first degenerate index
475        glDrawElements(GL_TRIANGLE_STRIP, numElements, GL_UNSIGNED_INT, mIndices + 1);
476}
477
478
479#define ALIGN_INDICES 1
480
481void Bvh::CreateIndices()
482{
483        // collect bvh nodes
484        BvhNodeContainer nodes;
485        CollectNodes(mRoot, nodes);
486
487        cout << "creating new indices" << endl;
488
489        int numMaxIndices = 0;
490
491        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
492
493        for (lit = nodes.begin(); lit != lit_end; ++ lit)
494        {
495                int offset = (*lit)->mNumTestNodes * sNumIndicesPerBox;
496#if ALIGN_INDICES
497                // align with 32
498                offset = (offset / 32) * 32 + 32;
499#endif
500                numMaxIndices += offset;
501        }
502
503
504        cout << "creating global indices buffer" << endl;
505
506        if (mIndices) delete [] mIndices;
507        if (mTestIndices) delete [] mTestIndices;
508
509        // global buffer: create it once so we don't have
510        // to allocate memory from the chunks of the node
511        mIndices = new unsigned int[numMaxIndices];
512
513        // create new index buffer for the individual nodes
514        mTestIndices = new unsigned int[numMaxIndices];
515       
516        mCurrentIndicesPtr = 0;
517
518        for (lit = nodes.begin(); lit != lit_end; ++ lit)
519        {
520                BvhNode *node = *lit;
521               
522                // resize array
523                node->mIndicesPtr = mCurrentIndicesPtr;
524
525                int numIndices = 0;
526
527                // the bounding box of the test nodes are rendered instead of the root node
528                // => store their indices
529                for (int i = 0; i < node->mNumTestNodes; ++ i, numIndices += sNumIndicesPerBox)
530                {
531                        BvhNode *testNode = mTestNodes[node->mTestNodesIdx + i];
532
533                        // add indices to root node
534                        for (int j = 0; j < sNumIndicesPerBox; ++ j)
535                        {
536                                mTestIndices[mCurrentIndicesPtr + numIndices + j] = sIndices[j] + testNode->GetId() * 8;
537                        }
538                }
539
540                // align with 32
541#if ALIGN_INDICES
542                const int offset = (numIndices / 32) * 32 + 32;
543#else
544                const int offset = numIndices;
545#endif
546                mCurrentIndicesPtr += offset;
547        }
548}
549
550
551void Bvh::ComputeIds()
552{
553        // collect all nodes
554        BvhNodeContainer nodes;
555        CollectNodes(mRoot, nodes);
556
557        // assign ids to all nodes of the "regular" hierarchy
558        int i = 0;
559        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
560
561        for (lit = nodes.begin(); lit != lit_end; ++ lit, ++ i)
562        {
563                (*lit)->SetId(i);
564        }
565}
566
567
568void Bvh::PrepareVertices()
569{
570        // collect all nodes
571        BvhNodeContainer nodes;
572
573        nodes.reserve(GetNumNodes());
574        CollectNodes(mRoot, nodes);
575
576        const unsigned int bufferSize = 8 * (int)nodes.size();
577        mVertices = new Vector3[bufferSize];
578       
579        int i = 0;
580       
581        // store bounding box vertices
582        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
583
584        for (lit = nodes.begin(); lit != lit_end; ++ lit, i += 8)
585        {
586                BvhNode *node = *lit;
587
588                for (int j = 0; j < 8; ++ j)
589                        ((Vector3 *)mVertices)[node->GetId() * 8 + j] = node->GetBox().GetVertex(j);
590        }
591
592        glGenBuffersARB(1, &mVboId);
593        glBindBufferARB(GL_ARRAY_BUFFER_ARB, mVboId);
594        glVertexPointer(3, GL_FLOAT, 0, (char *)NULL);
595       
596        glBufferDataARB(GL_ARRAY_BUFFER_ARB,
597                            bufferSize * sizeof(Vector3),
598                            mVertices,
599                                        GL_STATIC_DRAW_ARB);
600
601        //glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
602
603        // data handled by graphics driver from now on
604        DEL_PTR(mVertices);
605
606        cout << "***** created vbos for tighter bounds *********" << endl;
607}
608
609
610void Bvh::SetMaxDepthForTestingChildren(int maxDepth)
611{
612        if (maxDepth != mMaxDepthForTestingChildren)
613        {
614                mMaxDepthForTestingChildren = maxDepth;
615                RecomputeBounds();
616        }
617}
618
619
620void Bvh::SetAreaRatioThresholdForTestingChildren(float ratio)
621{
622        if (ratio != mAreaRatioThreshold)
623        {
624                mAreaRatioThreshold = ratio;
625                RecomputeBounds();
626        }
627}
628
629
630void Bvh::RecomputeBounds()
631{
632        // clear old list
633        mTestNodes.clear();
634
635        // collect all nodes
636        BvhNodeContainer nodes;
637        CollectNodes(mRoot, nodes);
638
639        cout << "recomputing bounds, children will be tested in depth " << mMaxDepthForTestingChildren << endl;
640
641        int success = 0;
642        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
643
644        for (lit = nodes.begin(); lit != lit_end; ++ lit)
645        {
646                BvhNode *node = *lit;
647
648                // recreate list of nodes that will be tested as a proxy ...
649                if (CreateNodeRenderList(node))
650                        ++ success;
651        }
652
653        float p = 100.0f * (float)success / nodes.size();
654        cout << "created tighter bounds for " << p << " percent of the nodes" << endl;
655
656        // recreate indices used for indirect mode rendering
657        if (mIndices)
658                CreateIndices();
659}
660
661       
662bool Bvh::CreateNodeRenderList(BvhNode *node)
663{
664        BvhNodeContainer children;
665
666        // collect nodes that will be tested instead of the leaf node
667        // in order to get a tighter bounding box test
668        CollectNodes(node, children, mMaxDepthForTestingChildren);
669       
670
671        // using the tighter bounds is not feasable in case
672        // that the tighter bounds represent nearly the same projected area
673        // as the old bounding box. Find this out using either volume or area
674        // heuristics
675
676        float vol = 0;
677        float area = 0;
678
679        BvhNodeContainer::const_iterator cit;
680
681        for (cit = children.begin(); cit != children.end(); ++ cit)
682                area += (*cit)->GetBox().SurfaceArea();
683
684        const float areaRatio = area / node->GetBox().SurfaceArea();
685       
686        bool success;
687
688        if (areaRatio < mAreaRatioThreshold)
689                success = true;
690        else
691        {
692                // hack: only store node itself
693                children.clear();
694                children.push_back(node);
695
696                success = false;
697        }
698
699        // the new test nodes are added at the end of the vector
700        node->mTestNodesIdx = (int)mTestNodes.size();
701
702        // use the found nodes as nodes during the occlusion tests
703        for (cit = children.begin(); cit != children.end(); ++ cit)
704        {
705                BvhNode *child = *cit;
706                mTestNodes.push_back(child);
707        }
708
709        node->mNumTestNodes = (int)children.size();
710
711        return success;
712}
713
714
715void Bvh::ResetNodeClassifications()
716{
717        BvhNodeContainer nodes;
718
719        nodes.reserve(GetNumNodes());
720        CollectNodes(mRoot, nodes);
721
722        BvhNodeContainer::const_iterator lit, lit_end = nodes.end();
723
724        for (lit = nodes.begin(); lit != lit_end; ++ lit)
725        {
726                (*lit)->ResetVisibility();
727        }
728}
729
730
731void Bvh::ComputeBvhStats()
732{
733        std::stack<BvhNode *> nodeStack;
734        nodeStack.push(mRoot);
735
736        int numVirtualLeaves = 0;
737
738        while (!nodeStack.empty())
739        {
740                BvhNode *node = nodeStack.top();
741                nodeStack.pop();
742
743                if (node->IsVirtualLeaf())
744                {
745                        ++ numVirtualLeaves;
746
747                        BvhLeaf *leaf = static_cast<BvhLeaf *>(node);
748
749                        mBvhStats.mTriangles += CountTriangles(leaf);
750                        mBvhStats.mLeafSA += leaf->mBox.SurfaceArea();
751                        mBvhStats.mLeafVol += leaf->mBox.GetVolume();
752                }
753                else
754                {
755                        mBvhStats.mInteriorSA += node->mBox.SurfaceArea();
756                        mBvhStats.mInteriorVol += node->mBox.GetVolume();
757
758                        BvhInterior *interior = static_cast<BvhInterior *>(node);
759                       
760                        nodeStack.push(interior->mBack);
761                        nodeStack.push(interior->mFront);
762                }
763        }
764
765        mBvhStats.mGeometryRatio = mGeometrySize / (float)numVirtualLeaves;
766        mBvhStats.mTriangleRatio = mBvhStats.mTriangles / (float)numVirtualLeaves;
767}
768
769
770void Bvh::PrintBvhStats() const
771{
772        cout << "bvh stats:" << endl;
773        cout << "interiorNodesSA = " << mBvhStats.mInteriorSA / mRoot->mBox.SurfaceArea() << endl;
774        cout << "leafNodesSA = " << mBvhStats.mLeafSA / mRoot->mBox.SurfaceArea() << endl;
775        cout << "interiorNodesVolume = " << mBvhStats.mInteriorVol / mRoot->mBox.GetVolume() << endl;
776        cout << "leafNodesVolume = " << mBvhStats.mLeafVol / mRoot->mBox.GetVolume() << endl;
777
778        cout << "geometry per leaf: " <<  mBvhStats.mGeometryRatio << endl;
779        cout << "triangles per leaf: " <<  mBvhStats.mTriangleRatio << endl;
780}
781
782
783int Bvh::CountTriangles(BvhNode *node) const
784{
785        int numTriangles = 0;
786
787        for (int i = node->mFirst; i <= node->mLast; ++ i)
788        {
789                numTriangles += mGeometry[i]->GetGeometry()->GetNumTriangles();
790        }
791
792        return numTriangles;
793}
794
795
796float Bvh::GetArea(BvhNode *node) const
797{
798        return node->mArea;
799}
800
801
802void Bvh::UpdateNumLeaves(BvhNode *node) const
803{
804        if (node->IsLeaf())
805        {
806                node->mNumLeaves = 1;
807        }
808        else
809        {
810                BvhNode *f = static_cast<BvhInterior *>(node)->GetFront();
811                BvhNode *b = static_cast<BvhInterior *>(node)->GetBack();
812
813                UpdateNumLeaves(f);
814                UpdateNumLeaves(b);
815
816                node->mNumLeaves = f->mNumLeaves + b->mNumLeaves;
817        }
818}
819
820
821void Bvh::CollectVirtualLeaves(BvhNode *node, BvhNodeContainer &leaves)
822{
823        stack<BvhNode *> tStack;
824        tStack.push(node);
825
826        while (!tStack.empty())
827        {
828                BvhNode *node = tStack.top();
829                tStack.pop();
830
831                if (node->mIsVirtualLeaf)
832                {
833                        leaves.push_back(node);
834                }
835                else if (!node->IsLeaf())
836                {
837                        BvhInterior *interior = static_cast<BvhInterior *>(node);
838
839                        tStack.push(interior->mFront);
840                        tStack.push(interior->mBack);
841                }
842        }
843}
844
845
846void Bvh::SetVirtualLeaves(int numTriangles)
847{
848        // first invalidate old leaves
849        BvhNodeContainer leaves;
850
851        CollectVirtualLeaves(mRoot, leaves);
852
853        BvhNodeContainer::const_iterator bit, bit_end = leaves.end();
854
855        for (bit = leaves.begin(); bit != bit_end; ++ bit)
856        {
857                (*bit)->mIsVirtualLeaf = false;
858        }
859
860        mNumVirtualNodes = 0;
861
862        // assign new virtual leaves based on specified number of triangles per leaf
863        std::stack<BvhNode *> nodeStack;
864        nodeStack.push(mRoot);
865
866        while (!nodeStack.empty())
867        {
868                BvhNode *node = nodeStack.top();
869                nodeStack.pop();
870
871                ++ mNumVirtualNodes;
872
873                if (node->IsLeaf())
874                {
875                        BvhLeaf *leaf = static_cast<BvhLeaf *>(node);
876                        leaf->mIsVirtualLeaf = true;
877                }
878                else
879                {
880                        BvhInterior *interior = static_cast<BvhInterior *>(node);
881
882                        BvhNode *f = interior->mFront;
883                        BvhNode *b = interior->mBack;
884
885                        if (node->mIsMaxDepthForVirtualLeaf || (CountTriangles(node) <= numTriangles))
886                        {
887                                 node->mIsVirtualLeaf = true;
888                        }
889                        else
890                        {
891                                nodeStack.push(interior->mBack);
892                                nodeStack.push(interior->mFront);
893                        }
894                }
895        }
896}
897
898
899void Bvh::PostProcess()
900{
901        std::stack<BvhNode *> nodeStack;
902        nodeStack.push(mRoot);
903
904        while (!nodeStack.empty())
905        {
906                BvhNode *node = nodeStack.top();
907                nodeStack.pop();
908
909                if (node->IsLeaf())
910                {
911                        node->mIsMaxDepthForVirtualLeaf = true;
912                }
913                else
914                {
915                        BvhInterior *interior = static_cast<BvhInterior *>(node);
916
917                        BvhNode *f = interior->mFront;
918                        BvhNode *b = interior->mBack;
919
920                        // point reached where we cannot subdivide further on object level
921                        if ((f->mFirst == b->mFirst) && (f->mLast == b->mLast))
922                        {
923                                node->mIsMaxDepthForVirtualLeaf = true;
924                        }
925                        else
926                        {
927                                nodeStack.push(f);
928                                nodeStack.push(b);
929                        }
930                }
931        }
932}
933
934
935void Bvh::RenderBoundingBoxImmediate(const AxisAlignedBox3 &box)
936{
937        const Vector3 l = box.Min();
938        const Vector3 u = box.Max();
939
940        glBegin(GL_TRIANGLE_STRIP);
941        {
942                ///////////
943                //-- render AABB as triangle strips
944
945                glVertex3f(l.x, l.y, u.z);
946                glVertex3f(u.x, l.y, u.z);
947                glVertex3f(l.x, u.y, u.z);
948                glVertex3f(u.x, u.y, u.z);
949                glVertex3f(l.x, u.y, l.z);
950                glVertex3f(u.x, u.y, l.z);
951                glVertex3f(l.x, l.y, l.z);
952                glVertex3f(u.x, l.y, l.z);
953
954                glPrimitiveRestartNV();
955
956                //-- render second half of AABB
957                glVertex3f(l.x, u.y, u.z);
958                glVertex3f(l.x, u.y, l.z);
959                glVertex3f(l.x, l.y, u.z);
960                glVertex3f(l.x, l.y, l.z);
961                glVertex3f(u.x, l.y, u.z);
962                glVertex3f(u.x, l.y, l.z);
963                glVertex3f(u.x, u.y, u.z);
964                glVertex3f(u.x, u.y, l.z);
965        }
966        glEnd();
967}
968
969
970
971
972static void RenderBoxForViz(const AxisAlignedBox3 &box)
973{
974        glBegin(GL_LINE_LOOP);
975        glVertex3d(box.Min().x, box.Max().y, box.Min().z);
976        glVertex3d(box.Max().x, box.Max().y, box.Min().z);
977        glVertex3d(box.Max().x, box.Min().y, box.Min().z);
978        glVertex3d(box.Min().x, box.Min().y, box.Min().z);
979        glEnd();
980
981        glBegin(GL_LINE_LOOP);
982        glVertex3d(box.Min().x, box.Min().y, box.Max().z);
983        glVertex3d(box.Max().x, box.Min().y, box.Max().z);
984        glVertex3d(box.Max().x, box.Max().y, box.Max().z);
985        glVertex3d(box.Min().x, box.Max().y, box.Max().z);
986        glEnd();
987
988        glBegin(GL_LINE_LOOP);
989        glVertex3d(box.Max().x, box.Min().y, box.Min().z);
990        glVertex3d(box.Max().x, box.Min().y, box.Max().z);
991        glVertex3d(box.Max().x, box.Max().y, box.Max().z);
992        glVertex3d(box.Max().x, box.Max().y, box.Min().z);
993        glEnd();
994
995        glBegin(GL_LINE_LOOP);
996        glVertex3d(box.Min().x, box.Min().y, box.Min().z);
997        glVertex3d(box.Min().x, box.Min().y, box.Max().z);
998        glVertex3d(box.Min().x, box.Max().y, box.Max().z);
999        glVertex3d(box.Min().x, box.Max().y, box.Min().z);
1000        glEnd();
1001
1002        glBegin(GL_LINE_LOOP);
1003        glVertex3d(box.Min().x, box.Min().y, box.Min().z);
1004        glVertex3d(box.Max().x, box.Min().y, box.Min().z);
1005        glVertex3d(box.Max().x, box.Min().y, box.Max().z);
1006        glVertex3d(box.Min().x, box.Min().y, box.Max().z);
1007        glEnd();
1008
1009        glBegin(GL_LINE_LOOP);
1010        glVertex3d(box.Min().x, box.Max().y, box.Min().z);
1011        glVertex3d(box.Max().x, box.Max().y, box.Min().z);
1012        glVertex3d(box.Max().x, box.Max().y, box.Max().z);
1013        glVertex3d(box.Min().x, box.Max().y, box.Max().z);
1014
1015        glEnd();
1016}
1017
1018
1019void Bvh::RenderBoundsForViz(BvhNode *node, bool useTightBounds)
1020{
1021        glDisable(GL_TEXTURE_2D);
1022        glDisable(GL_LIGHTING);
1023        glColor3f(1, 1, 1);
1024       
1025        if (!useTightBounds)
1026        {
1027                RenderBoxForViz(node->GetBox());
1028        }
1029        else
1030        {
1031                for (int i = 0; i < node->mNumTestNodes; ++ i)
1032                {
1033                        RenderBoxForViz(mTestNodes[node->mTestNodesIdx + i]->GetBox());
1034                }
1035        }
1036
1037        glEnable(GL_LIGHTING);
1038        glEnable(GL_TEXTURE_2D);
1039}
1040
1041
1042
1043}
Note: See TracBrowser for help on using the repository browser.