source: GTP/trunk/App/Demos/Vis/CHC_revisited/Bvh.cpp @ 2764

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