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

Revision 1303, 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                Debug << "here66 " << mCurrentCandidate << endl;
431                DEL_PTR(mCurrentCandidate);
432        }
433}
434
435
436bool HierarchyManager::FinishedConstruction() const
437{
438        return mTQueue.Empty();
439}
440
441
442void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
443{
444        switch (mObjectSpaceSubdivisonType)
445        {
446        case KD_BASED_OBJ_SUBDIV:
447                {
448                        OspTree::OspSubdivisionCandidate *sc =
449                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
450
451                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
452                        break;
453                }
454        case BV_BASED_OBJ_SUBDIV:
455                {
456                        BvHierarchy::BvhSubdivisionCandidate *sc =
457                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
458
459                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
460
461sc->mParentData.mNode->SetSubdivisionCandidate(NULL); // HACK
462                        break;
463                }
464        default:
465                break;
466        }
467}
468
469
470void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
471{
472        VspTree::VspSubdivisionCandidate *sc =
473                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
474
475        mVspTree->CollectDirtyCandidates(sc, dirtyList);
476
477sc->mParentData.mNode->SetSubdivisionCandidate(NULL); // HACK
478}
479
480
481void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
482{
483        // we have either a object space or view space split
484        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
485        {
486                Debug << "collecting candidates after view space split" << endl;
487                CollectViewSpaceDirtyList(dirtyList);
488        }
489        else // object space split
490        {       Debug << "collecting candidates after object space split" << endl;
491                CollectObjectSpaceDirtyList(dirtyList);
492        }
493}
494
495
496void HierarchyManager::RepairQueue()
497{
498        // TODO
499        // for each update of the view space partition:
500        // the candidates from object space partition which
501        // have been afected by the view space split (the kd split candidates
502        // which saw the view cell which was split) must be reevaluated
503        // (maybe not locally, just reinsert them into the queue)
504        //
505        // vice versa for the view cells
506        // for each update of the object space partition
507        // reevaluate split candidate for view cells which saw the split kd cell
508        //
509        // the priority queue update can be solved by implementing a binary heap
510        // (explicit data structure, binary tree)
511        // *) inserting and removal is efficient
512        // *) search is not efficient => store queue position with each
513        // split candidate
514
515        // collect list of "dirty" candidates
516        vector<SubdivisionCandidate *> dirtyList;
517        Debug << "collecting dirty candidates" << endl;
518        CollectDirtyCandidates(dirtyList);
519       
520        //-- reevaluate the dirty list
521
522        vector<SubdivisionCandidate *>::const_iterator sit, sit_end = dirtyList.end();
523       
524        Debug << "collected " << (int)dirtyList.size() << " candidates" << endl;
525
526        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
527        {
528                SubdivisionCandidate* sc = *sit;
529                float rcd = sc->GetRenderCostDecrease();
530                Debug << "here6 " << rcd << endl;
531                Debug << "here84 " << endl;
532                Debug << "here7 " << sc << endl;
533                Debug << "here90 " << sc->GetPosition() << endl;
534                Debug << "here91 " << sc->Type() << endl;
535                //Debug << "here1191" << sc->Type() << endl;
536                //Debug << "sc: " << sc << " " << sc->GetPosition() << " " << sc->Type() << endl;
537               
538                Debug << "here11" << endl;
539                mTQueue.Erase(sc); // erase from queue
540                Debug << "here2" << endl;
541
542                sc->EvalPriority(); // reevaluate
543               
544        /*      cout << "render cost decrease diff " << rcd - sc->GetRenderCostDecrease()
545                         << " old: " << rcd << " new " << sc->GetRenderCostDecrease()
546                         << " type " << sc->Type() << endl;*/
547
548                mTQueue.Push(sc); // reinsert
549        }
550}
551
552
553void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
554{
555        // the type of the view cells hierarchy
556        switch (mObjectSpaceSubdivisonType)
557        {
558        case KD_BASED_OBJ_SUBDIV:
559                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
560                mOspTree->Export(stream);
561                stream << endl << "</ObjectSpaceHierarchy>" << endl;
562                break;
563               
564        case BV_BASED_OBJ_SUBDIV:
565                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
566                mBvHierarchy->Export(stream);
567                stream << endl << "</ObjectSpaceHierarchy>" << endl;
568                break;
569        }
570}
571
572
573bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
574                                                                          const Vector3 &hitPoint,
575                                                                          ViewCell *vc,
576                                                                          const float pdf,
577                                                                          float &contribution) const
578{
579        if (!obj) return false;
580
581        switch (mObjectSpaceSubdivisonType)
582        {
583        case NO_OBJ_SUBDIV:
584                // potentially visible objects
585                return vc->AddPvsSample(obj, pdf, contribution);
586
587        case KD_BASED_OBJ_SUBDIV:
588                {
589                        // potentially visible kd cells
590                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
591                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
592                }
593        case BV_BASED_OBJ_SUBDIV:
594                {
595                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
596                        return mBvHierarchy->AddLeafToPvs(leaf, vc, pdf, contribution);
597                }
598        default:
599                return false;
600        }
601}
602
603
604void HierarchyManager::PrintObjectSpaceHierarchyStatistics(ofstream &stream) const
605{
606        switch (mObjectSpaceSubdivisonType)
607        {
608        case KD_BASED_OBJ_SUBDIV:
609                {
610                        stream << mOspTree->GetStatistics();
611                        break;
612                }
613        case BV_BASED_OBJ_SUBDIV:
614                {
615                        stream << mBvHierarchy->GetStatistics();
616                        break;
617                }
618        default:
619                break;
620        }
621}
622
623
624void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
625                                                                                                  const ObjectContainer &objects) const
626{
627        switch (mObjectSpaceSubdivisonType)
628        {
629        case KD_BASED_OBJ_SUBDIV:
630                {
631                        ExportOspTree(exporter, objects);
632                        break;
633                }
634        case BV_BASED_OBJ_SUBDIV:
635                {
636                        ExportBvHierarchy(exporter, objects);
637                        break;
638                }
639        default:
640                break;
641        }
642}
643
644
645void HierarchyManager::ExportBvHierarchy(Exporter *exporter,
646                                                                                 const ObjectContainer &objects) const
647{
648        exporter->SetWireframe();
649        exporter->ExportBvHierarchy(*mBvHierarchy, 0);
650}
651
652
653void HierarchyManager::ExportOspTree(Exporter *exporter,
654                                                                         const ObjectContainer &objects) const
655{
656        if (0) exporter->ExportGeometry(objects);
657                       
658        exporter->SetWireframe();
659        exporter->ExportOspTree(*mOspTree, 0);
660}
661
662
663void HierarchyManager::ConstructSequential(const VssRayContainer &sampleRays,
664                                                                                   const ObjectContainer &objects,
665                                                                                   AxisAlignedBox3 *forcedViewSpace)
666{
667        // rays clipped in view space and in object space
668        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
669       
670
671        /////////////////////////////////////////////////////////////
672        // view space space partition
673        /////////////////////////////////////////////////////////////
674
675
676        // use objects for evaluating vsp tree construction
677        const int savedobjectSpaceSubdivisionType = mObjectSpaceSubdivisonType;
678        mObjectSpaceSubdivisonType = NO_OBJ_SUBDIV;
679
680        SubdivisionCandidate *vsc =
681                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
682       
683        // add to queue
684        mTQueue.Push(vsc);
685
686        long startTime = GetTime();
687        cout << "starting vsp construction ... " << endl;
688
689        mVspTree->mVspStats.Reset();
690        mVspTree->mVspStats.Start();
691
692        // all objects can be seen from everywhere
693        mTotalCost = (float)dynamic_cast<VspTree::VspSubdivisionCandidate *>(vsc)->mParentData.mPvs;
694
695        const bool repairQueue = false;
696        // process view space candidates
697        RunConstruction(repairQueue);
698
699        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
700        mVspTree->mVspStats.Stop();
701
702        // reset subdivision type
703        mObjectSpaceSubdivisonType = savedobjectSpaceSubdivisionType;
704
705
706        /////////////////////////////////////////////////////////////
707        // object space partition
708        /////////////////////////////////////////////////////////////
709       
710       
711        switch (mObjectSpaceSubdivisonType)
712        {
713        case KD_BASED_OBJ_SUBDIV:
714                {
715                        ConstructOspTree(sampleRays, objects);
716                        break;
717                }
718        case BV_BASED_OBJ_SUBDIV:
719                {
720                        ConstructBvHierarchy(sampleRays, objects);
721                        break;
722                }
723        default:
724                break;
725        }
726}
727
728
729}
Note: See TracBrowser for help on using the repository browser.