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

Revision 2802, 22.1 KB checked in by mattausch, 17 years ago (diff)

worked on renderqueue

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