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

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