source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp @ 261

Revision 261, 21.5 KB checked in by mattausch, 19 years ago (diff)

added viewcell loader

Line 
1#include "Plane3.h"
2#include "ViewCellBsp.h"
3#include "Mesh.h"
4#include "common.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "Polygon3.h"
8#include "Ray.h"
9#include "AxisAlignedBox3.h"
10#include <stack>
11#include <time.h>
12#include <iomanip>
13
14#define INITIAL_COST 999999// unreachable high initial cost for heuristic evaluation
15
16int BspTree::sTermMaxPolygons = 10;
17int BspTree::sTermMaxDepth = 20;
18int BspTree::sSplitPlaneStrategy = NEXT_POLYGON;
19int BspTree::sMaxCandidates = 10;
20
21/****************************************************************/
22/*                  class BspNode implementation                */
23/****************************************************************/
24
25BspNode::BspNode(): mParent(NULL)
26{}
27
28BspNode::BspNode(BspInterior *parent): mParent(parent)
29{}
30
31
32bool BspNode::IsRoot() const
33{
34        return mParent == NULL;
35}
36
37BspInterior *BspNode::GetParent()
38{
39        return mParent;
40}
41
42void BspNode::SetParent(BspInterior *parent)
43{
44        mParent = parent;
45}
46
47PolygonContainer *BspNode::GetPolygons()
48{
49        return &mPolygons;
50}
51
52/****************************************************************/
53/*              class BspInterior implementation                */
54/****************************************************************/
55
56
57BspInterior::BspInterior(Plane3 plane): mPlane(plane)
58{}
59
60bool BspInterior::IsLeaf() const
61{
62        return false;
63}
64
65BspNode *BspInterior::GetBack()
66{
67        return mBack;
68}
69
70BspNode *BspInterior::GetFront()
71{
72        return mFront;
73}
74
75Plane3 *BspInterior::GetPlane()
76{
77        return &mPlane;
78}
79
80void BspInterior::ReplaceChildLink(BspNode *oldChild, BspNode *newChild)
81{
82        if (mBack == oldChild)
83        {
84                mBack = newChild;
85        }
86    else
87        {
88                mFront = newChild;
89        }
90}
91
92void BspInterior::SetupChildLinks(BspNode *b, BspNode *f)
93{
94    mBack = b;
95    mFront = f;
96}
97
98void BspInterior::SplitPolygons(PolygonContainer *polys,
99                                                                PolygonContainer *frontPolys,
100                                                                PolygonContainer *backPolys,
101                                                                int &splits, bool storePolys)
102{
103        while (!polys->empty())
104        {
105                Polygon3 *poly = polys->back();
106                polys->pop_back();
107
108                // test if split is neccessary
109                int result = poly->ClassifyPlane(mPlane);
110
111                Polygon3 *front_piece = NULL;
112                Polygon3 *back_piece = NULL;
113
114                switch (result)
115                {
116                        case Polygon3::COINCIDENT:
117                                // same sides => discard
118                                if (DotProd(poly->GetSupportingPlane().mNormal, mPlane.mNormal) > 0)
119                                {
120                                        if (storePolys)
121                                                mPolygons.push_back(poly);
122                                        else
123                                                DEL_PTR(poly);
124                                }
125                                else
126                                        backPolys->push_back(poly);
127                                break; // TODO: compare normals
128                        case Polygon3::FRONT_SIDE:
129                                frontPolys->push_back(poly);
130                                break;
131                        case Polygon3::BACK_SIDE:
132                                backPolys->push_back(poly);
133                                break;
134                        case Polygon3::SPLIT:
135                                front_piece = new Polygon3();
136                                back_piece = new Polygon3();
137
138                                //-- split polygon
139                                poly->Split(&mPlane, front_piece, back_piece, splits);
140
141                                frontPolys->push_back(front_piece);
142                                backPolys->push_back(back_piece);
143                               
144                                if (storePolys)
145                                        mPolygons.push_back(poly);
146                                else
147                                        DEL_PTR(poly);
148#ifdef _DEBUG
149                                Debug << "split " << poly << endl << front << endl << back << endl;
150#endif
151                                break;
152                        default:
153                Debug << "SHOULD NEVER COME HERE\n";
154                                break;
155                }
156        }
157
158        // contains nothing
159        delete polys;
160}
161
162/****************************************************************/
163/*                  class BspLeaf implementation                */
164/****************************************************************/
165
166BspLeaf::BspLeaf(ViewCell *viewCell): mViewCell(viewCell)
167{
168}
169
170ViewCell *BspLeaf::GetViewCell()
171{
172        return mViewCell;
173}
174
175void BspLeaf::SetViewCell(ViewCell *viewCell)
176{
177        mViewCell = viewCell;
178}
179
180bool BspLeaf::IsLeaf() const
181{
182        return true;
183}
184
185void BspLeaf::AddPolygons(PolygonContainer *polys)
186{
187        while (!polys->empty())
188        {
189                mPolygons.push_back(polys->back());
190                polys->pop_back();
191        }
192}
193/****************************************************************/
194/*                  class BspTree implementation                */
195/****************************************************************/
196
197BspTree::BspTree():
198mTermMaxPolygons(0),
199mTermMaxDepth(0),
200mRoot(NULL),
201mIsIncremential(false),
202mStorePolys(false)
203{
204        Randomize(); // initialise random generator for heuristics
205}
206 
207const BspTreeStatistics &BspTree::GetStatistics() const
208{
209        return mStat;
210}
211
212void BspTreeStatistics::Print(ostream &app) const
213{
214        app << "===== BspTree statistics ===============\n";
215
216        app << setprecision(4);
217
218        app << "#N_RAYS Number of rays )\n"
219                << rays <<endl;
220        app << "#N_DOMAINS  ( Number of query domains )\n"
221                << queryDomains <<endl;
222
223        app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
224
225        app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
226
227        app << "#N_SPLITS ( Number of splits)\n" << splits << "\n";
228
229        app << "#N_RAYREFS ( Number of rayRefs )\n" <<
230        rayRefs << "\n";
231
232        app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
233        rayRefs/(double)rays << "\n";
234
235        app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
236        rayRefs/(double)Leaves() << "\n";
237
238        app << "#N_MAXOBJECTREFS  ( Max number of rayRefs / leaf )\n" <<
239        maxObjectRefs << "\n";
240
241        app << "#N_NONEMPTYRAYREFS  ( Number of rayRefs in nonEmpty leaves / non empty leaf )\n" <<
242        rayRefsNonZeroQuery/(double)(Leaves() - zeroQueryNodes) << "\n";
243
244        app << "#N_LEAFDOMAINREFS  ( Number of query domain Refs / leaf )\n" <<
245        objectRefs/(double)Leaves() << "\n";
246
247        app << "#N_PEMPTYLEAVES  ( Percentage of leaves with zero query domains )\n"<<
248        zeroQueryNodes*100/(double)Leaves()<<endl;
249
250        app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<<
251        maxDepthNodes * 100 / (double)Leaves() << endl;
252
253        app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth <<endl;
254
255        app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
256        addedRayRefs<<endl;
257
258        app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
259        removedRayRefs<<endl;
260
261        //  app << setprecision(4);
262
263        //  app << "#N_CTIME  ( Construction time [s] )\n"
264        //      << Time() << " \n";
265
266        app << "===== END OF BspTree statistics ==========\n";
267}
268
269BspTree::~BspTree()
270{
271        std::stack<BspNode *> tStack;
272
273        tStack.push(mRoot);
274
275        while (!tStack.empty())
276        {
277                BspNode *node = tStack.top();
278
279            tStack.pop();
280       
281                /// if we store
282                if (mStorePolys)
283                        Polygon3::DeletePolygons(&node->mPolygons);
284
285                if (!node->IsLeaf())
286                {
287                        BspInterior *interior = dynamic_cast<BspInterior *>(node);
288
289                        // push the children on the stack (there are always two children)
290                        tStack.push(interior->GetBack());
291                        tStack.push(interior->GetFront());
292                }
293
294                DEL_PTR(node);
295        }
296}
297
298
299void BspTree::InsertViewCell(ViewCell *viewCell)
300{       
301        std::stack<BspTraversalData> tStack;
302       
303        PolygonContainer polys;
304
305        // copy polygon information to guide the split process
306        AddMesh2Polygons(viewCell->GetMesh(), polys);
307        mBox.Include(viewCell->GetBox()); // add to BSP aabb
308
309        BspNode *firstNode = mRoot ? mRoot : new BspLeaf(); // traverse tree or create new one
310
311        tStack.push(BspTraversalData(firstNode, NULL, &polys, 0));
312
313        while (!tStack.empty())
314        {
315                // filter polygons donw the tree
316                BspTraversalData tData = tStack.top();
317
318            tStack.pop();
319                               
320        if (!tData.mNode->IsLeaf())
321                {
322                        BspInterior *interior = dynamic_cast<BspInterior *>(tData.mNode);
323
324                        //-- filter view cell polygons down the tree until a leaf is reached
325                        PolygonContainer *frontPolys = new PolygonContainer();
326                        PolygonContainer *backPolys = new PolygonContainer();
327
328                        int splits = 0;
329                        // split viecell polygons with respect to split plane
330                        interior->SplitPolygons(tData.mPolygons, frontPolys, backPolys, splits);
331
332                        mStat.splits += splits;
333
334                        // push the children on the stack
335                        if (frontPolys->size() > 0) // if polygons on front side of bsp tree
336                        {
337                                tStack.push(BspTraversalData(interior->GetFront(), interior->GetParent(),
338                                                        frontPolys, tData.mDepth + 1));
339                        }
340                        else // front side polygons empty
341                                delete frontPolys;
342
343                        if (backPolys->size() > 0) // if polygons on backc side of bsp tree
344                        {
345                                tStack.push(BspTraversalData(interior->GetBack(), interior->GetParent(),
346                                                        backPolys, tData.mDepth + 1));
347                        }
348                        else // back side polygons empty
349                                delete backPolys;
350                }
351                else // reached leaf => subdivide current viewcell
352                {
353                        BspNode *root = Subdivide(tStack, tData, viewCell);
354
355            // tree empty => new root
356                        if (!mRoot)
357                                mRoot = root;                           
358                }
359        }
360}
361
362void BspTree::InitTree(int maxPolygons, int maxDepth)
363{
364        mTermMaxPolygons = maxPolygons;
365        mTermMaxDepth = maxDepth;
366        mStat.nodes = 1;
367        mBox.Initialize();      // initialise bsp tree bounding box
368}
369
370
371
372void BspTree::AddMesh2Polygons(Mesh *mesh, PolygonContainer &polys)
373{
374        FaceContainer::const_iterator fi;
375       
376        // copy the face data to polygons
377        for (fi = mesh->mFaces.begin(); fi != mesh->mFaces.end(); ++ fi)
378        {
379                Polygon3 *poly = new Polygon3((*fi), mesh);
380                polys.push_back(poly);
381        }
382}
383
384void BspTree::Copy2PolygonSoup(const ViewCellContainer &viewCells, PolygonContainer &polys, int maxObjects)
385{
386        int limit = (maxObjects > 0) ? Min((int)viewCells.size(), maxObjects) : (int)viewCells.size();
387 
388        for (int i = 0; i < limit; ++i)
389        {
390                if (viewCells[i]->GetMesh()) // copy the mesh data to polygons
391                {
392                        mBox.Include(viewCells[i]->GetBox()); // add to BSP tree aabb
393                        AddMesh2Polygons(viewCells[i]->GetMesh(), polys);
394                }
395        }
396}
397
398void BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxObjects)
399{
400        int limit = (maxObjects > 0) ? Min((int)objects.size(), maxObjects) : (int)objects.size();
401 
402        for (int i = 0; i < limit; ++i)
403        {
404                Intersectable *object = objects[i];//*it;
405                Mesh *mesh = NULL;
406
407                switch (object->Type()) // extract the meshes
408                {
409                case Intersectable::MESH_INSTANCE:
410                        mesh = dynamic_cast<MeshInstance *>(object)->GetMesh();
411                        break;
412                case Intersectable::VIEWCELL:
413                        mesh = dynamic_cast<ViewCell *>(object)->GetMesh();
414                        break;
415                        // TODO: handle transformed mesh instances
416                default:
417                        break;
418                }
419               
420        if (mesh) // copy the mesh data to polygons
421                {
422                        mBox.Include(object->GetBox()); // add to BSP tree aabb
423                        AddMesh2Polygons(mesh, polys);
424                }
425        }
426
427        Debug << "Number of polygons: " << (int)polys.size() << ", BSP root box: " << mBox << endl;
428}
429
430void BspTree::Construct(const ViewCellContainer &viewCells)
431{
432        //-- Construct tree using the given viewcells
433       
434        /* for this type of construction we filter all viewcells down the
435         * tree until there is no polygon left. The split of the last polygon
436         * decides inside or outside of the viewcell.
437    */
438        const int maxPolygons = 0;
439        const int maxDepth = 99999;
440        InitTree(maxPolygons, maxDepth);
441       
442
443        // tree is completely constructed before
444        // view cells are not inserted one after another => better tree behaviour
445        if (!mIsIncremential)
446        {
447                // copy view cell meshes into one big polygon soup
448                PolygonContainer *polys = new PolygonContainer();
449                Copy2PolygonSoup(viewCells, *polys, sMaxCandidates);
450
451                // construct tree from viewcell polygons
452                Construct(polys);
453        }
454
455        // insert all viewcells
456        ViewCellContainer::const_iterator it;
457
458        for (it = viewCells.begin(); it != viewCells.end(); ++ it)
459        {
460                InsertViewCell(*it);
461        }
462}
463
464
465void BspTree::Construct(const ObjectContainer &objects, ViewCellContainer *viewCells)
466{
467#ifdef _DEBUG
468        Debug << "Constructing tree using object container\n";
469#endif
470        // take termination criteria from globals
471        InitTree(mTermMaxPolygons, mTermMaxDepth);
472
473        PolygonContainer *polys = new PolygonContainer();
474       
475        // copy mesh instance polygons into one big polygon soup
476        Copy2PolygonSoup(objects, *polys, sMaxCandidates);
477
478        // construct tree from polygon soup
479        Construct(polys);
480
481        // TODO: generate view cells
482}
483
484void BspTree::Construct(const RayContainer &rays, ViewCellContainer *viewCells)
485{
486        // TODO
487}
488
489void BspTree::Construct(PolygonContainer *polys)
490{
491        std::stack<BspTraversalData> tStack;
492        // new root corresponding to unbounded space
493        BspTraversalData tData(new BspLeaf(), mRoot->GetParent(), polys, 0);
494
495        tStack.push(tData);
496
497        while (!tStack.empty())
498        {
499                tData = tStack.top();
500            tStack.pop();
501
502                // subdivide leaf node
503                BspNode *root = Subdivide(tStack, tData);
504
505                if (!mRoot) // empty tree => new root
506                        mRoot = root;
507        }
508}
509
510
511BspNode * BspTree::Subdivide(BspTraversalStack &tStack,
512                                                         BspTraversalData &tData,
513                                                         ViewCell *viewCell)
514{
515        PolygonContainer *backPolys = new PolygonContainer();
516        PolygonContainer *frontPolys = new PolygonContainer();
517
518        BspNode *node = SubdivideNode(dynamic_cast<BspLeaf *>(tData.mNode),
519                                                                  tData.mParent,
520                                                                  tData.mPolygons,
521                                                                  tData.mDepth,
522                                                                  frontPolys,
523                                                                  backPolys);
524
525        if (!node->IsLeaf()) // node was subdivided
526        {
527                BspInterior *interior = dynamic_cast<BspInterior *>(node);
528
529                // push the children on the stack (there are always two children)
530                tStack.push(BspTraversalData(interior->GetBack(), interior, backPolys, tData.mDepth + 1));
531                tStack.push(BspTraversalData(interior->GetFront(), interior, frontPolys, tData.mDepth + 1));
532        }
533        else // tree terminates here
534        {
535                EvaluateLeafStats(tData);
536
537                // add view cell if in positive halfspace
538                if (!tData.mParent || (node == tData.mParent->GetFront()))
539                        dynamic_cast<BspLeaf *>(node)->SetViewCell(viewCell);
540        }
541
542        return node;
543}
544
545BspNode *BspTree::SubdivideNode(BspLeaf *leaf,
546                                                                BspInterior *parent,
547                                                                PolygonContainer *polys,
548                                                                const int depth,
549                                                                PolygonContainer *frontPolys,
550                                                                PolygonContainer *backPolys)
551{
552        // terminate traversal
553        if ((polys->size() <= mTermMaxPolygons) || (depth >= mTermMaxDepth))
554        {
555                // add or delete remaining polygons
556                if (mStorePolys)
557                        leaf->AddPolygons(polys);
558                else
559                        Polygon3::DeletePolygons(polys);
560
561                delete polys;
562
563                return leaf;
564        }
565
566         mStat.nodes += 2;
567
568        // add the new nodes to the tree + select subdivision plane
569        BspInterior *node = new BspInterior(SelectPlane(polys));
570
571#ifdef _DEBUG
572        Debug << node << endl;
573#endif
574        // split polygon according to current plane
575        int splits = 0;
576               
577        node->SplitPolygons(polys, frontPolys, backPolys, splits, mStorePolys);
578       
579        mStat.splits += splits;
580
581        // two new leaves
582        BspLeaf *back = new BspLeaf();
583        BspLeaf *front = new BspLeaf();
584
585        // replace a link from node's parent
586        if (parent)
587        {
588                parent->ReplaceChildLink(leaf, node);
589        }
590
591        // and setup child links
592        node->SetupChildLinks(back, front);
593
594        delete leaf; // leaf not member of tree anymore
595       
596        return node;
597}
598
599Plane3 BspTree::SelectPlane(PolygonContainer *polygons)  const
600{
601        // simple strategy: just take next polygon
602        if (sSplitPlaneStrategy == NEXT_POLYGON)
603        {
604                return polygons->front()->GetSupportingPlane();
605        }
606       
607        // use heuristics to find appropriate plane
608        return SelectPlaneHeuristics(polygons, sMaxCandidates);
609}
610
611Plane3 BspTree::SelectPlaneHeuristics(PolygonContainer *polygons, int maxTests) const
612{
613        int lowestCost = INITIAL_COST;
614        Plane3 *bestPlane = NULL;
615       
616        int limit = Min((int)polygons->size(), maxTests);
617
618        for (int i = 0; i < limit; ++i)
619        {
620                int candidateIdx = Random((int)polygons->size());
621                Plane3 candidatePlane = (*polygons)[candidateIdx]->GetSupportingPlane();
622               
623                // evaluate current candidate
624                int candidateCost = EvalSplitPlane(polygons, candidatePlane);
625                       
626                if (candidateCost < lowestCost)
627                {
628                        bestPlane = &candidatePlane;
629                        lowestCost = candidateCost;
630                        //Debug << "new plane cost " << lowestCost << endl;
631                }
632        }
633               
634        return *bestPlane;
635}
636
637int BspTree::EvalSplitPlane(PolygonContainer *polygons, const Plane3 &candidatePlane) const
638{
639        PolygonContainer::const_iterator it;
640
641        int sum = 0, sum2 = 0;
642
643        for (it = polygons->begin(); it < polygons->end(); ++ it)
644        {
645                int classification = (*it)->ClassifyPlane(candidatePlane);
646               
647                if ((sSplitPlaneStrategy == BALANCED_TREE) || (sSplitPlaneStrategy == COMBINED))
648                {
649                        sum += EvalForBalancedTree(classification);
650                }
651               
652                if ((sSplitPlaneStrategy == LEAST_SPLITS) || (sSplitPlaneStrategy == COMBINED))
653                {
654                        sum2 += EvalForLeastSplits(classification);
655                }
656        }
657
658        // return linear combination of both sums
659        return abs(sum) + abs(sum2);
660}
661
662int BspTree::EvalForBalancedTree(const int classification)
663{
664        // there should be roughly the same number of front and back polygons
665        if (classification == Polygon3::FRONT_SIDE)
666                return 1;
667        else if (classification == Polygon3::BACK_SIDE)
668                return -1;
669
670        return 0;
671}
672
673int BspTree::EvalForLeastSplits(const int classification)
674{
675        if (classification == Polygon3::SPLIT)
676                return 1;
677
678        return 0;
679}
680
681
682void BspTree::ParseEnvironment()
683{
684        environment->GetIntValue("BspTree.Termination.maxDepth", sTermMaxDepth);
685        environment->GetIntValue("BspTree.Termination.maxPolygons", sTermMaxPolygons);
686        environment->GetIntValue("BspTree.maxCandidates", sMaxCandidates);
687
688        //-- extract strategy to choose the next split plane
689        char splitPlaneStrategyStr[60];
690
691        environment->GetStringValue("BspTree.splitPlaneStrategy", splitPlaneStrategyStr);
692       
693        sSplitPlaneStrategy = BspTree::NEXT_POLYGON;
694       
695        if (strcmp(splitPlaneStrategyStr, "nextPolygon") == 0)
696                sSplitPlaneStrategy = BspTree::NEXT_POLYGON;
697        else if (strcmp(splitPlaneStrategyStr, "leastSplits") == 0)
698                sSplitPlaneStrategy = BspTree::LEAST_SPLITS;
699        else if (strcmp(splitPlaneStrategyStr, "balancedTree") == 0)
700                sSplitPlaneStrategy = BspTree::BALANCED_TREE;
701        else
702        {
703                cerr << "Wrong BSP split plane strategy " << splitPlaneStrategyStr << endl;
704                exit(1);
705    }
706}
707
708void BspTree::CollectLeaves(vector<BspLeaf *> &leaves)
709{
710        stack<BspNode *> nodeStack;
711        nodeStack.push(mRoot);
712 
713        while (!nodeStack.empty())
714        {
715                BspNode *node = nodeStack.top();
716   
717                nodeStack.pop();
718   
719                if (node->IsLeaf())
720                {
721                        BspLeaf *leaf = (BspLeaf *)node;
722                       
723                        leaves.push_back(leaf);
724                } else
725                {
726                        BspInterior *interior = dynamic_cast<BspInterior *>(node);
727                        nodeStack.push(interior->GetBack());
728                        nodeStack.push(interior->GetFront());
729                }
730        }
731}
732
733int BspTree::CollectLeafPvs()
734{
735        int totalPvsSize = 0;
736 
737        stack<BspNode *> nodeStack;
738 
739        nodeStack.push(mRoot);
740 
741        while (!nodeStack.empty())
742        {
743                BspNode *node = nodeStack.top();
744               
745                nodeStack.pop();
746               
747                if (node->IsLeaf())
748                {
749                        BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
750
751                        ViewCell *viewcell = leaf->GetViewCell();
752                       
753                        if (!viewcell->Mailed())
754                        {
755                                viewcell->Mail(); // what does mail mean?
756                                       
757                                // add this node to pvs of all nodes it can see
758                                BspPvsMap::iterator ni;
759         
760        /*                      for (ni = object->mBspPvs.mEntries.begin(); ni != object->mKdPvs.mEntries.end(); ni++)
761                                {
762                                        BspNode *node = (*ni).first;
763           
764                                        // $$ JB TEMPORARY solution -> should add object PVS or explictly computed
765                                        // BSP tree PVS
766                                if (leaf->mBspPvs.AddNodeSample(node))
767                                                totalPvsSize++;
768                                }*/
769                        }
770                } else
771                {
772                        // traverse tree
773                        BspInterior *interior = (BspInterior *)node;
774     
775                        nodeStack.push(interior->GetFront());
776                        nodeStack.push(interior->GetBack());
777                }
778        }
779
780        return totalPvsSize;
781}
782
783AxisAlignedBox3 BspTree::GetBoundingBox() const
784{
785        return mBox;
786}
787
788BspNode *BspTree::GetRoot() const
789{
790        return mRoot;
791}
792
793bool BspTree::StorePolys() const
794{
795        return mStorePolys;
796}
797void BspTree::EvaluateLeafStats(const BspTraversalData &data)
798{
799        // the node became a leaf -> evaluate stats for leafs
800        BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode);
801
802        if (data.mDepth >= mTermMaxDepth)
803        {
804                ++ mStat.maxDepthNodes;
805        }
806
807        // store maximal depth
808        if (data.mDepth > mStat.maxDepth)
809                mStat.maxDepth = data.mDepth;
810
811#ifdef _DEBUG
812        Debug << "BSP Traversal data. Depth: " << data.mDepth << " (max: " << mTermMaxDepth<< "), #polygons: " <<
813          data.mPolygons->size() << " (max: " << mTermMaxPolygons << ")" << endl;
814#endif
815}
816
817int BspTree::CastRay(Ray &ray)
818{
819        int hits = 0;
820 
821        stack<BspRayTraversalData> tStack;
822 
823        float maxt = 1e6;
824        float mint = 0;
825
826        Intersectable::NewMail();
827
828        // test with tree bounding box
829        if (!mBox.GetMinMaxT(ray, &mint, &maxt))
830                return 0;
831
832        if (mint < 0)
833                mint = 0;
834 
835        maxt += Limits::Threshold;
836 
837        Vector3 entp = ray.Extrap(mint);
838        Vector3 extp = ray.Extrap(maxt);
839 
840        BspNode *node = mRoot;
841        BspNode *farChild;
842       
843        while (1)
844        {
845                if (!node->IsLeaf())
846                {
847                        BspInterior *in = (BspInterior *) node;
848                       
849                        Plane3 *splitPlane = in->GetPlane();
850
851                        float t = 0;
852                        bool coplanar = false;
853               
854                        int entSide = splitPlane->Side(entp);
855                        int extSide = splitPlane->Side(extp);
856
857                        Vector3 intersection;
858
859                        if (entSide < 0)
860                        {
861                                node = in->GetBack();
862
863                                if(extSide <= 0)
864                                        continue;
865                                       
866                                farChild = in->GetFront(); // plane splits ray
867
868                        } else if (entSide > 0)
869                        {
870                                node = in->GetFront();
871
872                                if (extSide >= 0)
873                                        continue;
874
875                                farChild = in->GetBack();        // plane splits ray                   
876                        }
877                        else // ray and plane are coincident // WHAT TO DO IN THIS CASE ?
878                        {
879                                node = in->GetFront();
880                                continue;
881                        }
882
883                        //-- split
884
885                        // push data for far child
886                        tStack.push(BspRayTraversalData(farChild, extp, maxt));
887
888                        // find intersection with plane between ray origin and exit point
889                        extp = splitPlane->FindIntersection(ray.GetLoc(), extp, &maxt);
890
891                } else // compute intersections with objects in leaf
892                {
893                        BspLeaf *leaf = dynamic_cast<BspLeaf *>(node);
894                        //ray.leaves.push_back(leaf);
895     
896                        /*ObjectContainer::const_iterator mi;
897                        for (mi = leaf->mObjects.begin(); mi != leaf->mObjects.end(); ++mi)
898                        {
899                                Intersectable *object = *mi;
900                                if (!object->Mailed())
901                                {
902                                        object->Mail();
903                                        //ray.meshes.push_back(mesh);
904                                        hits += object->CastRay(ray);
905                                }
906                        }*/
907
908                        if (hits && ray.GetType() == Ray::LOCAL_RAY)
909                                if (ray.intersections[0].mT <= maxt)
910                                        break;
911     
912                        // get the next node from the stack
913                        if (tStack.empty())
914                                break;
915     
916                        entp = extp;
917                        mint = maxt;
918                        BspRayTraversalData &s  = tStack.top();
919
920                        node = s.mNode;
921                        extp = s.mExitPoint;
922                        maxt = s.mMaxT;
923
924                        tStack.pop();
925                }
926        }
927
928        return hits;
929}
930
931//} // GtpVisibilityPreprocessor
Note: See TracBrowser for help on using the repository browser.