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

Revision 262, 22.2 KB checked in by mattausch, 19 years ago (diff)

debugged bsp

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