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

Revision 2894, 22.2 KB checked in by mattausch, 16 years ago (diff)

shadow mapping almost working (but ulgy!!)

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