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

Revision 242, 19.1 KB checked in by mattausch, 19 years ago (diff)

added output functions and castray method for bsp viewcells

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