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

Revision 1779, 60.1 KB checked in by mattausch, 18 years ago (diff)

warning: this version contains bugs!!

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