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

Revision 1418, 22.8 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 "IntersectableWrapper.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):
38mObjectSpaceSubdivisionType(objectSpaceSubdivisionType),
39mVspTree(vspTree),
40mOspTree(NULL),
41mBvHierarchy(NULL)
42{
43        switch(mObjectSpaceSubdivisionType)
44        {
45        case KD_BASED_OBJ_SUBDIV:
46                mOspTree = new OspTree();
47                mOspTree->mVspTree = mVspTree;
48                mOspTree->mHierarchyManager = this;
49                break;
50        case BV_BASED_OBJ_SUBDIV:
51        mBvHierarchy = new BvHierarchy();
52                mBvHierarchy->mHierarchyManager = this;
53                break;
54        default:
55                break;
56        }
57
58        // hierarchy manager links view space partition and object space partition
59        mVspTree->mHierarchyManager = this;
60       
61        ParseEnvironment();
62}
63
64
65HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree):
66mObjectSpaceSubdivisionType(KD_BASED_OBJ_SUBDIV),
67mVspTree(vspTree),
68mBvHierarchy(NULL)
69{
70        mOspTree = new OspTree(*kdTree);
71        mOspTree->mVspTree = mVspTree;
72
73        mVspTree->mHierarchyManager = this;
74
75        ParseEnvironment();
76}
77
78
79void HierarchyManager::ParseEnvironment()
80{
81        char subdivisionStatsLog[100];
82        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
83                subdivisionStatsLog);
84        mSubdivisionStats.open(subdivisionStatsLog);
85
86        Environment::GetSingleton()->GetFloatValue(
87                "Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
88        Environment::GetSingleton()->GetIntValue(
89                "Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
90
91        Environment::GetSingleton()->GetBoolValue(
92                "Hierarchy.Construction.startWithObjectSpace", mStartWithObjectSpace);
93
94        Environment::GetSingleton()->GetIntValue(
95                "Hierarchy.Termination.maxLeaves", mTermMaxLeaves);
96
97        Environment::GetSingleton()->GetIntValue(
98                "Hierarchy.Construction.type", mConstructionType);
99
100        Environment::GetSingleton()->GetIntValue(
101                "Hierarchy.Construction.minDepthForOsp", mMinDepthForObjectSpaceSubdivion);
102
103        Environment::GetSingleton()->GetIntValue(
104                "Hierarchy.Construction.minDepthForVsp", mMinDepthForViewSpaceSubdivion);
105       
106        Environment::GetSingleton()->GetBoolValue(
107                "Hierarchy.Construction.repairQueue", mRepairQueue);
108
109        Debug << "******** Hierachy Manager Parameters ***********" << endl;
110        Debug << "max leaves: " << mTermMaxLeaves << endl;
111        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
112        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
113        Debug << "construction type: " << mConstructionType << endl;
114        Debug << "min depth for object space subdivision: " << mMinDepthForObjectSpaceSubdivion << endl;
115        Debug << "repair queue: " << mRepairQueue << endl;
116}
117
118
119HierarchyManager::~HierarchyManager()
120{
121        DEL_PTR(mOspTree);
122        //DEL_PTR(mVspTree);
123        DEL_PTR(mBvHierarchy);
124}
125
126
127int HierarchyManager::GetObjectSpaceSubdivisionType() const
128{
129        return mObjectSpaceSubdivisionType;
130}
131
132
133int HierarchyManager::GetViewSpaceSubdivisionType() const
134{
135        return mViewSpaceSubdivisionType;
136}
137
138
139void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
140{
141        mVspTree->SetViewCellsManager(vcm);
142
143        if (mOspTree)
144                mOspTree->SetViewCellsManager(vcm);
145        else if (mBvHierarchy)
146                mBvHierarchy->SetViewCellsManager(vcm);
147}
148
149
150void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
151{
152        mVspTree->SetViewCellsTree(vcTree);
153}
154
155
156VspTree *HierarchyManager::GetVspTree()
157{
158        return mVspTree;
159}
160
161
162AxisAlignedBox3 HierarchyManager::GetViewSpaceBox() const
163{
164        return mVspTree->mBoundingBox;
165}
166
167
168AxisAlignedBox3 HierarchyManager::GetObjectSpaceBox() const
169{
170        switch (mObjectSpaceSubdivisionType)
171        {
172        case KD_BASED_OBJ_SUBDIV:
173                return mOspTree->mBoundingBox;
174        case BV_BASED_OBJ_SUBDIV:
175                return mBvHierarchy->mBoundingBox;
176        default:
177                // empty box
178                return AxisAlignedBox3();
179        }
180}
181
182
183SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate()
184{
185        SubdivisionCandidate *splitCandidate = mTQueue.Top();
186        mTQueue.Pop();
187
188        return splitCandidate;
189}
190
191
192void HierarchyManager::EvalSubdivisionStats(const SubdivisionCandidate &tData)
193{
194        const float costDecr = tData.GetRenderCostDecrease();
195
196        switch (mObjectSpaceSubdivisionType)
197        {
198        case KD_BASED_OBJ_SUBDIV:
199                AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
200                                                        costDecr,
201                                                        mTotalCost
202                                                        );
203                break;
204        case BV_BASED_OBJ_SUBDIV:
205                AddSubdivisionStats(mBvHierarchy->mBvhStats.Leaves() + mVspTree->mVspStats.Leaves(),
206                                                        costDecr,
207                                                        mTotalCost
208                                                        );
209                break;
210        default:
211                AddSubdivisionStats(mVspTree->mVspStats.Leaves(),
212                                                        costDecr,
213                                                        mTotalCost
214                                                        );
215                break;
216        }
217}
218
219
220void HierarchyManager::AddSubdivisionStats(const int splits,
221                                                                                   const float renderCostDecr,
222                                                                                   const float totalRenderCost)
223{
224        mSubdivisionStats
225                        << "#Splits\n" << splits << endl
226                        << "#RenderCostDecrease\n" << renderCostDecr << endl
227                        << "#TotalRenderCost\n" << totalRenderCost << endl;
228                        //<< "#AvgRenderCost\n" << avgRenderCost << endl;
229}
230
231
232bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
233{
234        return (0
235                || (mHierarchyStats.Leaves() >= mTermMaxLeaves)
236                //|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
237                ||      candidate->GlobalTerminationCriteriaMet()
238                );
239}
240
241
242void HierarchyManager::Construct(const VssRayContainer &sampleRays,
243                                                                 const ObjectContainer &objects,
244                                                                 AxisAlignedBox3 *forcedViewSpace)
245{
246        mHierarchyStats.Reset();
247        mHierarchyStats.Start();
248       
249        mTotalCost = (float)objects.size();
250        Debug << "setting total cost to " << mTotalCost << endl;
251
252        const long startTime = GetTime();
253        cout << "Constructing view space / object space tree ... \n";
254       
255        // compute view space bounding box
256        mVspTree->ComputeBoundingBox(sampleRays, forcedViewSpace);
257
258        // use objects for evaluating vsp tree construction in the first levels
259        // of the subdivision
260        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
261        mObjectSpaceSubdivisionType = NO_OBJ_SUBDIV;
262
263        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
264        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
265
266        // start with view space subdivison: prepare vsp tree for traversal
267        if (StartViewSpaceSubdivision())
268        {
269                mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
270                PrepareViewSpaceSubdivision(sampleRays, objects);
271        }
272       
273        // start object space subdivision immediately?
274        if (StartObjectSpaceSubdivision())
275        {
276                mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
277                PrepareObjectSpaceSubdivision(sampleRays, objects);
278        }
279
280        // process object space candidates
281        RunConstruction(sampleRays, objects, forcedViewSpace);
282       
283        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
284
285        cout << "here5 " << GetViewSpaceBox() << endl;
286        cout << "here6 " << GetObjectSpaceBox() << endl;
287        mHierarchyStats.Stop();
288        mVspTree->mVspStats.Stop();
289        FinishObjectSpaceSubdivision(objects);
290
291        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
292        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
293}
294
295
296void HierarchyManager::PrepareViewSpaceSubdivision(const VssRayContainer &sampleRays,
297                                                                                                   const ObjectContainer &objects)
298{
299        cout << "starting view space hierarchy construction ... " << endl;
300
301        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
302        SubdivisionCandidate *vsc =
303                mVspTree->PrepareConstruction(sampleRays, *viewSpaceRays);
304
305        mTQueue.Push(vsc);
306}
307
308
309void HierarchyManager::PrepareObjectSpaceSubdivision(const VssRayContainer &sampleRays,
310                                                                                                         const ObjectContainer &objects)
311{
312        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
313        {
314                PrepareOspTree(sampleRays, objects);
315        }
316        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
317        {
318                PrepareBvHierarchy(sampleRays, objects);
319        }
320}
321
322
323void HierarchyManager::PrepareBvHierarchy(const VssRayContainer &sampleRays,
324                                                                                  const ObjectContainer &objects)
325
326{
327        cout << "starting bv hierarchy construction ... " << endl;
328        mBvHierarchy->CreateRoot(objects);
329
330        // compute first candidate
331        SubdivisionCandidate *sc =
332                mBvHierarchy->PrepareConstruction(sampleRays, objects);
333
334        mTotalCost = mBvHierarchy->mTotalCost;
335        Debug << "\nreseting cost, new total cost: " << mTotalCost << endl;
336
337    mTQueue.Push(sc);
338}
339
340
341void HierarchyManager::PrepareOspTree(const VssRayContainer &sampleRays,
342                                                                          const ObjectContainer &objects)
343{
344        cout << "starting osp tree construction ... " << endl;
345
346        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
347
348        // start with one big kd cell - all objects can be seen from everywhere
349        // note: only true for view space = object space
350
351        // compute first candidate
352        SubdivisionCandidate *osc =
353                mOspTree->PrepareConstruction(sampleRays, objects, *objectSpaceRays);
354
355        mTotalCost = mOspTree->mTotalCost;
356        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
357       
358    mTQueue.Push(osc);
359}
360
361
362bool HierarchyManager::ApplySubdivisionCandidate(SubdivisionCandidate *sc)
363{
364        const bool globalTerminationCriteriaMet = GlobalTerminationCriteriaMet(sc);
365        const bool vspSplit = (sc->Type() == SubdivisionCandidate::VIEW_SPACE);
366
367        if (vspSplit)
368        {
369                VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
370
371                if (n->IsLeaf()) // local or global termination criteria failed
372                        return false;
373        }
374        else
375        {
376                if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
377                {
378                        KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
379                        // local or global termination criteria failed
380                        if (n->IsLeaf())
381                                return false;
382                }
383                else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
384                {
385                        BvhNode *n = mBvHierarchy->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
386                        // local or global termination criteria failed
387                        if (n->IsLeaf())
388                                return false;
389                }
390        }
391
392        return true;
393}
394
395
396int HierarchyManager::GetObjectSpaceSubdivisionDepth() const
397{
398        int maxDepth = 0;
399
400        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
401        {
402                maxDepth = mOspTree->mOspStats.maxDepth;
403        }
404        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
405        {
406                maxDepth = mBvHierarchy->mBvhStats.maxDepth;
407        }
408
409        return maxDepth;
410}
411
412
413bool HierarchyManager::StartObjectSpaceSubdivision() const
414{
415        // view space construction already started
416        if (ObjectSpaceSubdivisionConstructed())
417                return false;
418
419        // start immediately with object space subdivision?
420        if (mStartWithObjectSpace)
421                return true;
422
423        // is the queue empty again?
424        if (ViewSpaceSubdivisionConstructed() && mTQueue.Empty())
425                return true;
426
427        // has the depth for subdivision been reached?
428        return
429                ((mConstructionType == INTERLEAVED) &&
430                 (mMinDepthForObjectSpaceSubdivion <= mVspTree->mVspStats.maxDepth));
431}
432
433
434bool HierarchyManager::StartViewSpaceSubdivision() const
435{
436        // view space construction already started
437        if (ViewSpaceSubdivisionConstructed())
438                return false;
439
440        // start immediately with view space subdivision?
441        if (!mStartWithObjectSpace)
442                return true;
443
444        // is the queue empty again?
445        if (ObjectSpaceSubdivisionConstructed() && mTQueue.Empty())
446                return true;
447
448        // has the depth for subdivision been reached?
449        return
450                ((mConstructionType == INTERLEAVED) &&
451                 (mMinDepthForViewSpaceSubdivion <= GetObjectSpaceSubdivisionDepth()));
452}
453
454
455void HierarchyManager::RunConstruction(const VssRayContainer &sampleRays,
456                                                                           const ObjectContainer &objects,
457                                                                           AxisAlignedBox3 *forcedViewSpace)
458{
459        mHierarchyStats.nodes = 0;
460        mGlobalCostMisses = 0;
461
462        int i = 0;
463        while (!FinishedConstruction())
464        {
465                mCurrentCandidate = NextSubdivisionCandidate();   
466                mTotalCost -= mCurrentCandidate->GetRenderCostDecrease();
467
468                // cost ratio of cost decrease / totalCost
469                const float costRatio = mCurrentCandidate->GetRenderCostDecrease() / mTotalCost;
470
471                //Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
472                if (costRatio < mTermMinGlobalCostRatio)
473                {
474                        ++ mGlobalCostMisses;
475                }
476               
477                ///////////////////
478                //-- subdivide leaf node
479
480                if (ApplySubdivisionCandidate(mCurrentCandidate))
481                {
482                        cout << mCurrentCandidate->Type() << " ";
483                        if (0) cout << "subdividing candidate " << ++ i << " of type " << mCurrentCandidate->Type() << endl;
484                        mHierarchyStats.nodes += 2;
485
486                        // subdivision successful
487                        EvalSubdivisionStats(*mCurrentCandidate);
488               
489                        // reevaluate candidates affected by the split for view space splits,
490                        // this would be object space splits and other way round
491                        if (mRepairQueue) RepairQueue();
492                }
493
494                // we use objects for evaluating vsp tree construction until
495                // a certain depth once a certain depth existiert ...
496                if (StartObjectSpaceSubdivision())
497                {
498                        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
499
500                        cout << "\nstarting object space subdivision at depth "
501                                 << mVspTree->mVspStats.maxDepth << " ("
502                                 << mMinDepthForObjectSpaceSubdivion << ") " << endl;
503
504                        PrepareObjectSpaceSubdivision(sampleRays, objects);
505
506                        cout << "reseting queue ... ";
507                        ResetQueue();
508                        cout << "finished" << endl;
509                }
510
511                if (StartViewSpaceSubdivision())
512                {
513                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
514
515                        cout << "\nstarting view space subdivision at depth "
516                                 << GetObjectSpaceSubdivisionDepth() << " ("
517                                 << mMinDepthForViewSpaceSubdivion << ") " << endl;
518
519                        PrepareViewSpaceSubdivision(sampleRays, objects);
520
521                        cout << "reseting queue ... ";
522                        ResetQueue();
523                        cout << "finished" << endl;
524                }
525
526                DEL_PTR(mCurrentCandidate);
527        }
528}
529
530
531bool HierarchyManager::FinishedConstruction() const
532{
533        return mTQueue.Empty();
534}
535
536
537bool HierarchyManager::ObjectSpaceSubdivisionConstructed() const
538{
539        switch (mObjectSpaceSubdivisionType)
540        {
541        case KD_BASED_OBJ_SUBDIV:
542                return mOspTree && mOspTree->GetRoot();
543        case BV_BASED_OBJ_SUBDIV:
544                return mBvHierarchy && mBvHierarchy->GetRoot();
545        default:
546        return false;
547        }
548}
549
550
551bool HierarchyManager::ViewSpaceSubdivisionConstructed() const
552{
553        return mVspTree && mVspTree->GetRoot();
554}
555
556
557void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
558{
559        switch (mObjectSpaceSubdivisionType)
560        {
561        case KD_BASED_OBJ_SUBDIV:
562                {
563                        OspTree::OspSubdivisionCandidate *sc =
564                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
565
566                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
567                        break;
568                }
569        case BV_BASED_OBJ_SUBDIV:
570                {
571                        BvHierarchy::BvhSubdivisionCandidate *sc =
572                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
573
574                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
575                        break;
576                }
577        default:
578                break;
579        }
580}
581
582
583void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
584{
585        VspTree::VspSubdivisionCandidate *sc =
586                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
587
588        mVspTree->CollectDirtyCandidates(sc, dirtyList);
589}
590
591
592void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
593{
594        // we have either a object space or view space split
595        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
596        {
597                CollectViewSpaceDirtyList(dirtyList);
598        }
599        else // object space split
600        {
601                CollectObjectSpaceDirtyList(dirtyList);
602        }
603}
604
605
606void HierarchyManager::RepairQueue()
607{
608        // for each update of the view space partition:
609        // the candidates from object space partition which
610        // have been afected by the view space split (the kd split candidates
611        // which saw the view cell which was split) must be reevaluated
612        // (maybe not locally, just reinsert them into the queue)
613        //
614        // vice versa for the view cells
615        // for each update of the object space partition
616        // reevaluate split candidate for view cells which saw the split kd cell
617        //
618        // the priority queue update can be solved by implementing a binary heap
619        // (explicit data structure, binary tree)
620        // *) inserting and removal is efficient
621        // *) search is not efficient => store queue position with each
622        // split candidate
623
624        // collect list of "dirty" candidates
625        long startTime = GetTime();
626   
627        vector<SubdivisionCandidate *> dirtyList;
628        CollectDirtyCandidates(dirtyList);
629        if (0) cout << "repairing " << (int)dirtyList.size() << " candidates ... ";
630       
631        /////////////////////////////////
632        //-- reevaluate the dirty list
633
634        SubdivisionCandidateContainer::const_iterator sit, sit_end = dirtyList.end();
635       
636        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
637        {
638                SubdivisionCandidate* sc = *sit;
639                const float rcd = sc->GetRenderCostDecrease();
640               
641                mTQueue.Erase(sc); // erase from queue
642                sc->EvalPriority(); // reevaluate
643               
644                /*
645                Debug << "candidate " << sc << " reevaluated\n"
646                          << "render cost decrease diff " <<  rcd - sc->GetRenderCostDecrease()
647                          << " old: " << rcd << " new " << sc->GetRenderCostDecrease() << endl;*/
648                if (0)
649                {
650                        const float rcDiff =  rcd - sc->GetRenderCostDecrease();
651                        mTotalCost += rcDiff;
652                }
653                mTQueue.Push(sc); // reinsert
654        }
655
656        long endTime = GetTime();
657        Real timeDiff = TimeDiff(startTime, endTime);
658
659        mHierarchyStats.repairTime += timeDiff;
660
661        if (0) cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
662}
663
664
665void HierarchyManager::ResetQueue()
666{
667        SubdivisionCandidateContainer mCandidateBuffer;
668
669        // remove from queue
670        while (!mTQueue.Empty())
671        {
672                SubdivisionCandidate *candidate = NextSubdivisionCandidate();
673                candidate->EvalPriority(); // reevaluate
674                cout << ".";
675                mCandidateBuffer.push_back(candidate);
676        }
677
678        // put back into queue
679        SubdivisionCandidateContainer::const_iterator sit, sit_end = mCandidateBuffer.end();
680    for (sit = mCandidateBuffer.begin(); sit != sit_end; ++ sit)
681        {cout << ":";
682                mTQueue.Push(*sit);
683        }
684}
685
686
687void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
688{
689        // the type of the view cells hierarchy
690        switch (mObjectSpaceSubdivisionType)
691        {
692        case KD_BASED_OBJ_SUBDIV:
693                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
694                mOspTree->Export(stream);
695                stream << endl << "</ObjectSpaceHierarchy>" << endl;
696                break;         
697        case BV_BASED_OBJ_SUBDIV:
698                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
699                mBvHierarchy->Export(stream);
700                stream << endl << "</ObjectSpaceHierarchy>" << endl;
701                break;
702        }
703}
704
705
706bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
707                                                                          const Vector3 &hitPoint,
708                                                                          ViewCell *vc,
709                                                                          const float pdf,
710                                                                          float &contribution) const
711{
712        if (!obj) return false;
713
714        switch (mObjectSpaceSubdivisionType)
715        {
716        case NO_OBJ_SUBDIV:
717                // potentially visible objects
718                return vc->AddPvsSample(obj, pdf, contribution);
719        case KD_BASED_OBJ_SUBDIV:
720                {
721                        // potentially visible kd cells
722                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
723                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
724                }
725        case BV_BASED_OBJ_SUBDIV:
726                {
727                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
728                        BvhIntersectable *bvhObj = mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
729                       
730                        return vc->AddPvsSample(bvhObj, pdf, contribution);
731                }
732        default:
733                return false;
734        }
735}
736
737
738void HierarchyManager::PrintHierarchyStatistics(ofstream &stream) const
739{
740        stream << mHierarchyStats << endl;
741
742        stream << "\nview space:" << endl << endl;
743        stream << mVspTree->GetStatistics() << endl;
744        stream << "\nobject space:" << endl << endl;
745
746        switch (mObjectSpaceSubdivisionType)
747        {
748        case KD_BASED_OBJ_SUBDIV:
749                {
750                        stream << mOspTree->GetStatistics() << endl;
751                        break;
752                }
753        case BV_BASED_OBJ_SUBDIV:
754                {
755                        stream << mBvHierarchy->GetStatistics() << endl;
756                        break;
757                }
758        default:
759                break;
760        }
761}
762
763
764void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
765                                                                                                  const ObjectContainer &objects,
766                                                                                                  const AxisAlignedBox3 *bbox,
767                                                                                                  const bool exportBounds) const
768{
769        switch (mObjectSpaceSubdivisionType)
770        {
771        case KD_BASED_OBJ_SUBDIV:
772                {
773                        ExportOspTree(exporter, objects);
774                        break;
775                }
776        case BV_BASED_OBJ_SUBDIV:
777                {
778                        exporter->ExportBvHierarchy(*mBvHierarchy, 0, bbox, exportBounds);
779                        break;
780                }
781        default:
782                break;
783        }
784}
785
786
787void HierarchyManager::ExportOspTree(Exporter *exporter,
788                                                                         const ObjectContainer &objects) const
789{
790        if (0) exporter->ExportGeometry(objects);
791                       
792        exporter->SetWireframe();
793        exporter->ExportOspTree(*mOspTree, 0);
794}
795
796
797Intersectable *HierarchyManager::GetIntersectable(const VssRay &ray,
798                                                                                                  const bool isTermination) const
799{
800
801        Intersectable *obj;
802        Vector3 pt;
803        KdNode *node;
804
805        ray.GetSampleData(isTermination, pt, &obj, &node);
806       
807        if (!obj) return NULL;
808
809        switch (mObjectSpaceSubdivisionType)
810        {
811        case HierarchyManager::KD_BASED_OBJ_SUBDIV:
812                {
813                        KdLeaf *leaf = mOspTree->GetLeaf(pt, node);
814                        return mOspTree->GetOrCreateKdIntersectable(leaf);
815                }
816        case HierarchyManager::BV_BASED_OBJ_SUBDIV:
817                {
818                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
819                        return mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
820                }
821        default:
822                return obj;
823        }
824}
825
826
827void HierarchyStatistics::Print(ostream &app) const
828{
829        app << "=========== Hierarchy statistics ===============\n";
830
831        app << setprecision(4);
832
833        app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
834       
835        app << "#N_RTIME  ( Repair time [s] )\n" << repairTime * 1e-3f << " \n";
836
837        app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
838
839        app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
840
841        app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
842
843        app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
844       
845        app << "========== END OF Hierarchy statistics ==========\n";
846}
847
848
849static void RemoveRayRefs(const ObjectContainer &objects)
850{
851        ObjectContainer::const_iterator oit, oit_end = objects.end();
852        for (oit = objects.begin(); oit != oit_end; ++ oit)
853        {
854                (*oit)->mVssRays.clear();
855        }
856}
857
858
859void HierarchyManager::FinishObjectSpaceSubdivision(const ObjectContainer &objects) const
860{
861        switch (mObjectSpaceSubdivisionType)
862        {
863        case KD_BASED_OBJ_SUBDIV:
864                {
865                        mOspTree->mOspStats.Stop();
866                        break;
867                }
868        case BV_BASED_OBJ_SUBDIV:
869                {
870                        mBvHierarchy->mBvhStats.Stop();
871                        RemoveRayRefs(objects);
872                        break;
873                }
874        default:
875                break;
876        }
877}
878
879}
Note: See TracBrowser for help on using the repository browser.