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

Revision 1731, 58.6 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#include "ViewCell.h"
24
25
26namespace GtpVisibilityPreprocessor {
27
28
29#define USE_FIXEDPOINT_T 0
30
31
32/*******************************************************************/
33/*              class HierarchyManager implementation              */
34/*******************************************************************/
35
36
37HierarchyManager::HierarchyManager(const int objectSpaceSubdivisionType):
38mObjectSpaceSubdivisionType(objectSpaceSubdivisionType),
39mOspTree(NULL),
40mBvHierarchy(NULL)
41{
42        switch(mObjectSpaceSubdivisionType)
43        {
44        case KD_BASED_OBJ_SUBDIV:
45                mOspTree = new OspTree();
46                mOspTree->mVspTree = mVspTree;
47                mOspTree->mHierarchyManager = this;
48                break;
49        case BV_BASED_OBJ_SUBDIV:
50        mBvHierarchy = new BvHierarchy();
51                mBvHierarchy->mHierarchyManager = this;
52                break;
53        default:
54                break;
55        }
56
57        // hierarchy manager links view space partition and object space partition
58        mVspTree = new VspTree();
59        mVspTree->mHierarchyManager = this;
60       
61        mViewSpaceSubdivisionType = KD_BASED_VIEWSPACE_SUBDIV;
62        ParseEnvironment();
63}
64
65
66HierarchyManager::HierarchyManager(KdTree *kdTree):
67mObjectSpaceSubdivisionType(KD_BASED_OBJ_SUBDIV),
68mBvHierarchy(NULL)
69{
70        mOspTree = new OspTree(*kdTree);
71        mOspTree->mVspTree = mVspTree;
72
73        mVspTree = new VspTree();
74        mVspTree->mHierarchyManager = this;
75
76        mViewSpaceSubdivisionType = KD_BASED_VIEWSPACE_SUBDIV;
77        ParseEnvironment();
78}
79
80
81void HierarchySubdivisionStats::Print(ostream &app) const
82{
83        app << "#Pass\n" << 0 << endl
84                << "#Splits\n" << mNumSplits << endl
85                << "#TotalRenderCost\n" << mTotalRenderCost << endl
86                << "#TotalEntriesInPvs\n" << mEntriesInPvs << endl
87                << "#Memory\n" << mMemoryCost << endl
88                << "#StepsView\n" << mViewSpaceSplits << endl
89                << "#StepsObject\n" << mObjectSpaceSplits << endl
90                << "#VspOspRatio\n" << VspOspRatio() << endl
91                << "#FullMem\n" << mFullMemory << endl
92                << "#RenderCostDecrease\n" << mRenderCostDecrease << endl
93                << "#FpsPerMb\n" << FpsPerMb() << endl
94                << endl;
95}
96
97
98void HierarchyManager::ParseEnvironment()
99{
100        Environment::GetSingleton()->GetFloatValue(
101                "Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
102        Environment::GetSingleton()->GetIntValue(
103                "Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
104
105        Environment::GetSingleton()->GetBoolValue(
106                "Hierarchy.Construction.startWithObjectSpace", mStartWithObjectSpace);
107
108        Environment::GetSingleton()->GetIntValue(
109                "Hierarchy.Termination.maxLeaves", mTermMaxLeaves);
110
111        Environment::GetSingleton()->GetIntValue(
112                "Hierarchy.Construction.type", mConstructionType);
113
114        Environment::GetSingleton()->GetIntValue(
115                "Hierarchy.Construction.minDepthForOsp", mMinDepthForObjectSpaceSubdivion);
116
117        Environment::GetSingleton()->GetIntValue(
118                "Hierarchy.Construction.minDepthForVsp", mMinDepthForViewSpaceSubdivion);
119       
120        Environment::GetSingleton()->GetBoolValue(
121                "Hierarchy.Construction.repairQueue", mRepairQueue);
122
123        Environment::GetSingleton()->GetBoolValue(
124                "Hierarchy.Construction.useMultiLevel", mUseMultiLevelConstruction);
125
126        Environment::GetSingleton()->GetIntValue(
127                "Hierarchy.Construction.levels", mNumMultiLevels);
128
129        Environment::GetSingleton()->GetIntValue(
130                "Hierarchy.Construction.minStepsOfSameType", mMinStepsOfSameType);
131       
132        Environment::GetSingleton()->GetIntValue(
133                "Hierarchy.Construction.maxStepsOfSameType", mMaxStepsOfSameType);
134
135        char subdivisionStatsLog[100];
136        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats", subdivisionStatsLog);
137        mSubdivisionStats.open(subdivisionStatsLog);
138
139        Environment::GetSingleton()->GetBoolValue(
140                "Hierarchy.Construction.recomputeSplitPlaneOnRepair", mRecomputeSplitPlaneOnRepair);
141
142        Environment::GetSingleton()->GetBoolValue(
143                "Hierarchy.Construction.considerMemory", mConsiderMemory);
144
145        Environment::GetSingleton()->GetBoolValue(
146                "Hierarchy.Construction.considerMemory2", mConsiderMemory2);
147
148        Environment::GetSingleton()->GetFloatValue(
149                "Hierarchy.Termination.maxMemory", mTermMaxMemory);
150
151        Environment::GetSingleton()->GetIntValue(
152                "Hierarchy.Construction.maxRepairs", mMaxRepairs);
153
154        if (1 && mConsiderMemory2)
155        {
156                mMemoryConst = (float)(sizeof(VspLeaf *) + sizeof (VspViewCell *));
157        }
158        else
159        {
160                Environment::GetSingleton()->GetFloatValue(
161                        "Hierarchy.Termination.memoryConst", mMemoryConst);
162        }
163
164        // compare to bytes
165        mTermMaxMemory *= (1024.0f * 1024.0f);
166
167        Debug << "******** Hierarchy Manager Options ***********" << endl;
168        Debug << "max leaves: " << mTermMaxLeaves << endl;
169        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
170        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
171        Debug << "min depth for object space subdivision: " << mMinDepthForObjectSpaceSubdivion << endl;
172        Debug << "repair queue: " << mRepairQueue << endl;
173        Debug << "number of multilevels: " << mNumMultiLevels << endl;
174        Debug << "recompute split plane on repair: " << mRecomputeSplitPlaneOnRepair << endl;
175        Debug << "minimal number of steps from same type: " << mMinStepsOfSameType << endl;
176        Debug << "maximal allowed memory: " << mTermMaxMemory << endl;
177        Debug << "consider memory: " << mConsiderMemory << endl;
178        Debug << "consider memory2: " << mConsiderMemory << endl;
179        Debug << "mem const: " << mMemoryConst << endl;
180        Debug << "min steps of same kind: " << mMinStepsOfSameType << endl;
181        Debug << "max steps of same kind: " << mMaxStepsOfSameType << endl;
182        Debug << "max repairs: " << mMaxRepairs << endl;
183
184        switch (mConstructionType)
185        {
186        case 0:
187                Debug << "construction type: sequential" << endl;
188                break;
189        case 1:
190                Debug << "construction type: interleaved" << endl;
191                break;
192        case 2:
193                Debug << "construction type: gradient" << endl;
194                break;
195        case 3:
196                Debug << "construction type: multilevel" << endl;
197                break;
198        default:
199                Debug << "construction type " << mConstructionType << " unknown" << endl;
200                break;
201        }
202
203        //Debug << "min render cost " << mMinRenderCostDecrease << endl;
204        Debug << endl;
205}
206
207
208HierarchyManager::~HierarchyManager()
209{
210        DEL_PTR(mOspTree);
211        DEL_PTR(mVspTree);
212        DEL_PTR(mBvHierarchy);
213}
214
215
216int HierarchyManager::GetObjectSpaceSubdivisionType() const
217{
218        return mObjectSpaceSubdivisionType;
219}
220
221
222int HierarchyManager::GetViewSpaceSubdivisionType() const
223{
224        return mViewSpaceSubdivisionType;
225}
226
227
228void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
229{
230        mVspTree->SetViewCellsManager(vcm);
231
232        if (mOspTree)
233        {
234                mOspTree->SetViewCellsManager(vcm);
235        }
236        else if (mBvHierarchy)
237        {
238                mBvHierarchy->SetViewCellsManager(vcm);
239        }
240}
241
242
243void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
244{
245        mVspTree->SetViewCellsTree(vcTree);
246}
247
248
249VspTree *HierarchyManager::GetVspTree()
250{
251        return mVspTree;
252}
253
254/*
255AxisAlignedBox3 HierarchyManager::GetViewSpaceBox() const
256{
257        return mVspTree->mBoundingBox;
258}*/
259
260
261AxisAlignedBox3 HierarchyManager::GetObjectSpaceBox() const
262{
263        switch (mObjectSpaceSubdivisionType)
264        {
265        case KD_BASED_OBJ_SUBDIV:
266                return mOspTree->mBoundingBox;
267        case BV_BASED_OBJ_SUBDIV:
268                return mBvHierarchy->mBoundingBox;
269        default:
270                // hack: empty box
271                return AxisAlignedBox3();
272        }
273}
274
275
276SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate(SplitQueue &splitQueue)
277{
278        SubdivisionCandidate *splitCandidate = splitQueue.Top();
279        splitQueue.Pop();
280
281        return splitCandidate;
282}
283
284
285void HierarchyManager::EvalSubdivisionStats()
286{
287        // question: should I also add the mem usage of the hierarchies?
288        const float objectSpaceMem = GetObjectSpaceMemUsage();
289        const float viewSpaceMem = mVspTree->GetMemUsage();
290               
291        HierarchySubdivisionStats stats;
292        stats.mNumSplits = mHierarchyStats.Leaves();
293        stats.mTotalRenderCost = mHierarchyStats.mTotalCost;
294        stats.mEntriesInPvs = mHierarchyStats.mPvsEntries;
295        stats.mMemoryCost = mHierarchyStats.mMemory  / float(1024 * 1024);
296        stats.mFullMemory = mHierarchyStats.mMemory  / float(1024 * 1024)
297                                                + objectSpaceMem + viewSpaceMem;
298        stats.mViewSpaceSplits = mVspTree->mVspStats.Leaves();
299        stats.mObjectSpaceSplits = GetObjectSpaceSubdivisionLeaves();
300       
301        stats.Print(mSubdivisionStats);
302}
303
304
305void HierarchyManager::AddSubdivisionStats(const int splits,
306                                                                                   const float renderCostDecr,
307                                                                                   const float totalRenderCost,
308                                                                                   const int pvsEntries,
309                                                                                   const float memory,
310                                                                                   const float renderCostPerStorage,
311                                                                                   const float vspOspRatio)
312{
313        mSubdivisionStats
314                        << "#Splits\n" << splits << endl
315                        << "#RenderCostDecrease\n" << renderCostDecr << endl
316                        << "#TotalEntriesInPvs\n" << pvsEntries << endl
317                        << "#TotalRenderCost\n" << totalRenderCost << endl
318                        << "#Memory\n" << memory << endl
319                        << "#FpsPerMb\n" << renderCostPerStorage << endl
320                        << "#VspOspRatio\n" << vspOspRatio << endl
321                        << endl;
322}
323
324
325bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
326{
327        const bool terminationCriteriaMet =
328                (0
329                || (mHierarchyStats.Leaves() >= mTermMaxLeaves)
330                || (mHierarchyStats.mMemory >= mTermMaxMemory)
331                || candidate->GlobalTerminationCriteriaMet()
332                //|| (mHierarchyStats.mRenderCostDecrease < mMinRenderCostDecrease)
333                //|| (mHierarchyStats.mGlobalCostMisses >= mTermGlobalCostMissTolerance)
334                );
335
336#if GTP_DEBUG
337        if (terminationCriteriaMet)
338        {
339                Debug << "hierarchy global termination criteria met:" << endl;
340                Debug << "leaves: " << mHierarchyStats.Leaves() << " " << mTermMaxLeaves << endl;
341                Debug << "cost misses: " << mHierarchyStats.mGlobalCostMisses << " " << mTermGlobalCostMissTolerance << endl;
342                Debug << "memory: " << mHierarchyStats.mMemory << " " << mTermMaxMemory << endl;
343        }
344#endif
345
346        return terminationCriteriaMet;
347}
348
349
350void HierarchyManager::Construct(const VssRayContainer &sampleRays,
351                                                                 const ObjectContainer &objects,
352                                                                 AxisAlignedBox3 *forcedViewSpace)
353{
354        mTimeStamp = 1;
355
356        switch (mConstructionType)
357        {
358        case MULTILEVEL:
359                ConstructMultiLevel(sampleRays, objects, forcedViewSpace);
360                break;
361        case INTERLEAVED:
362        case SEQUENTIAL:
363                ConstructInterleaved(sampleRays, objects, forcedViewSpace);
364                break;
365        case GRADIENT:
366                ConstructInterleavedWithGradient(sampleRays, objects, forcedViewSpace);
367                break;
368        default:
369                break;
370        }
371
372        // hack: should be different parameter name
373        if (mUseMultiLevelConstruction)
374        {
375                cout << "starting optimizing multilevel ... " << endl;
376                // try to optimize on the above hierarchy
377                OptimizeMultiLevel(sampleRays, objects, forcedViewSpace);
378               
379                cout << "finished" << endl;
380        }
381}
382
383
384void HierarchyManager::ConstructInterleavedWithGradient(const VssRayContainer &sampleRays,
385                                                                                                                const ObjectContainer &objects,
386                                                                                                                AxisAlignedBox3 *forcedViewSpace)
387{
388        mHierarchyStats.Reset();
389        mHierarchyStats.Start();
390       
391        mHierarchyStats.mNodes = 2;
392
393        // create first nodes
394        mVspTree->Initialise(sampleRays, forcedViewSpace);
395        InitialiseObjectSpaceSubdivision(objects);
396
397        // hack: assume that object space can be seen from view space
398        mHierarchyStats.mTotalCost = mInitialRenderCost = (float)objects.size();
399        // only one entry for start
400        mHierarchyStats.mPvsEntries = 1;
401        mHierarchyStats.mMemory = (float)ObjectPvs::GetEntrySizeByte();
402
403        EvalSubdivisionStats();
404        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
405
406        const long startTime = GetTime();
407        cout << "Constructing view space / object space tree ... \n";
408       
409        SplitQueue objectSpaceQueue;
410        SplitQueue viewSpaceQueue;
411
412        int vspSteps = 0, ospSteps = 0;
413
414        // use sah for evaluating osp tree construction
415        // in the first iteration of the subdivision
416        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
417        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
418        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
419
420        // number of initial splits
421        const int minSteps = mMinStepsOfSameType;
422        const int maxSteps = mMaxStepsOfSameType;
423
424        SubdivisionCandidate *osc =
425                PrepareObjectSpaceSubdivision(sampleRays, objects);
426        objectSpaceQueue.Push(osc);
427
428        /////////////////////////
429        // calulcate initial object space splits
430       
431        SubdivisionCandidateContainer dirtyList;
432
433        // subdivide object space first
434        // for first round, use sah splits. Once view space partition
435        // has started, use render cost heuristics instead
436        ospSteps = RunConstruction(objectSpaceQueue,
437                                                           dirtyList,
438                                                           NULL,
439                                                           minSteps,
440                                                           maxSteps);
441
442        cout << "\n" << ospSteps << " object space partition steps taken" << endl;
443
444        // create view space
445        SubdivisionCandidate *vsc = PrepareViewSpaceSubdivision(sampleRays, objects);
446        viewSpaceQueue.Push(vsc);
447
448        dirtyList.clear();
449
450        // view space subdivision started
451        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
452
453        if (1)
454        {
455                // rather also start with 100 view space splits to avoid initial bias.
456                vspSteps = RunConstruction(viewSpaceQueue, dirtyList, NULL, minSteps, maxSteps);
457                cout << "\n" << vspSteps << " view space partition steps taken" << endl;
458               
459                /// Repair split queue
460                cout << "repairing queue ... " << endl;
461                RepairQueue(dirtyList, objectSpaceQueue, true);
462                cout << "repaired " << (int)dirtyList.size() << " candidates" << endl;
463
464                dirtyList.clear();
465        }
466        else
467        {
468                // the priorities were calculated for driving sah.
469                // => recalculate "real" priorities taking visibility into
470                // account so we can compare to view space splits
471                ResetQueue(objectSpaceQueue, false);
472        }
473
474        // This method subdivides view space / object space
475        // in order to converge to some optimal cost for this partition
476        // start with object space partiton
477        // then optimizate view space partition for the current osp
478        // and vice versa until iteration depth is reached.
479
480        bool lastSplitWasOsp = true;
481
482        while (!(viewSpaceQueue.Empty() && objectSpaceQueue.Empty()))
483        {
484                // decide upon next split type
485                if (viewSpaceQueue.Top()->IsDirty())
486                        viewSpaceQueue.Top()->EvalCandidate();
487
488                if (objectSpaceQueue.Top()->IsDirty())
489                        objectSpaceQueue.Top()->EvalCandidate();
490
491                const float vspPriority = viewSpaceQueue.Top() ? viewSpaceQueue.Top()->GetPriority() : -1e20f;
492                const float ospPriority = objectSpaceQueue.Top() ? objectSpaceQueue.Top()->GetPriority() : -1e20f;
493               
494                cout << "new decicion, vsp: " << vspPriority << ", osp: " << ospPriority << endl;
495
496                // should view or object space be subdivided further?
497                if (ospPriority >= vspPriority)
498                //if (!lastSplitWasOsp)
499                {
500                        lastSplitWasOsp = true;
501                        cout << "osp" << endl;
502                       
503                        // dirtied view space candidates
504                        SubdivisionCandidateContainer dirtyVspList;
505
506                        // subdivide object space first for first round,
507                        // use sah splits. Once view space partition
508                        // has started, use render cost heuristics instead
509                        const int ospSteps = RunConstruction(objectSpaceQueue,
510                                                                                                 dirtyVspList,
511                                                                                                 viewSpaceQueue.Top(),
512                                                                                                 minSteps,
513                                                                                                 maxSteps);
514
515                        cout << "\n" << ospSteps << " object space partition steps taken" << endl;
516                        Debug << "\n" << ospSteps << " object space partition steps taken" << endl;
517
518                        /// Repair split queue, i.e., affected view space candidates
519                        cout << "repairing queue ... " << endl;
520                        RepairQueue(dirtyVspList, viewSpaceQueue, true);
521           
522                        cout << "\nrepaired " << (int)dirtyVspList.size() << " candidates" << endl;
523                }
524                else
525                {
526                        lastSplitWasOsp = false;
527                        cout << "vsp" << endl;
528                       
529                        /////////////////
530                        // subdivide view space with respect to the objects
531
532                        // dirtied object space candidates
533                        SubdivisionCandidateContainer dirtyOspList;
534
535                        // process view space candidates
536                        const int vspSteps = RunConstruction(viewSpaceQueue,
537                                                                                                 dirtyOspList,
538                                                                                                 objectSpaceQueue.Top(),
539                                                                                                 minSteps,
540                                                                                                 maxSteps);
541
542                        cout << "\n" << vspSteps << " view space partition steps taken" << endl;
543                        Debug << "\n" << vspSteps << " view space partition steps taken" << endl;
544
545                        // view space subdivision constructed
546                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
547
548                        /// Repair split queue
549                        cout << "repairing queue ... " << endl;
550                        RepairQueue(dirtyOspList, objectSpaceQueue, true);
551
552                        cout << "repaired " << (int)dirtyOspList.size() << " candidates" << endl;
553                }
554        }
555
556        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
557
558        mHierarchyStats.Stop();
559        mVspTree->mVspStats.Stop();
560
561        FinishObjectSpaceSubdivision(objects, !mUseMultiLevelConstruction);
562}
563
564
565void HierarchyManager::ConstructInterleaved(const VssRayContainer &sampleRays,
566                                                                                        const ObjectContainer &objects,
567                                                                                        AxisAlignedBox3 *forcedViewSpace)
568{
569        mHierarchyStats.Reset();
570        mHierarchyStats.Start();
571
572        // two nodes for view space and object space
573        mHierarchyStats.mNodes = 2;
574        mHierarchyStats.mPvsEntries = 1;
575        mHierarchyStats.mMemory = (float)ObjectPvs::GetEntrySizeByte();
576        mHierarchyStats.mTotalCost = (float)objects.size();
577
578        mHierarchyStats.mRenderCostDecrease = 0;
579
580        EvalSubdivisionStats();
581        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
582
583        const long startTime = GetTime();
584        cout << "Constructing view space / object space tree ... \n";
585       
586        // create only roots
587        mVspTree->Initialise(sampleRays, forcedViewSpace);
588        InitialiseObjectSpaceSubdivision(objects);
589
590        // use objects for evaluating vsp tree construction in the
591        // first levels of the subdivision
592        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
593        mObjectSpaceSubdivisionType = NO_OBJ_SUBDIV;
594
595        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
596        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
597
598        // start view space subdivison immediately?
599        if (StartViewSpaceSubdivision())
600        {
601                // prepare vsp tree for traversal
602        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
603                SubdivisionCandidate *vspSc =
604                        PrepareViewSpaceSubdivision(sampleRays, objects);
605
606                mTQueue.Push(vspSc);
607        }
608       
609        // start object space subdivision immediately?
610        if (StartObjectSpaceSubdivision())
611        {
612                mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
613                SubdivisionCandidate *ospSc =
614                        PrepareObjectSpaceSubdivision(sampleRays, objects);
615                mTQueue.Push(ospSc);
616        }
617
618        // begin subdivision
619        RunConstruction(mRepairQueue, sampleRays, objects, forcedViewSpace);
620       
621        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
622
623        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
624        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
625
626        mHierarchyStats.Stop();
627        mVspTree->mVspStats.Stop();
628       
629        FinishObjectSpaceSubdivision(objects, !mUseMultiLevelConstruction);
630}
631
632
633SubdivisionCandidate *HierarchyManager::PrepareViewSpaceSubdivision(const VssRayContainer &sampleRays,
634                                                                                                                                        const ObjectContainer &objects)
635{
636        cout << "\npreparing view space hierarchy construction ... " << endl;
637
638        // hack: reset global cost misses
639        mHierarchyStats.mGlobalCostMisses = 0;
640
641        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
642        SubdivisionCandidate *vsc =
643                mVspTree->PrepareConstruction(sampleRays, *viewSpaceRays);
644
645        /////////
646        //-- new stats
647
648        mHierarchyStats.mTotalCost = mVspTree->mTotalCost;
649       
650        cout << "\nreseting cost for vsp, new total cost: " << mHierarchyStats.mTotalCost << endl;
651
652        return vsc;
653}
654
655
656float HierarchyManager::GetObjectSpaceMemUsage() const
657{
658        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
659        {
660                // TODO;
661        }
662        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
663        {
664                return mBvHierarchy->GetMemUsage();
665        }
666
667        return -1;
668}
669
670void HierarchyManager::InitialiseObjectSpaceSubdivision(const ObjectContainer &objects)
671{
672        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
673        {
674                // TODO;
675        }
676        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
677        {
678                mBvHierarchy->Initialise(objects);
679        }
680}
681
682
683SubdivisionCandidate *HierarchyManager::PrepareObjectSpaceSubdivision(const VssRayContainer &sampleRays,
684                                                                                                                                          const ObjectContainer &objects)
685{
686        // hack: reset global cost misses
687        mHierarchyStats.mGlobalCostMisses = 0;
688
689        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
690        {
691                return PrepareOspTree(sampleRays, objects);
692        }
693        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
694        {
695                return PrepareBvHierarchy(sampleRays, objects);
696        }
697       
698        return NULL;
699}
700
701
702SubdivisionCandidate *HierarchyManager::PrepareBvHierarchy(const VssRayContainer &sampleRays,
703                                                                                                                   const ObjectContainer &objects)
704{
705        const long startTime = GetTime();
706
707        cout << "preparing bv hierarchy construction ... " << endl;
708       
709        // compute first candidate
710        SubdivisionCandidate *sc =
711                mBvHierarchy->PrepareConstruction(sampleRays, objects);
712
713        mHierarchyStats.mTotalCost = mBvHierarchy->mTotalCost;
714        Debug << "\nreseting cost, new total cost: " << mHierarchyStats.mTotalCost << endl;
715
716        cout << "finished bv hierarchy preparation in "
717                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
718         
719        return sc;
720}
721
722
723SubdivisionCandidate *HierarchyManager::PrepareOspTree(const VssRayContainer &sampleRays,
724                                                                                                           const ObjectContainer &objects)
725{
726        cout << "starting osp tree construction ... " << endl;
727
728        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
729
730        // start with one big kd cell - all objects can be seen from everywhere
731        // note: only true for view space = object space
732
733        // compute first candidate
734        SubdivisionCandidate *osc =
735                mOspTree->PrepareConstruction(sampleRays, objects, *objectSpaceRays);
736
737        mHierarchyStats.mTotalCost = mOspTree->mTotalCost;
738        Debug << "\nreseting cost for osp, new total cost: " << mHierarchyStats.mTotalCost << endl;
739       
740    return osc;
741}
742
743
744bool HierarchyManager::ApplySubdivisionCandidate(SubdivisionCandidate *sc,
745                                                                                                 SplitQueue &splitQueue,
746                                                                                                 const bool repairQueue)
747{
748        const bool terminationCriteriaMet = GlobalTerminationCriteriaMet(sc);
749        const bool success = sc->Apply(splitQueue, terminationCriteriaMet);
750
751        if (!success) // split was not taken
752        {
753                return false;
754        }
755
756        ///////////////
757        //-- split was successful => update stats and queue
758
759    // cost ratio of cost decrease / totalCost
760        const float costRatio = sc->GetRenderCostDecrease() / mHierarchyStats.mTotalCost;
761        //Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
762       
763        if (costRatio < mTermMinGlobalCostRatio)
764        {
765                ++ mHierarchyStats.mGlobalCostMisses;
766        }
767       
768        cout << sc->Type() << " ";
769               
770        /////////////
771        // update stats
772
773        mHierarchyStats.mNodes += 2;
774        mHierarchyStats.mTotalCost -= sc->GetRenderCostDecrease();
775
776        const int pvsEntriesIncr = sc->GetPvsEntriesIncr();
777        mHierarchyStats.mPvsEntries += pvsEntriesIncr;
778        //cout << "pvs entries: " << pvsEntriesIncr << " " << mHierarchyStats.pvsEntries << endl;
779
780        // memory size in byte
781        mHierarchyStats.mMemory += (float)ObjectPvs::GetEntrySizeByte() * pvsEntriesIncr;
782        mHierarchyStats.mRenderCostDecrease = sc->GetRenderCostDecrease();
783
784        static float memoryCount = 0;
785
786        if (mHierarchyStats.mMemory > memoryCount)
787        {
788                memoryCount += 100000;
789                cout << "\nstorage cost: " << mHierarchyStats.mMemory / float(1024 * 1024)
790                         << " MB, steps: " << mHierarchyStats.Leaves() << endl;
791        }
792
793        // output stats
794        EvalSubdivisionStats();
795               
796        if (repairQueue)
797        {
798                // reevaluate candidates affected by the split for view space splits,
799                // this would be object space splits and other way round
800                vector<SubdivisionCandidate *> dirtyList;
801                sc->CollectDirtyCandidates(dirtyList, false);
802
803                RepairQueue(dirtyList, splitQueue, mRecomputeSplitPlaneOnRepair);
804        }
805
806        return true;
807}
808
809
810int HierarchyManager::GetObjectSpaceSubdivisionDepth() const
811{
812        int maxDepth = 0;
813
814        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
815        {
816                maxDepth = mOspTree->mOspStats.maxDepth;
817        }
818        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
819        {
820                maxDepth = mBvHierarchy->mBvhStats.maxDepth;
821        }
822
823        return maxDepth;
824}
825
826
827int HierarchyManager::GetObjectSpaceSubdivisionLeaves() const
828{
829        int maxLeaves= 0;
830
831        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
832        {
833                maxLeaves = mOspTree->mOspStats.Leaves();
834        }
835        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
836        {
837                maxLeaves = mBvHierarchy->mBvhStats.Leaves();
838        }
839
840        return maxLeaves;
841}
842
843
844int HierarchyManager::GetObjectSpaceSubdivisionNodes() const
845{
846        int maxLeaves = 0;
847
848        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
849        {
850                maxLeaves = mOspTree->mOspStats.nodes;
851        }
852        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
853        {
854                maxLeaves = mBvHierarchy->mBvhStats.nodes;
855        }
856
857        return maxLeaves;
858}
859
860bool HierarchyManager::StartObjectSpaceSubdivision() const
861{
862        // view space construction already started
863        if (ObjectSpaceSubdivisionConstructed())
864                return false;
865
866        // start immediately with object space subdivision?
867        if (mStartWithObjectSpace)
868                return true;
869
870        // is the queue empty again?
871        if (ViewSpaceSubdivisionConstructed() && mTQueue.Empty())
872                return true;
873
874        // has the depth for subdivision been reached?
875        return
876                ((mConstructionType == INTERLEAVED) &&
877                 (mMinStepsOfSameType <= mVspTree->mVspStats.nodes));
878}
879
880
881bool HierarchyManager::StartViewSpaceSubdivision() const
882{
883        // view space construction already started
884        if (ViewSpaceSubdivisionConstructed())
885                return false;
886
887        // start immediately with view space subdivision?
888        if (!mStartWithObjectSpace)
889                return true;
890
891        // is the queue empty again?
892        if (ObjectSpaceSubdivisionConstructed() && mTQueue.Empty())
893                return true;
894
895        // has the depth for subdivision been reached?
896        return
897                ((mConstructionType == INTERLEAVED) &&
898                 (mMinStepsOfSameType <= GetObjectSpaceSubdivisionLeaves()));
899}
900
901
902void HierarchyManager::RunConstruction(const bool repairQueue,
903                                                                           const VssRayContainer &sampleRays,
904                                                                           const ObjectContainer &objects,
905                                                                           AxisAlignedBox3 *forcedViewSpace)
906{
907        while (!FinishedConstruction())
908        {
909                SubdivisionCandidate *sc = NextSubdivisionCandidate(mTQueue);   
910       
911                ///////////////////
912                //-- subdivide leaf node
913
914                ApplySubdivisionCandidate(sc, mTQueue, repairQueue);
915                               
916                // we use objects for evaluating vsp tree construction until
917                // a certain depth once a certain depth existiert ...
918                if (StartObjectSpaceSubdivision())
919                {
920                        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
921
922                        cout << "\nstarting object space subdivision after "
923                                 << mVspTree->mVspStats.nodes << " (" << mMinStepsOfSameType << ") steps, mem="
924                                 << mHierarchyStats.mMemory / float(1024 * 1024) << " MB" << endl;
925
926                        SubdivisionCandidate *ospSc = PrepareObjectSpaceSubdivision(sampleRays, objects);
927                       
928                        cout << "reseting queue ... ";
929                        ResetQueue(mTQueue, mRecomputeSplitPlaneOnRepair);
930                        cout << "finished" << endl;
931
932                        mTQueue.Push(ospSc);
933                }
934
935                if (StartViewSpaceSubdivision())
936                {
937                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
938
939                        cout << "\nstarting view space subdivision at "
940                                 << GetObjectSpaceSubdivisionLeaves() << " ("
941                                 << mMinStepsOfSameType << ") , mem="
942                                 << mHierarchyStats.mMemory / float(1024 * 1024) << " MB" << endl;
943
944                        SubdivisionCandidate *vspSc = PrepareViewSpaceSubdivision(sampleRays, objects);
945
946                        cout << "reseting queue ... ";
947                        ResetQueue(mTQueue, mRecomputeSplitPlaneOnRepair);
948                        cout << "finished" << endl;
949
950                        // push view space candidate                   
951                        mTQueue.Push(vspSc);
952                }
953
954                DEL_PTR(sc);
955        }
956}
957
958
959void HierarchyManager::RunConstruction(const bool repairQueue)
960{
961        // main loop
962        while (!FinishedConstruction())
963        {
964                SubdivisionCandidate *sc = NextSubdivisionCandidate(mTQueue);   
965               
966                ////////
967                //-- subdivide leaf node of either type
968        ApplySubdivisionCandidate(sc, mTQueue, repairQueue);
969               
970                DEL_PTR(sc);
971        }
972}
973
974
975int HierarchyManager::RunConstruction(SplitQueue &splitQueue,
976                                                                          SubdivisionCandidateContainer &dirtyCandidates,
977                                                                          SubdivisionCandidate *oldCandidate,
978                                                                          const int minSteps,
979                                                                          const int maxSteps)
980{
981        if (minSteps >= maxSteps)
982                cout << "error!! " << minSteps << " equal or larger maxSteps" << endl;
983
984        int steps = 0;
985        SubdivisionCandidate::NewMail();
986
987        // main loop
988        while (!splitQueue.Empty())
989        {
990                // reevaluate current candidate
991                if (splitQueue.Top()->IsDirty())
992                        splitQueue.Top()->EvalCandidate();
993               
994                const float priority = splitQueue.Top()->GetPriority();
995                const float threshold = oldCandidate ? oldCandidate->GetPriority() : 1e20f;
996
997                // minimum slope reached
998                if ((steps >= maxSteps) || ((priority < threshold) && !(steps < minSteps)))
999                {
1000                        cout << "\n**************** breaking on " << priority
1001                                 << " smaller than " << threshold << endl;
1002                        break;
1003                }
1004               
1005                ////////
1006                //-- subdivide leaf node of either type
1007
1008                SubdivisionCandidate *sc = NextSubdivisionCandidate(splitQueue);
1009                       
1010                const bool repairQueue = false;
1011                const bool success = ApplySubdivisionCandidate(sc, splitQueue, repairQueue);
1012
1013                if (success)
1014                {
1015                        sc->CollectDirtyCandidates(dirtyCandidates, true);
1016                        ++ steps;
1017                }
1018
1019                DEL_PTR(sc);
1020        }
1021
1022        return steps;
1023}
1024
1025
1026SubdivisionCandidate *HierarchyManager::ResetObjectSpaceSubdivision(const VssRayContainer &sampleRays,
1027                                                                                                                                        const ObjectContainer &objects)
1028{       
1029        SubdivisionCandidate *firstCandidate;
1030
1031        // object space partition constructed => reconstruct
1032        switch (mObjectSpaceSubdivisionType)
1033        {
1034        case BV_BASED_OBJ_SUBDIV:
1035                {
1036                        cout << "\nreseting bv hierarchy" << endl;
1037                        Debug << "old bv hierarchy:\n " << mBvHierarchy->mBvhStats << endl;
1038                               
1039                        // rather use this: remove previous nodes and add the two new ones
1040                        //mHierarchyStats.mNodes -= mBvHierarchy->mBvhStats.nodes + 1;
1041                        mHierarchyStats.mNodes = mVspTree->mVspStats.nodes;
1042                       
1043                        // create root
1044                        mBvHierarchy->Initialise(objects);
1045       
1046                        firstCandidate = mBvHierarchy->Reset(sampleRays, objects);
1047
1048                        mHierarchyStats.mTotalCost = mBvHierarchy->mTotalCost;
1049                       
1050                        //mHierarchyStats.mPvsEntries -= mBvHierarchy->mPvsEntries + 1;
1051                        mHierarchyStats.mPvsEntries = mBvHierarchy->CountViewCells(objects);
1052
1053                        mHierarchyStats.mMemory =
1054                                (float)mHierarchyStats.mPvsEntries * ObjectPvs::GetEntrySizeByte();
1055
1056                        mHierarchyStats.mRenderCostDecrease = 0;
1057
1058                        // evaluate stats before first subdivision
1059                        EvalSubdivisionStats();
1060                        cout << "finished bv hierarchy preparation" << endl;
1061                }
1062                break;
1063
1064        case KD_BASED_OBJ_SUBDIV:
1065                // TODO
1066        default:
1067                firstCandidate = NULL;
1068                break;
1069        }
1070
1071        return firstCandidate;
1072}
1073
1074
1075SubdivisionCandidate *HierarchyManager::ResetViewSpaceSubdivision(const VssRayContainer &sampleRays,
1076                                                                                                                                  const ObjectContainer &objects,
1077                                                                                                                                  AxisAlignedBox3 *forcedViewSpace)
1078{
1079        ViewCellsManager *vm = mVspTree->mViewCellsManager;
1080
1081        // HACK: rather not destroy vsp tree
1082        DEL_PTR(mVspTree);
1083        mVspTree = new VspTree();
1084
1085        mVspTree->mHierarchyManager = this;
1086        mVspTree->mViewCellsManager = vm;
1087
1088        mVspTree->Initialise(sampleRays, forcedViewSpace);
1089       
1090        //-- reset stats
1091    mHierarchyStats.mNodes = GetObjectSpaceSubdivisionNodes();//-mVspTree->mVspStats.nodes + 1;
1092       
1093        SubdivisionCandidate *vsc = PrepareViewSpaceSubdivision(sampleRays, objects);
1094       
1095        mHierarchyStats.mPvsEntries = mVspTree->mPvsEntries;
1096        mHierarchyStats.mRenderCostDecrease = 0;
1097
1098        mHierarchyStats.mMemory = (float)mHierarchyStats.mPvsEntries * ObjectPvs::GetEntrySizeByte();
1099
1100        // evaluate new stats before first subdivsiion
1101        EvalSubdivisionStats();
1102
1103        return vsc;
1104}
1105
1106
1107void HierarchyManager::ConstructMultiLevel(const VssRayContainer &sampleRays,                                                                                   
1108                                                                                   const ObjectContainer &objects,
1109                                                                                   AxisAlignedBox3 *forcedViewSpace)
1110{
1111        mHierarchyStats.Reset();
1112        mHierarchyStats.Start();
1113        mHierarchyStats.mNodes = 2;
1114       
1115        mHierarchyStats.mTotalCost = (float)objects.size();
1116        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
1117
1118        const long startTime = GetTime();
1119        cout << "Constructing view space / object space tree ... \n";
1120       
1121        // initialise view / object space
1122        mVspTree->Initialise(sampleRays, forcedViewSpace);
1123        InitialiseObjectSpaceSubdivision(objects);
1124
1125        // use sah for evaluating osp tree construction
1126        // in the first iteration of the subdivision
1127
1128        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
1129        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
1130
1131        SubdivisionCandidate *osc =
1132                PrepareObjectSpaceSubdivision(sampleRays, objects);
1133        mTQueue.Push(osc);
1134
1135        //////////////////////////
1136
1137
1138        const int limit = mNumMultiLevels;
1139        int i = 0;
1140
1141        // This method subdivides view space / object space
1142        // in order to converge to some optimal cost for this partition
1143        // start with object space partiton
1144        // then optimizate view space partition for the current osp
1145        // and vice versa until iteration depth is reached.
1146        while (1)
1147        {
1148                char subdivisionStatsLog[100];
1149                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", i);
1150                mSubdivisionStats.open(subdivisionStatsLog);
1151
1152                // subdivide object space first
1153                osc = ResetObjectSpaceSubdivision(sampleRays, objects);
1154                mTQueue.Push(osc);
1155
1156                // process object space candidates
1157                RunConstruction(false);
1158
1159                // object space subdivision constructed
1160                mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
1161
1162                cout << "iteration " << i << " of " << limit << " finished" << endl;
1163                mSubdivisionStats.close();
1164
1165                if ((i ++) >= limit)
1166                        break;
1167
1168                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", i);
1169                mSubdivisionStats.open(subdivisionStatsLog);
1170
1171
1172                /////////////////
1173                // subdivide view space with respect to the objects
1174
1175                SubdivisionCandidate *vspVc =
1176                        ResetViewSpaceSubdivision(sampleRays, objects, forcedViewSpace);
1177                mTQueue.Push(vspVc);
1178
1179                // view space subdivision constructed
1180                mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
1181               
1182                // process view space candidates
1183                RunConstruction(false);
1184
1185                cout << "iteration " << i << " of " << limit << " finished" << endl;
1186                mSubdivisionStats.close();
1187
1188                if ((i ++) >= limit)
1189                        break;
1190        }
1191       
1192        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
1193
1194        mHierarchyStats.Stop();
1195        mVspTree->mVspStats.Stop();
1196        FinishObjectSpaceSubdivision(objects);
1197}
1198
1199
1200void HierarchyManager::OptimizeMultiLevel(const VssRayContainer &sampleRays,                                                                                     
1201                                                                                  const ObjectContainer &objects,
1202                                                                                  AxisAlignedBox3 *forcedViewSpace)
1203{
1204        const long startTime = GetTime();
1205        const int limit = mNumMultiLevels;
1206
1207        // open up new subdivision
1208        mSubdivisionStats.close();
1209
1210        int steps = 0;
1211
1212        int maxViewSpaceLeaves = mVspTree->mVspStats.Leaves();
1213        int maxObjectSpaceLeaves;
1214       
1215        // set the number of leaves 'evaluated' from the previous methods
1216        // we go for the same numbers, but we try to optimize both subdivisions
1217        switch (mObjectSpaceSubdivisionType)
1218        {
1219        case BV_BASED_OBJ_SUBDIV:
1220                maxObjectSpaceLeaves = mBvHierarchy->mBvhStats.Leaves();
1221                break;
1222        case KD_BASED_OBJ_SUBDIV:
1223                maxObjectSpaceLeaves = mOspTree->mOspStats.Leaves();
1224        default:
1225                maxObjectSpaceLeaves = 0;
1226                break;
1227        }
1228
1229        // This method subdivides view space / object space
1230        // in order to converge to some optimal cost for this partition
1231        // start with object space partiton
1232        // then optimizate view space partition for the current osp
1233        // and vice versa until iteration depth is reached.
1234        while (1)
1235        {
1236                char subdivisionStatsLog[100];
1237                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", steps);
1238                mSubdivisionStats.open(subdivisionStatsLog);
1239
1240                // subdivide object space first
1241                SubdivisionCandidate *ospVc =
1242                        ResetObjectSpaceSubdivision(sampleRays, objects);
1243       
1244                // set the number of leaves 'evaluated' from the previous methods
1245                // we go for the same numbers, but we try to optimize both subdivisions
1246                mBvHierarchy->mTermMaxLeaves = maxObjectSpaceLeaves;
1247                mTQueue.Push(ospVc);
1248
1249                // process object space candidates
1250                RunConstruction(false);
1251
1252                cout << "iteration " << steps << " of " << limit << " finished" << endl;
1253                mSubdivisionStats.close();
1254
1255                if ((++ steps) >= limit)
1256                        break;
1257
1258                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", steps);
1259                mSubdivisionStats.open(subdivisionStatsLog);
1260
1261                /////////////////
1262                // subdivide view space with respect to the objects
1263
1264                SubdivisionCandidate *vspVc =
1265                        ResetViewSpaceSubdivision(sampleRays, objects, forcedViewSpace);
1266
1267                mVspTree->mMaxViewCells = maxViewSpaceLeaves;
1268                mTQueue.Push(vspVc);
1269
1270                // process view space candidates
1271                RunConstruction(false);
1272
1273                cout << "iteration " << steps << " of " << limit << " finished" << endl;
1274                mSubdivisionStats.close();
1275
1276                if ((++ steps) >= limit)
1277                        break;
1278        }
1279       
1280        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
1281
1282        mHierarchyStats.Stop();
1283        mVspTree->mVspStats.Stop();
1284        FinishObjectSpaceSubdivision(objects);
1285}
1286
1287
1288
1289bool HierarchyManager::FinishedConstruction() const
1290{
1291        return mTQueue.Empty();
1292}
1293
1294
1295bool HierarchyManager::ObjectSpaceSubdivisionConstructed() const
1296{
1297        /*switch (mObjectSpaceSubdivisionType)
1298        {
1299        case KD_BASED_OBJ_SUBDIV:
1300                return mOspTree && mOspTree->GetRoot();
1301        case BV_BASED_OBJ_SUBDIV:
1302                return mBvHierarchy && mBvHierarchy->GetRoot();
1303        default:
1304                return false;
1305        }*/
1306        return mObjectSpaceSubdivisionType != NO_OBJ_SUBDIV;
1307}
1308
1309
1310bool HierarchyManager::ViewSpaceSubdivisionConstructed() const
1311{
1312        return mViewSpaceSubdivisionType != NO_VIEWSPACE_SUBDIV;
1313        //return mVspTree && mVspTree->GetRoot();
1314}
1315
1316
1317void HierarchyManager::CollectDirtyCandidates(const SubdivisionCandidateContainer &chosenCandidates,
1318                                                                                          SubdivisionCandidateContainer &dirtyList)
1319{
1320        SubdivisionCandidateContainer::const_iterator sit, sit_end = chosenCandidates.end();
1321        SubdivisionCandidate::NewMail();
1322
1323        for (sit = chosenCandidates.begin(); sit != sit_end; ++ sit)
1324        {
1325                (*sit)->CollectDirtyCandidates(dirtyList, true);
1326        }
1327}
1328
1329
1330void HierarchyManager::RepairQueue(const SubdivisionCandidateContainer &dirtyList,
1331                                                                   SplitQueue &splitQueue,
1332                                                                   const bool recomputeSplitPlaneOnRepair)
1333{
1334        // for each update of the view space partition:
1335        // the candidates from object space partition which
1336        // have been afected by the view space split (the kd split candidates
1337        // which saw the view cell which was split) must be reevaluated
1338        // (maybe not locally, just reinsert them into the queue)
1339        //
1340        // vice versa for the view cells
1341        // for each update of the object space partition
1342        // reevaluate split candidate for view cells which saw the split kd cell
1343        //
1344        // the priority queue update can be solved by implementing a binary heap
1345        // (explicit data structure, binary tree)
1346        // *) inserting and removal is efficient
1347        // *) search is not efficient => store queue position with each
1348        // split candidate
1349
1350        // collect list of "dirty" candidates
1351        const long startTime = GetTime();
1352        if (0) cout << "repairing " << (int)dirtyList.size() << " candidates ... ";
1353
1354        const float prop = (float)mMaxRepairs / (float)dirtyList.size();
1355
1356        ///////////////////////////
1357        //-- reevaluate the dirty list
1358
1359        SubdivisionCandidateContainer::const_iterator sit, sit_end = dirtyList.end();
1360       
1361        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
1362        {
1363                // only repair a certain number of candidates
1364                if ((mMaxRepairs < (int)dirtyList.size()) && (Random(1.0f) >= prop))
1365                        continue;
1366
1367                SubdivisionCandidate* sc = *sit;
1368                const float rcd = sc->GetRenderCostDecrease();
1369               
1370                // erase from queue
1371                splitQueue.Erase(sc);
1372                // reevaluate candidate
1373                sc->EvalCandidate(recomputeSplitPlaneOnRepair);
1374                 // reinsert
1375                splitQueue.Push(sc);
1376
1377                cout << ".";
1378
1379#ifdef GTP_DEBUG
1380                Debug << "candidate " << sc << " reevaluated\n"
1381                          << "render cost decrease diff " <<  rcd - sc->GetRenderCostDecrease()
1382                          << " old: " << rcd << " new " << sc->GetRenderCostDecrease() << endl;
1383#endif 
1384        }
1385
1386        const long endTime = GetTime();
1387        const Real timeDiff = TimeDiff(startTime, endTime);
1388
1389        mHierarchyStats.mRepairTime += timeDiff;
1390
1391        if (0) cout << "repaired in " << timeDiff * 1e-3f << " secs" << endl;
1392}
1393
1394
1395void HierarchyManager::ResetQueue(SplitQueue &splitQueue, const bool recomputeSplitPlane)
1396{
1397        SubdivisionCandidateContainer mCandidateBuffer;
1398
1399        // remove from queue
1400        while (!splitQueue.Empty())
1401        {
1402                SubdivisionCandidate *candidate = NextSubdivisionCandidate(splitQueue);
1403                 // reevaluate local split plane and priority
1404                candidate->EvalCandidate(recomputeSplitPlane);
1405                cout << ".";
1406                mCandidateBuffer.push_back(candidate);
1407        }
1408
1409        // put back into queue
1410        SubdivisionCandidateContainer::const_iterator sit, sit_end = mCandidateBuffer.end();
1411    for (sit = mCandidateBuffer.begin(); sit != sit_end; ++ sit)
1412        {
1413                splitQueue.Push(*sit);
1414        }
1415}
1416
1417
1418void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
1419{
1420        // the type of the view cells hierarchy
1421        switch (mObjectSpaceSubdivisionType)
1422        {
1423        case KD_BASED_OBJ_SUBDIV:
1424                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
1425                mOspTree->Export(stream);
1426                stream << endl << "</ObjectSpaceHierarchy>" << endl;
1427                break;         
1428        case BV_BASED_OBJ_SUBDIV:
1429                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
1430                mBvHierarchy->Export(stream);
1431                stream << endl << "</ObjectSpaceHierarchy>" << endl;
1432                break;
1433        }
1434}
1435
1436
1437bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
1438                                                                          const Vector3 &hitPoint,
1439                                                                          ViewCell *vc,
1440                                                                          const float pdf,
1441                                                                          float &contribution) const
1442{
1443        if (!obj) return false;
1444
1445        switch (mObjectSpaceSubdivisionType)
1446        {
1447        case NO_OBJ_SUBDIV:
1448                {
1449                        // potentially visible objects
1450                        return vc->AddPvsSample(obj, pdf, contribution);
1451                }
1452        case KD_BASED_OBJ_SUBDIV:
1453                {
1454                        // potentially visible kd cells
1455                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
1456                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
1457                }
1458        case BV_BASED_OBJ_SUBDIV:
1459                {
1460                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
1461                        BvhIntersectable *bvhObj = mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
1462                       
1463                        return vc->AddPvsSample(bvhObj, pdf, contribution);
1464                }
1465        default:
1466                return false;
1467        }
1468}
1469
1470
1471void HierarchyManager::PrintHierarchyStatistics(ostream &stream) const
1472{
1473        stream << mHierarchyStats << endl;
1474        stream << "\nview space:" << endl << endl;
1475        stream << mVspTree->GetStatistics() << endl;
1476        stream << "\nobject space:" << endl << endl;
1477
1478        switch (mObjectSpaceSubdivisionType)
1479        {
1480        case KD_BASED_OBJ_SUBDIV:
1481                {
1482                        stream << mOspTree->GetStatistics() << endl;
1483                        break;
1484                }
1485        case BV_BASED_OBJ_SUBDIV:
1486                {
1487                        stream << mBvHierarchy->GetStatistics() << endl;
1488                        break;
1489                }
1490        default:
1491                break;
1492        }
1493}
1494
1495
1496void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
1497                                                                                                  const ObjectContainer &objects,
1498                                                                                                  const AxisAlignedBox3 *bbox,
1499                                                                                                  const bool exportBounds) const
1500{
1501        switch (mObjectSpaceSubdivisionType)
1502        {
1503        case KD_BASED_OBJ_SUBDIV:
1504                {
1505                        ExportOspTree(exporter, objects);
1506                        break;
1507                }
1508        case BV_BASED_OBJ_SUBDIV:
1509                {
1510                        exporter->ExportBvHierarchy(*mBvHierarchy, 0, bbox, exportBounds);
1511                        break;
1512                }
1513        default:
1514                break;
1515        }
1516}
1517
1518
1519void HierarchyManager::ExportOspTree(Exporter *exporter,
1520                                                                         const ObjectContainer &objects) const
1521{
1522        if (0) exporter->ExportGeometry(objects);
1523                       
1524        exporter->SetWireframe();
1525        exporter->ExportOspTree(*mOspTree, 0);
1526}
1527
1528
1529Intersectable *HierarchyManager::GetIntersectable(const VssRay &ray,
1530                                                                                                  const bool isTermination) const
1531{
1532
1533        Intersectable *obj;
1534        Vector3 pt;
1535        KdNode *node;
1536
1537        ray.GetSampleData(isTermination, pt, &obj, &node);
1538       
1539        if (!obj) return NULL;
1540
1541        switch (mObjectSpaceSubdivisionType)
1542        {
1543        case HierarchyManager::KD_BASED_OBJ_SUBDIV:
1544                {
1545                        KdLeaf *leaf = mOspTree->GetLeaf(pt, node);
1546                        return mOspTree->GetOrCreateKdIntersectable(leaf);
1547                }
1548        case HierarchyManager::BV_BASED_OBJ_SUBDIV:
1549                {
1550                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
1551                        return mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
1552                }
1553        default:
1554                return obj;
1555        }
1556}
1557
1558
1559void HierarchyStatistics::Print(ostream &app) const
1560{
1561        app << "=========== Hierarchy statistics ===============\n";
1562
1563        app << setprecision(4);
1564
1565        app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
1566       
1567        app << "#N_RTIME  ( Repair time [s] )\n" << mRepairTime * 1e-3f << " \n";
1568
1569        app << "#N_NODES ( Number of nodes )\n" << mNodes << "\n";
1570
1571        app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
1572
1573        app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
1574
1575        app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << mMaxDepth << endl;
1576
1577        app << "#N_GLOBALCOSTMISSES ( Global cost misses )\n" << mGlobalCostMisses << endl;
1578       
1579        app << "========== END OF Hierarchy statistics ==========\n";
1580}
1581
1582
1583static void RemoveRayRefs(const ObjectContainer &objects)
1584{
1585        ObjectContainer::const_iterator oit, oit_end = objects.end();
1586        for (oit = objects.begin(); oit != oit_end; ++ oit)
1587        {
1588                (*oit)->DelRayRefs();
1589        }
1590}
1591
1592
1593void HierarchyManager::FinishObjectSpaceSubdivision(const ObjectContainer &objects,
1594                                                                                                        const bool removeRayRefs) const
1595{
1596        switch (mObjectSpaceSubdivisionType)
1597        {
1598        case KD_BASED_OBJ_SUBDIV:
1599                {
1600                        mOspTree->mOspStats.Stop();
1601                        break;
1602                }
1603        case BV_BASED_OBJ_SUBDIV:
1604                {
1605                        mBvHierarchy->mBvhStats.Stop();
1606                        if (removeRayRefs)
1607                                RemoveRayRefs(objects);
1608                        break;
1609                }
1610        default:
1611                break;
1612        }
1613}
1614
1615
1616void HierarchyManager::ExportBoundingBoxes(OUT_STREAM &stream, const ObjectContainer &objects)
1617{
1618        stream << "<BoundingBoxes>" << endl;
1619           
1620        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
1621        {
1622                KdIntersectableMap::const_iterator kit, kit_end = mOspTree->mKdIntersectables.end();
1623
1624                int id = 0;
1625                for (kit = mOspTree->mKdIntersectables.begin(); kit != kit_end; ++ kit, ++ id)
1626                {
1627                        Intersectable *obj = (*kit).second;
1628                        const AxisAlignedBox3 box = obj->GetBox();
1629               
1630                        obj->SetId(id);
1631
1632                        stream << "<BoundingBox" << " id=\"" << id << "\""
1633                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
1634                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
1635                }
1636        }
1637        else
1638        {
1639                ObjectContainer::const_iterator oit, oit_end = objects.end();
1640
1641                for (oit = objects.begin(); oit != oit_end; ++ oit)
1642                {
1643                        const AxisAlignedBox3 box = (*oit)->GetBox();
1644               
1645                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
1646                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
1647                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
1648                }
1649        }
1650               
1651        stream << "</BoundingBoxes>" << endl;
1652}
1653
1654
1655class HierarchyNodeWrapper;
1656
1657
1658template <typename T> class myless
1659{
1660public:
1661        bool operator() (T v1, T v2) const
1662        {
1663                return (v1->GetMergeCost() < v2->GetMergeCost());
1664        }
1665};
1666
1667
1668typedef priority_queue<HierarchyNodeWrapper *, vector<HierarchyNodeWrapper *>,
1669                                           myless<vector<HierarchyNodeWrapper *>::value_type> > HierarchyNodeQueue;
1670
1671class HierarchyNodeWrapper
1672{
1673public:
1674        enum {VSP_NODE, BVH_NODE, VIEW_CELL};
1675
1676        virtual float GetMergeCost() const = 0;
1677        virtual int Type() const  = 0;
1678        virtual bool IsLeaf() const = 0;
1679
1680        virtual void PushChildren(HierarchyNodeQueue &tQueue) = 0;
1681};
1682
1683
1684class VspNodeWrapper: public HierarchyNodeWrapper
1685{
1686public:
1687        VspNodeWrapper(VspNode *node): mNode(node) {}
1688
1689        int Type() const { return VSP_NODE; }
1690
1691        float GetMergeCost() const { return (float) -mNode->mTimeStamp; };
1692
1693        bool IsLeaf() const { return mNode->IsLeaf(); }
1694
1695        void PushChildren(HierarchyNodeQueue &tQueue)
1696        {
1697                if (!mNode->IsLeaf())
1698                {
1699                        VspInterior *interior = dynamic_cast<VspInterior *>(mNode);
1700
1701                        tQueue.push(new VspNodeWrapper(interior->GetFront()));
1702                        tQueue.push(new VspNodeWrapper(interior->GetBack()));
1703                }
1704        }
1705
1706        VspNode *mNode;
1707};
1708
1709
1710class BvhNodeWrapper: public HierarchyNodeWrapper
1711{
1712public:
1713        BvhNodeWrapper(BvhNode *node): mNode(node) {}
1714       
1715        int Type()  const { return BVH_NODE; }
1716
1717        float GetMergeCost() const { return (float)-mNode->mTimeStamp; };
1718
1719        bool IsLeaf() const { return mNode->IsLeaf(); }
1720
1721        void PushChildren(HierarchyNodeQueue &tQueue)
1722        {
1723                if (!mNode->IsLeaf())
1724                {
1725                        BvhInterior *interior = dynamic_cast<BvhInterior *>(mNode);
1726
1727                        tQueue.push(new BvhNodeWrapper(interior->GetFront()));
1728                        tQueue.push(new BvhNodeWrapper(interior->GetBack()));
1729                }
1730        }
1731
1732        BvhNode *mNode;
1733};
1734
1735
1736class ViewCellWrapper: public HierarchyNodeWrapper
1737{
1738public:
1739
1740        ViewCellWrapper(ViewCell *vc): mViewCell(vc) {}
1741       
1742        int Type()  const { return VIEW_CELL; }
1743
1744        float GetMergeCost() const { return mViewCell->GetMergeCost(); };
1745
1746        bool IsLeaf() const { return mViewCell->IsLeaf(); }
1747
1748        void PushChildren(HierarchyNodeQueue &tQueue)
1749        {
1750                if (!mViewCell->IsLeaf())
1751                {
1752                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(mViewCell);
1753
1754                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1755
1756                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1757                        {
1758                                tQueue.push(new ViewCellWrapper(*it));
1759                        }
1760                }
1761        }
1762
1763        ViewCell *mViewCell;
1764};
1765
1766
1767void HierarchyManager::CollectBestSet(const int maxSplits,
1768                                                                          const float maxMemoryCost,
1769                                                                          ViewCellContainer &viewCells,
1770                                                                          vector<BvhNode *> &bvhNodes)
1771{
1772        HierarchyNodeQueue tqueue;
1773        //tqueue.push(new VspNodeWrapper(mVspTree->GetRoot()));
1774        tqueue.push(new ViewCellWrapper(mVspTree->mViewCellsTree->GetRoot()));
1775        tqueue.push(new BvhNodeWrapper(mBvHierarchy->GetRoot()));
1776       
1777        float memCost = 0;
1778
1779        while (!tqueue.empty())
1780        {
1781                HierarchyNodeWrapper *nodeWrapper = tqueue.top();
1782                tqueue.pop();
1783                //cout << "priority: " << nodeWrapper->GetMergeCost() << endl;
1784                // save the view cells if it is a leaf or if enough view cells have already been traversed
1785                // because of the priority queue, this will be the optimal set of v
1786                if (nodeWrapper->IsLeaf() ||
1787                        ((viewCells.size() + bvhNodes.size() + tqueue.size() + 1) >= maxSplits) ||
1788                        (memCost > maxMemoryCost)
1789                        )
1790                {
1791                        if (nodeWrapper->Type() == HierarchyNodeWrapper::VIEW_CELL)
1792                        {
1793                                //cout << "1";
1794                                ViewCellWrapper *viewCellWrapper = dynamic_cast<ViewCellWrapper *>(nodeWrapper);
1795                                viewCells.push_back(viewCellWrapper->mViewCell);
1796                        }
1797                        else
1798                        {
1799                                //cout << "0";
1800                                BvhNodeWrapper *bvhNodeWrapper = dynamic_cast<BvhNodeWrapper *>(nodeWrapper);
1801                                bvhNodes.push_back(bvhNodeWrapper->mNode);
1802                        }
1803                }
1804                else
1805                {       
1806                        nodeWrapper->PushChildren(tqueue);
1807                }
1808
1809                delete nodeWrapper;
1810        }
1811}
1812
1813
1814int HierarchyManager::ExtractStatistics(const int maxSplits,
1815                                                                                const float maxMemoryCost,
1816                                                                                float &renderCost,
1817                                                                                float &memory,
1818                                                                                int &pvsEntries,
1819                                                                                int &viewSpaceSplits,
1820                                                                                int &objectSpaceSplits)
1821{
1822        ViewCellContainer viewCells;
1823        vector<BvhNode *> bvhNodes;
1824
1825        // collect best set of view cells for this #splits
1826    CollectBestSet(maxSplits, maxMemoryCost, viewCells, bvhNodes);
1827        //cout << "here5 " << bvhNodes.size() << endl;
1828        vector<BvhNode *>::const_iterator bit, bit_end = bvhNodes.end();
1829       
1830        // set new nodes to be active
1831        for (bit = bvhNodes.begin(); bit != bit_end; ++ bit)
1832        {
1833                mBvHierarchy->SetActive(*bit);
1834        }
1835
1836        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
1837
1838        pvsEntries = 0;
1839        renderCost = 0.0f;
1840
1841        //BvhNode::NewMail();
1842        //int dummy = 0;
1843        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
1844        {
1845                float rc = 0;
1846                ViewCell *vc = *vit;
1847                ObjectPvs pvs;
1848                mVspTree->mViewCellsTree->GetPvs(vc, pvs);
1849                //dummy+=pvs.GetSize();
1850                BvhNode::NewMail();
1851
1852                // hack: should not be done here
1853                ObjectPvsMap::const_iterator oit, oit_end = pvs.mEntries.end();
1854
1855                for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
1856                {
1857                        BvhIntersectable *intersect = dynamic_cast<BvhIntersectable *>((*oit).first);
1858
1859                        BvhLeaf *leaf = intersect->GetItem();
1860                        BvhNode *activeNode = leaf->GetActiveNode();
1861
1862                        if (!activeNode->Mailed())
1863                        {
1864                                activeNode->Mail();
1865
1866                                ObjectContainer objects;
1867                                activeNode->CollectObjects(objects);
1868
1869                                ++ pvsEntries;
1870                                rc += mBvHierarchy->EvalAbsCost(objects);
1871                                //cout << " pvs: " << mBvHierarchy->EvalAbsCost(leaf->mObjects);
1872                        }
1873                }
1874
1875                rc *= vc->GetVolume();
1876                renderCost += rc;
1877        }
1878
1879        renderCost /= mVspTree->mViewCellsManager->GetViewSpaceBox().GetVolume();
1880
1881        memory = pvsEntries * ObjectPvs::GetEntrySize();
1882
1883        viewSpaceSplits = (int)viewCells.size();
1884        objectSpaceSplits = (int)bvhNodes.size();
1885
1886        //cout << "viewCells: " << (int)viewCells.size() << " nodes: " << (int)bvhNodes.size() << " rc: " << renderCost << " entries: " << pvsEntries << endl;
1887
1888        return viewCells.size() + bvhNodes.size();
1889}
1890
1891
1892void HierarchyManager::ExportStats(ofstream &stats,
1893                                                                   SplitQueue &tQueue,
1894                                                                   const ObjectContainer &objects)
1895{
1896        HierarchySubdivisionStats subStats;
1897        subStats.Reset();
1898
1899        /////////////
1900        //-- initial situation
1901
1902        subStats.mNumSplits = 0;
1903        subStats.mTotalRenderCost = (float)objects.size();
1904        subStats.mEntriesInPvs = 1;
1905        subStats.mMemoryCost = (float)ObjectPvs::GetEntrySize();
1906        subStats.mFullMemory = subStats.mMemoryCost;
1907        subStats.mViewSpaceSplits = 0;
1908        subStats.mObjectSpaceSplits = 0;
1909       
1910        subStats.Print(stats);
1911
1912        cout << "exporting vsposp stats ... " << endl;
1913
1914        //-- go through tree in the order of render cost decrease
1915        //-- which is the same order as the view cells were merged
1916        //-- or the reverse order of subdivision for subdivision-only
1917        //-- view cell hierarchies.
1918       
1919        while (!tQueue.Empty())
1920        {
1921                SubdivisionCandidate *nextCandidate = NextSubdivisionCandidate(tQueue);
1922                bool isLeaf;
1923                int timeStamp;
1924                float rcDecr;
1925                int entriesIncr;
1926
1927        if (nextCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
1928                {
1929                        timeStamp = (int)-nextCandidate->GetPriority();
1930
1931                        VspNode *newNode = mVspTree->SubdivideAndCopy(tQueue, nextCandidate);
1932                        VspNode *oldNode = (VspNode *)nextCandidate->mEvaluationHack;
1933                       
1934                        isLeaf = newNode->IsLeaf();
1935                        subStats.mRenderCostDecrease = oldNode->mRenderCostDecr;
1936                        entriesIncr = oldNode->mPvsEntriesIncr;
1937                }
1938                else
1939                {
1940                        timeStamp = (int)-nextCandidate->GetPriority();
1941                       
1942                        BvhNode *newNode = mBvHierarchy->SubdivideAndCopy(tQueue, nextCandidate);
1943                        BvhNode *oldNode = (BvhNode *)nextCandidate->mEvaluationHack;
1944                       
1945                        isLeaf = newNode->IsLeaf();
1946                        subStats.mRenderCostDecrease = oldNode->mRenderCostDecr;
1947                        entriesIncr = oldNode->mPvsEntriesIncr;
1948                }               
1949                               
1950                if (!isLeaf)
1951                {
1952                        subStats.mTotalRenderCost -= subStats.mRenderCostDecrease;
1953                        subStats.mEntriesInPvs += entriesIncr;
1954
1955                        // if (rcDecr <= 0)
1956                        if (nextCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
1957                        {
1958                                ++ subStats.mViewSpaceSplits;
1959                                cout << "v";//cout << "vsp t: " << timeStamp << " rc: " << rcDecr << " pvs: " << entriesIncr << endl;
1960                        }
1961                        else
1962                        {
1963                                ++ subStats.mObjectSpaceSplits;
1964                                cout << "o";//"osp t: " << timeStamp << " rc: " << rcDecr << " pvs: " << entriesIncr << endl;
1965                        }
1966
1967                        ++ subStats.mNumSplits;
1968
1969                        if ((subStats.mNumSplits % 500) == 499)
1970                                cout << subStats.mNumSplits << " steps taken" << endl;
1971
1972                        subStats.mMemoryCost = (float)subStats.mEntriesInPvs * (float)ObjectPvs::GetEntrySize();
1973                        subStats.mFullMemory = subStats.mMemoryCost;
1974
1975                        subStats.Print(stats);
1976                       
1977                }
1978
1979                DEL_PTR(nextCandidate);
1980        }
1981
1982        stats.close();
1983}
1984
1985
1986void HierarchyManager::EvaluateSubdivision(const VssRayContainer &sampleRays,                                                                                                                                             
1987                                                                                   const ObjectContainer &objects,
1988                                                                                   const string &filename)
1989{
1990        VspTree *oldVspTree = mVspTree;
1991        ViewCellsManager *vm = mVspTree->mViewCellsManager;
1992        BvHierarchy *oldHierarchy = mBvHierarchy;
1993
1994        mBvHierarchy = new BvHierarchy();
1995        mBvHierarchy->mHierarchyManager = this;
1996        mBvHierarchy->mViewCellsManager = vm;
1997
1998        mVspTree = new VspTree();
1999        mVspTree->mHierarchyManager = this;
2000        mVspTree->mViewCellsManager = vm;
2001
2002        // create first nodes
2003        mVspTree->Initialise(sampleRays, &oldVspTree->mBoundingBox);
2004        InitialiseObjectSpaceSubdivision(objects);
2005
2006        const long startTime = GetTime();
2007        cout << "Constructing evaluation hierarchies ... \n";
2008       
2009        ofstream stats;
2010        stats.open(filename.c_str());
2011        SplitQueue tQueue;
2012
2013        BvhNode *oldBvhRoot = oldHierarchy->GetRoot();
2014        VspNode *oldVspRoot = oldVspTree->GetRoot();
2015
2016        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
2017       
2018        SubdivisionCandidate *firstVsp = mVspTree->PrepareConstruction(sampleRays, *viewSpaceRays);
2019        SubdivisionCandidate *firstBvh = mBvHierarchy->PrepareConstruction(sampleRays, objects);
2020
2021    firstVsp->mEvaluationHack = oldVspRoot;
2022        firstBvh->mEvaluationHack = oldBvhRoot;
2023
2024        firstVsp->SetPriority((float)-oldVspRoot->mTimeStamp);
2025        firstBvh->SetPriority((float)-oldBvhRoot->mTimeStamp);
2026
2027        tQueue.Push(firstVsp);
2028        tQueue.Push(firstBvh);
2029
2030        ExportStats(stats, tQueue, objects);
2031
2032        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
2033        RemoveRayRefs(objects);
2034
2035        // view cells needed only for evaluation
2036        ViewCellContainer viewCells;
2037        mVspTree->CollectViewCells(viewCells, false);
2038       
2039        // helper trees can be destroyed
2040        DEL_PTR(mVspTree);
2041        DEL_PTR(mBvHierarchy);
2042
2043        CLEAR_CONTAINER(viewCells);
2044
2045        // reset hierarchies
2046        mVspTree = oldVspTree;
2047        mBvHierarchy = oldHierarchy;
2048
2049        // reinstall old bv refs
2050        vector<BvhLeaf *> leaves;
2051        mBvHierarchy->CollectLeaves(mBvHierarchy->GetRoot(), leaves);
2052        vector<BvhLeaf *>::const_iterator bit, bit_end = leaves.end();
2053
2054        for (bit = leaves.begin(); bit != bit_end; ++ bit)
2055        {
2056                mBvHierarchy->AssociateObjectsWithLeaf(*bit);
2057        }
2058}
2059
2060
2061void HierarchyManager::EvaluateSubdivision2(ofstream &splitsStats,
2062                                                                                        const int splitsStepSize)
2063{
2064        HierarchySubdivisionStats subStats;
2065       
2066        int splits = 0;
2067
2068        while (1)
2069        {
2070                subStats.mNumSplits = ExtractStatistics(splits,
2071                                                                                                99999.0,
2072                                                                                                subStats.mTotalRenderCost,
2073                                                                                                subStats.mMemoryCost,
2074                                                                                                subStats.mEntriesInPvs,
2075                                                                                                subStats.mViewSpaceSplits,
2076                                                                                                subStats.mObjectSpaceSplits);
2077
2078               
2079                const float objectSpaceHierarchyMem = float(
2080                                                                                          subStats.mObjectSpaceSplits * sizeof(BvhLeaf *) +
2081                                                                                          (subStats.mObjectSpaceSplits - 1) * sizeof(BvhInterior *) +
2082                                                                                          sizeof(BvHierarchy)
2083                                                                                          ) / float(1024 * 1024);
2084
2085                       
2086                const float viewSpaceHierarchyMem = float(
2087                                                                                        subStats.mViewSpaceSplits * sizeof(VspLeaf *) +
2088                                                                                        (subStats.mViewSpaceSplits - 1) * sizeof(VspInterior *) +
2089                                                                                        sizeof(VspTree)
2090                                                                                        )  / float(1024 * 1024);
2091
2092                subStats.mFullMemory = subStats.mMemoryCost + objectSpaceHierarchyMem + viewSpaceHierarchyMem;
2093               
2094                subStats.Print(splitsStats);
2095
2096                splits += splitsStepSize;
2097
2098                if (subStats.mNumSplits == mHierarchyStats.Leaves())
2099                        break;
2100        }
2101}
2102
2103
2104void HierarchyManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
2105{
2106        mBvHierarchy->CollectObjects(box, objects);
2107}
2108
2109}
Note: See TracBrowser for help on using the repository browser.