source: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp @ 1302

Revision 1302, 19.0 KB checked in by mattausch, 18 years ago (diff)
Line 
1#include <stack>
2#include <time.h>
3#include <iomanip>
4
5#include "ViewCell.h"
6#include "Plane3.h"
7#include "HierarchyManager.h"
8#include "Mesh.h"
9#include "common.h"
10#include "Environment.h"
11#include "Polygon3.h"
12#include "Ray.h"
13#include "AxisAlignedBox3.h"
14#include "Exporter.h"
15#include "Plane3.h"
16#include "ViewCellsManager.h"
17#include "Beam.h"
18#include "KdTree.h"
19#include "KdIntersectable.h"
20#include "VspTree.h"
21#include "OspTree.h"
22#include "BvHierarchy.h"
23
24
25namespace GtpVisibilityPreprocessor {
26
27
28#define USE_FIXEDPOINT_T 0
29
30
31/*******************************************************************/
32/*              class HierarchyManager implementation              */
33/*******************************************************************/
34
35
36HierarchyManager::HierarchyManager(VspTree *vspTree,
37                                                                   const int objectSpaceSubdivisionType):
38mObjectSpaceSubdivisonType(objectSpaceSubdivisionType),
39mVspTree(vspTree),
40mOspTree(NULL),
41mBvHierarchy(NULL)
42{
43        switch(mObjectSpaceSubdivisonType)
44        {
45        case KD_BASED_OBJ_SUBDIV:
46                mOspTree = new OspTree();
47                mOspTree->mVspTree = mVspTree;
48                //mOspTree->mHierarchyManager = this;
49                Debug << "creating osp tree" << endl;
50                break;
51        case BV_BASED_OBJ_SUBDIV:
52        mBvHierarchy = new BvHierarchy();
53                mBvHierarchy->mVspTree = mVspTree;
54                //mBvHierarchy->mHierarchyManager = this;
55                Debug << "creating bv hierachy" << endl;
56                break;
57        default:
58                break;
59        }
60
61        if (mVspTree)
62                mVspTree->mHierarchyManager = this;
63
64        ParseEnvironment();
65}
66
67
68HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree):
69mObjectSpaceSubdivisonType(KD_BASED_OBJ_SUBDIV),
70mVspTree(vspTree),
71mBvHierarchy(NULL)
72{
73        mOspTree = new OspTree(*kdTree);
74        mOspTree->mVspTree = mVspTree;
75
76        //mOspTree->mHierarchyManager = this;
77        Debug << "creating osp tree" << endl;
78
79        if (mVspTree)
80                mVspTree->mHierarchyManager = this;
81
82        ParseEnvironment();
83}
84
85
86void HierarchyManager::ParseEnvironment()
87{
88        char subdivisionStatsLog[100];
89        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
90                subdivisionStatsLog);
91        mSubdivisionStats.open(subdivisionStatsLog);
92
93        Environment::GetSingleton()->GetFloatValue(
94                "Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
95        Environment::GetSingleton()->GetIntValue(
96                "Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
97
98        Environment::GetSingleton()->GetIntValue(
99                "Hierarchy.Termination.maxLeaves", mTermMaxLeaves);
100
101        Environment::GetSingleton()->GetIntValue(
102                "Hierarchy.Construction.type", mConstructionType);
103
104        Debug << "******** Hierachy Manager Parameters ***********" << endl;
105        Debug << "max leaves: " << mTermMaxLeaves << endl;
106        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
107        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
108}
109
110
111HierarchyManager::~HierarchyManager()
112{
113        DEL_PTR(mOspTree);
114        //DEL_PTR(mVspTree);
115        DEL_PTR(mBvHierarchy);
116}
117
118
119void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
120{
121        mVspTree->SetViewCellsManager(vcm);
122
123        if (mOspTree)
124                mOspTree->SetViewCellsManager(vcm);
125        if (mBvHierarchy)
126                mBvHierarchy->SetViewCellsManager(vcm);
127}
128
129
130void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
131{
132        mVspTree->SetViewCellsTree(vcTree);
133}
134
135
136SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate()
137{
138        SubdivisionCandidate *splitCandidate = mTQueue.Top();
139        mTQueue.Pop();
140
141        return splitCandidate;
142}
143
144
145void HierarchyManager::PrepareConstruction(const VssRayContainer &sampleRays,
146                                                                                   const ObjectContainer &objects,
147                                                                                   AxisAlignedBox3 *forcedViewSpace,
148                                                                                   RayInfoContainer &viewSpaceRays,
149                                                                                   RayInfoContainer &objectSpaceRays)
150{
151        mHierarchyStats.Reset();
152        mHierarchyStats.Start();
153
154        switch (mObjectSpaceSubdivisonType)
155        {
156        case KD_BASED_OBJ_SUBDIV:
157                {
158                        SubdivisionCandidate *vsc =
159                                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, viewSpaceRays);
160                        mTQueue.Push(vsc);
161
162                        SubdivisionCandidate *osc;
163                        osc = mOspTree->PrepareConstruction(sampleRays, objects, objectSpaceRays);
164                        mTQueue.Push(osc);
165                        break;
166                }
167        case BV_BASED_OBJ_SUBDIV:
168                {
169                        mBvHierarchy->CreateRoot(objects);
170
171                        SubdivisionCandidate *vsc =
172                                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, viewSpaceRays);
173                        mTQueue.Push(vsc);
174
175                        SubdivisionCandidate *osc;
176                        osc = mBvHierarchy->PrepareConstruction(sampleRays, objects);
177                        mTQueue.Push(osc);
178                        break;
179                }
180        default:
181                break;
182        }
183
184        mTotalCost = (float)objects.size();
185        Debug << "setting total cost to " << mTotalCost << endl;
186}
187
188
189void HierarchyManager::EvalSubdivisionStats(const SubdivisionCandidate &tData)
190{
191        const float costDecr = tData.GetRenderCostDecrease();
192
193        switch (mObjectSpaceSubdivisonType)
194        {
195        case KD_BASED_OBJ_SUBDIV:
196                AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
197                                                        costDecr,
198                                                        mTotalCost
199                                                        );
200                break;
201        case BV_BASED_OBJ_SUBDIV:
202                AddSubdivisionStats(mBvHierarchy->mBvhStats.Leaves() + mVspTree->mVspStats.Leaves(),
203                                                        costDecr,
204                                                        mTotalCost
205                                                        );
206                break;
207        default:
208                AddSubdivisionStats(mVspTree->mVspStats.Leaves(),
209                                                        costDecr,
210                                                        mTotalCost
211                                                        );
212                break;
213        }
214}
215
216
217void HierarchyManager::AddSubdivisionStats(const int splits,
218                                                                                   const float renderCostDecr,
219                                                                                   const float totalRenderCost)
220{
221        mSubdivisionStats
222                        << "#Splits\n" << splits << endl
223                        << "#RenderCostDecrease\n" << renderCostDecr << endl
224                        << "#TotalRenderCost\n" << totalRenderCost << endl;
225                        //<< "#AvgRenderCost\n" << avgRenderCost << endl;
226}
227
228
229bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
230{
231        return (0
232                || (mHierarchyStats.Leaves() >= mTermMaxLeaves)
233                //|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
234                ||      candidate->GlobalTerminationCriteriaMet()
235                );
236}
237
238
239void HierarchyManager::Construct(const VssRayContainer &sampleRays,
240                                                                const ObjectContainer &objects,
241                                                                AxisAlignedBox3 *forcedViewSpace)
242{
243        switch (mConstructionType)
244        {
245        case 0:
246                ConstructSequential(sampleRays, objects, forcedViewSpace);
247                break;
248        case 1:
249                ConstructInterleaved(sampleRays, objects, forcedViewSpace);
250                break;
251        default:
252                break;
253        }
254}
255
256
257void HierarchyManager::ConstructInterleaved(const VssRayContainer &sampleRays,
258                                                                                        const ObjectContainer &objects,
259                                                                                        AxisAlignedBox3 *forcedViewSpace)
260{
261        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
262        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
263
264        // prepare vsp and osp trees for traversal
265        PrepareConstruction(sampleRays,
266                                                objects,
267                                                forcedViewSpace,
268                                                *viewSpaceRays,
269                                                *objectSpaceRays);
270
271        cout << "Constructing view space / object space tree ... \n";
272        const long startTime = GetTime();       
273       
274        const bool repairQueue = true;
275        //const bool repairQueue = false;
276
277        // process object space candidates
278        RunConstruction(repairQueue);
279        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
280
281        mVspTree->mVspStats.Stop();
282}
283
284
285void HierarchyManager::ConstructBvHierarchy(const VssRayContainer &sampleRays,
286                                                                                        const ObjectContainer &objects)
287
288{
289        Debug << "\n$$$$$$$$$ bv hierarchy construction $$$$$$$$$$\n" << endl;
290        cout << "starting bv hierarchy construction ... " << endl;
291
292        mBvHierarchy->CreateRoot(objects);
293
294        // compute first candidate
295        SubdivisionCandidate *sc =
296                mBvHierarchy->PrepareConstruction(sampleRays, objects);
297
298        mTotalCost = mBvHierarchy->mTotalCost;
299        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
300       
301    mTQueue.Push(sc);
302
303        mBvHierarchy->mBvhStats.Reset();
304        mBvHierarchy->mBvhStats.Start();
305
306        const long startTime = GetTime();
307
308        const bool repairQueue = false;
309        // process object space candidates
310        RunConstruction(repairQueue);
311
312        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
313
314        mBvHierarchy->mBvhStats.Stop();
315}
316
317
318void HierarchyManager::ConstructOspTree(const VssRayContainer &sampleRays,
319                                                                                const ObjectContainer &objects)
320
321{
322        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
323
324        Debug << "\n$$$$$$$$$ osp tree construction $$$$$$$$$$\n" << endl;
325        cout << "starting osp tree construction ... " << endl;
326
327        // start with one big kd cell - all objects can be seen from everywhere
328        // note: only true for view space = object space
329
330        // compute first candidate
331        SubdivisionCandidate *osc =
332                mOspTree->PrepareConstruction(sampleRays, objects, *objectSpaceRays);
333
334        mTotalCost = mOspTree->mTotalCost;
335        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
336       
337    mTQueue.Push(osc);
338
339        mOspTree->mOspStats.Reset();
340        mOspTree->mOspStats.Start();
341
342        const long startTime = GetTime();
343               
344        const bool repairQueue = false;
345        // process object space candidates
346        RunConstruction(repairQueue);
347
348        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
349        mOspTree->mOspStats.Stop();
350
351        //////////////////////////
352        // matt: only for debugging purpose
353
354        const float rc = mOspTree->EvalRenderCost(sampleRays);
355        Debug << "My render cost evalulation: " << rc << endl;
356}
357
358
359
360bool HierarchyManager::ApplySubdivisionCandidate(SubdivisionCandidate *sc)
361{
362        const bool globalTerminationCriteriaMet = GlobalTerminationCriteriaMet(sc);
363        const bool vspSplit = (sc->Type() == SubdivisionCandidate::VIEW_SPACE);
364
365        if (vspSplit)
366        {
367                VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
368
369                if (n->IsLeaf()) // local or global termination criteria failed
370                        return false;
371        }
372        else
373        {
374                if (mObjectSpaceSubdivisonType == KD_BASED_OBJ_SUBDIV)
375                {
376                        KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
377
378                        if (n->IsLeaf()) // local or global termination criteria failed
379                                return false;
380                }
381                else if (mObjectSpaceSubdivisonType == BV_BASED_OBJ_SUBDIV)
382                {
383                        BvhNode *n = mBvHierarchy->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
384
385                        if (n->IsLeaf()) // local or global termination criteria failed
386                                return false;
387                }
388        }
389       
390        return true;//!globalTerminationCriteriaMet;
391}
392
393
394void HierarchyManager::RunConstruction(const bool repair)
395{
396        mHierarchyStats.nodes = 0;
397        mGlobalCostMisses = 0;
398
399        while (!FinishedConstruction())
400        {
401                mCurrentCandidate = NextSubdivisionCandidate();
402           
403                mTotalCost -= mCurrentCandidate->GetRenderCostDecrease();
404
405                // cost ratio of cost decrease / totalCost
406                const float costRatio = mCurrentCandidate->GetRenderCostDecrease() / mTotalCost;
407
408                //Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
409                if (costRatio < mTermMinGlobalCostRatio)
410                        ++ mGlobalCostMisses;
411
412                //-- subdivide leaf node
413
414                if (ApplySubdivisionCandidate(mCurrentCandidate))
415                {
416                        mHierarchyStats.nodes += 2;
417
418                        // subdivision successful
419                        EvalSubdivisionStats(*mCurrentCandidate);
420               
421                        // reevaluate candidates affected by the split
422                        // for view space splits, this would be object space splits
423                        // and other way round
424                        if (repair) RepairQueue();
425
426                        Debug << "candidate: " << mCurrentCandidate->Type() << ", priority: "
427                                  << mCurrentCandidate->GetPriority() << endl;
428                }
429               
430                DEL_PTR(mCurrentCandidate);
431        }
432}
433
434
435bool HierarchyManager::FinishedConstruction() const
436{
437        return mTQueue.Empty();
438}
439
440
441void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
442{
443        switch (mObjectSpaceSubdivisonType)
444        {
445        case KD_BASED_OBJ_SUBDIV:
446                {
447                        OspTree::OspSubdivisionCandidate *sc =
448                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
449
450                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
451                        break;
452                }
453        case BV_BASED_OBJ_SUBDIV:
454                {
455                        BvHierarchy::BvhSubdivisionCandidate *sc =
456                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
457
458                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
459
460sc->mParentData.mNode->SetSubdivisionCandidate(NULL); // HACK
461                        break;
462                }
463        default:
464                break;
465        }
466}
467
468
469void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
470{
471        VspTree::VspSubdivisionCandidate *sc =
472                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
473
474        mVspTree->CollectDirtyCandidates(sc, dirtyList);
475
476sc->mParentData.mNode->SetSubdivisionCandidate(NULL); // HACK
477}
478
479
480void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
481{
482        // we have either a object space or view space split
483        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
484        {
485                Debug << "collecting candidates after view space split" << endl;
486                CollectViewSpaceDirtyList(dirtyList);
487        }
488        else // object space split
489        {       Debug << "collecting candidates after object space split" << endl;
490                CollectObjectSpaceDirtyList(dirtyList);
491        }
492}
493
494
495void HierarchyManager::RepairQueue()
496{
497        // TODO
498        // for each update of the view space partition:
499        // the candidates from object space partition which
500        // have been afected by the view space split (the kd split candidates
501        // which saw the view cell which was split) must be reevaluated
502        // (maybe not locally, just reinsert them into the queue)
503        //
504        // vice versa for the view cells
505        // for each update of the object space partition
506        // reevaluate split candidate for view cells which saw the split kd cell
507        //
508        // the priority queue update can be solved by implementing a binary heap
509        // (explicit data structure, binary tree)
510        // *) inserting and removal is efficient
511        // *) search is not efficient => store queue position with each
512        // split candidate
513
514        // collect list of "dirty" candidates
515        vector<SubdivisionCandidate *> dirtyList;
516        Debug << "collecting dirty candidates" << endl;
517        CollectDirtyCandidates(dirtyList);
518       
519        //-- reevaluate the dirty list
520        vector<SubdivisionCandidate *>::const_iterator sit, sit_end = dirtyList.end();
521       
522        Debug << "collected " << (int)dirtyList.size() << " candidates" << endl;
523
524        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
525        {
526                SubdivisionCandidate* sc = *sit;
527                float rcd = sc->GetRenderCostDecrease();
528                Debug << "here6 " << rcd << endl;
529                Debug << "here84 " << endl;
530                Debug << "here7 " << sc << endl;
531                Debug << "here90 " << sc->GetPosition() << endl;
532                Debug << "here91 " << sc->Type() << endl;
533                //Debug << "here1191" << sc->Type() << endl;
534                //Debug << "sc: " << sc << " " << sc->GetPosition() << " " << sc->Type() << endl;
535               
536                Debug << "here11" << endl;
537                mTQueue.Erase(sc); // erase from queue
538                Debug << "here2" << endl;
539
540                sc->EvalPriority(); // reevaluate
541               
542        /*      cout << "render cost decrease diff " << rcd - sc->GetRenderCostDecrease()
543                         << " old: " << rcd << " new " << sc->GetRenderCostDecrease()
544                         << " type " << sc->Type() << endl;*/
545
546                mTQueue.Push(sc); // reinsert
547        }
548}
549
550
551void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
552{
553        // the type of the view cells hierarchy
554        switch (mObjectSpaceSubdivisonType)
555        {
556        case KD_BASED_OBJ_SUBDIV:
557                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
558                mOspTree->Export(stream);
559                stream << endl << "</ObjectSpaceHierarchy>" << endl;
560                break;
561               
562        case BV_BASED_OBJ_SUBDIV:
563                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
564                mBvHierarchy->Export(stream);
565                stream << endl << "</ObjectSpaceHierarchy>" << endl;
566                break;
567        }
568}
569
570
571bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
572                                                                          const Vector3 &hitPoint,
573                                                                          ViewCell *vc,
574                                                                          const float pdf,
575                                                                          float &contribution) const
576{
577        if (!obj) return false;
578
579        switch (mObjectSpaceSubdivisonType)
580        {
581        case NO_OBJ_SUBDIV:
582                // potentially visible objects
583                return vc->AddPvsSample(obj, pdf, contribution);
584
585        case KD_BASED_OBJ_SUBDIV:
586                {
587                        // potentially visible kd cells
588                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
589                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
590                }
591        case BV_BASED_OBJ_SUBDIV:
592                {
593                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
594                        return mBvHierarchy->AddLeafToPvs(leaf, vc, pdf, contribution);
595                }
596        default:
597                return false;
598        }
599}
600
601
602void HierarchyManager::PrintObjectSpaceHierarchyStatistics(ofstream &stream) const
603{
604        switch (mObjectSpaceSubdivisonType)
605        {
606        case KD_BASED_OBJ_SUBDIV:
607                {
608                        stream << mOspTree->GetStatistics();
609                        break;
610                }
611        case BV_BASED_OBJ_SUBDIV:
612                {
613                        stream << mBvHierarchy->GetStatistics();
614                        break;
615                }
616        default:
617                break;
618        }
619}
620
621
622void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
623                                                                                                  const ObjectContainer &objects) const
624{
625        switch (mObjectSpaceSubdivisonType)
626        {
627        case KD_BASED_OBJ_SUBDIV:
628                {
629                        ExportOspTree(exporter, objects);
630                        break;
631                }
632        case BV_BASED_OBJ_SUBDIV:
633                {
634                        ExportBvHierarchy(exporter, objects);
635                        break;
636                }
637        default:
638                break;
639        }
640}
641
642
643void HierarchyManager::ExportBvHierarchy(Exporter *exporter,
644                                                                                 const ObjectContainer &objects) const
645{
646        exporter->SetWireframe();
647        exporter->ExportBvHierarchy(*mBvHierarchy, 0);
648}
649
650
651void HierarchyManager::ExportOspTree(Exporter *exporter,
652                                                                         const ObjectContainer &objects) const
653{
654        if (0) exporter->ExportGeometry(objects);
655                       
656        exporter->SetWireframe();
657        exporter->ExportOspTree(*mOspTree, 0);
658}
659
660
661void HierarchyManager::ConstructSequential(const VssRayContainer &sampleRays,
662                                                                                   const ObjectContainer &objects,
663                                                                                   AxisAlignedBox3 *forcedViewSpace)
664{
665        // rays clipped in view space and in object space
666        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
667       
668
669        /////////////////////////////////////////////////////////////
670        // view space space partition
671        /////////////////////////////////////////////////////////////
672
673
674        // use objects for evaluating vsp tree construction
675        const int savedobjectSpaceSubdivisionType = mObjectSpaceSubdivisonType;
676        mObjectSpaceSubdivisonType = NO_OBJ_SUBDIV;
677
678        SubdivisionCandidate *vsc =
679                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
680       
681        // add to queue
682        mTQueue.Push(vsc);
683
684        long startTime = GetTime();
685        cout << "starting vsp construction ... " << endl;
686
687        mVspTree->mVspStats.Reset();
688        mVspTree->mVspStats.Start();
689
690        // all objects can be seen from everywhere
691        mTotalCost = (float)dynamic_cast<VspTree::VspSubdivisionCandidate *>(vsc)->mParentData.mPvs;
692
693        const bool repairQueue = false;
694        // process view space candidates
695        RunConstruction(repairQueue);
696
697        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
698        mVspTree->mVspStats.Stop();
699
700        // reset subdivision type
701        mObjectSpaceSubdivisonType = savedobjectSpaceSubdivisionType;
702
703
704        /////////////////////////////////////////////////////////////
705        // object space partition
706        /////////////////////////////////////////////////////////////
707       
708       
709        switch (mObjectSpaceSubdivisonType)
710        {
711        case KD_BASED_OBJ_SUBDIV:
712                {
713                        ConstructOspTree(sampleRays, objects);
714                        break;
715                }
716        case BV_BASED_OBJ_SUBDIV:
717                {
718                        ConstructBvHierarchy(sampleRays, objects);
719                        break;
720                }
721        default:
722                break;
723        }
724}
725
726
727}
Note: See TracBrowser for help on using the repository browser.