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

Revision 1636, 36.4 KB checked in by mattausch, 18 years ago (diff)
RevLine 
[1237]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"
[1315]19#include "IntersectableWrapper.h"
[1237]20#include "VspTree.h"
21#include "OspTree.h"
[1259]22#include "BvHierarchy.h"
[1237]23
24
25namespace GtpVisibilityPreprocessor {
26
27
28#define USE_FIXEDPOINT_T 0
29
30
31/*******************************************************************/
32/*              class HierarchyManager implementation              */
33/*******************************************************************/
34
35
[1421]36HierarchyManager::HierarchyManager(const int objectSpaceSubdivisionType):
[1308]37mObjectSpaceSubdivisionType(objectSpaceSubdivisionType),
[1279]38mOspTree(NULL),
39mBvHierarchy(NULL)
[1237]40{
[1308]41        switch(mObjectSpaceSubdivisionType)
[1279]42        {
43        case KD_BASED_OBJ_SUBDIV:
44                mOspTree = new OspTree();
45                mOspTree->mVspTree = mVspTree;
[1379]46                mOspTree->mHierarchyManager = this;
[1279]47                break;
48        case BV_BASED_OBJ_SUBDIV:
49        mBvHierarchy = new BvHierarchy();
[1379]50                mBvHierarchy->mHierarchyManager = this;
[1279]51                break;
52        default:
53                break;
54        }
55
[1379]56        // hierarchy manager links view space partition and object space partition
[1421]57        mVspTree = new VspTree();
[1379]58        mVspTree->mHierarchyManager = this;
59       
[1580]60        mViewSpaceSubdivisionType = KD_BASED_VIEWSPACE_SUBDIV;
[1288]61        ParseEnvironment();
[1237]62}
63
64
[1421]65HierarchyManager::HierarchyManager(KdTree *kdTree):
[1308]66mObjectSpaceSubdivisionType(KD_BASED_OBJ_SUBDIV),
[1279]67mBvHierarchy(NULL)
68{
69        mOspTree = new OspTree(*kdTree);
70        mOspTree->mVspTree = mVspTree;
71
[1421]72        mVspTree = new VspTree();
[1379]73        mVspTree->mHierarchyManager = this;
[1279]74
[1580]75        mViewSpaceSubdivisionType = KD_BASED_VIEWSPACE_SUBDIV;
[1288]76        ParseEnvironment();
77}
78
79
80void HierarchyManager::ParseEnvironment()
81{
82        Environment::GetSingleton()->GetFloatValue(
83                "Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
84        Environment::GetSingleton()->GetIntValue(
85                "Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
86
[1370]87        Environment::GetSingleton()->GetBoolValue(
88                "Hierarchy.Construction.startWithObjectSpace", mStartWithObjectSpace);
89
[1293]90        Environment::GetSingleton()->GetIntValue(
[1294]91                "Hierarchy.Termination.maxLeaves", mTermMaxLeaves);
92
93        Environment::GetSingleton()->GetIntValue(
[1293]94                "Hierarchy.Construction.type", mConstructionType);
95
[1311]96        Environment::GetSingleton()->GetIntValue(
97                "Hierarchy.Construction.minDepthForOsp", mMinDepthForObjectSpaceSubdivion);
[1370]98
99        Environment::GetSingleton()->GetIntValue(
100                "Hierarchy.Construction.minDepthForVsp", mMinDepthForViewSpaceSubdivion);
[1311]101       
[1314]102        Environment::GetSingleton()->GetBoolValue(
103                "Hierarchy.Construction.repairQueue", mRepairQueue);
104
[1449]105        Environment::GetSingleton()->GetBoolValue(
[1564]106                "Hierarchy.Construction.useMultiLevel", mUseMultiLevelConstruction);
[1449]107
[1580]108        Environment::GetSingleton()->GetIntValue(
109                "Hierarchy.Construction.levels", mNumMultiLevels);
110
[1624]111        char subdivisionStatsLog[100];
112        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats", subdivisionStatsLog);
113        mSubdivisionStats.open(subdivisionStatsLog);
114
[1633]115        Environment::GetSingleton()->GetBoolValue(
116                "Hierarchy.Construction.recomputeSplitPlaneOnRepair", mRecomputeSplitPlaneOnRepair);
[1624]117
[1294]118        Debug << "******** Hierachy Manager Parameters ***********" << endl;
119        Debug << "max leaves: " << mTermMaxLeaves << endl;
[1288]120        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
121        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
[1314]122        Debug << "min depth for object space subdivision: " << mMinDepthForObjectSpaceSubdivion << endl;
123        Debug << "repair queue: " << mRepairQueue << endl;
[1580]124        Debug << "number of multilevels: " << mNumMultiLevels << endl;
[1633]125        Debug << "recompute split plane on repair: " << mRecomputeSplitPlaneOnRepair << endl;
[1632]126
127        switch (mConstructionType)
128        {
129        case 0:
130                Debug << "construction type: sequential" << endl;
131                break;
132        case 1:
133                Debug << "construction type: interleaved" << endl;
134                break;
135        case 2:
136                Debug << "construction type: gradient" << endl;
137                break;
138        case 3:
139                Debug << "construction type: multilevel" << endl;
140                break;
141        default:
142                Debug << "construction type " << mConstructionType << " unknown" << endl;
143                break;
144        }
145
[1625]146        //Debug << "min render cost " << mMinRenderCostDecrease << endl;
[1449]147        Debug << endl;
[1279]148}
149
150
151HierarchyManager::~HierarchyManager()
152{
153        DEL_PTR(mOspTree);
[1421]154        DEL_PTR(mVspTree);
[1279]155        DEL_PTR(mBvHierarchy);
156}
157
158
[1370]159int HierarchyManager::GetObjectSpaceSubdivisionType() const
160{
161        return mObjectSpaceSubdivisionType;
162}
163
164
165int HierarchyManager::GetViewSpaceSubdivisionType() const
166{
167        return mViewSpaceSubdivisionType;
168}
169
170
[1279]171void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
172{
173        mVspTree->SetViewCellsManager(vcm);
174
175        if (mOspTree)
[1576]176        {
[1279]177                mOspTree->SetViewCellsManager(vcm);
[1576]178        }
[1416]179        else if (mBvHierarchy)
[1576]180        {
[1279]181                mBvHierarchy->SetViewCellsManager(vcm);
[1576]182        }
[1279]183}
184
185
186void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
187{
188        mVspTree->SetViewCellsTree(vcTree);
189}
190
191
[1379]192VspTree *HierarchyManager::GetVspTree()
193{
194        return mVspTree;
195}
196
[1563]197/*
[1379]198AxisAlignedBox3 HierarchyManager::GetViewSpaceBox() const
199{
200        return mVspTree->mBoundingBox;
[1563]201}*/
[1379]202
203
[1416]204AxisAlignedBox3 HierarchyManager::GetObjectSpaceBox() const
205{
206        switch (mObjectSpaceSubdivisionType)
207        {
208        case KD_BASED_OBJ_SUBDIV:
209                return mOspTree->mBoundingBox;
210        case BV_BASED_OBJ_SUBDIV:
211                return mBvHierarchy->mBoundingBox;
212        default:
[1576]213                // hack: empty box
[1416]214                return AxisAlignedBox3();
215        }
216}
217
218
[1625]219SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate(SplitQueue &splitQueue)
[1237]220{
[1625]221        SubdivisionCandidate *splitCandidate = splitQueue.Top();
222        splitQueue.Pop();
[1237]223
224        return splitCandidate;
225}
226
227
[1624]228void HierarchyManager::EvalSubdivisionStats()
[1237]229{
[1580]230        //cout << "pvs entries " << mHierarchyStats.pvsEntries << endl;
[1576]231        AddSubdivisionStats(mHierarchyStats.Leaves(),
[1624]232                                                mHierarchyStats.mRenderCostDecrease,
233                                                mHierarchyStats.mTotalCost,
[1625]234                                                mHierarchyStats.mPvsEntries,
235                                                mHierarchyStats.mMemory,
236                                                1.0f / (mHierarchyStats.mTotalCost * mHierarchyStats.mMemory)
[1576]237                                                );
[1237]238}
239
240
241void HierarchyManager::AddSubdivisionStats(const int splits,
242                                                                                   const float renderCostDecr,
[1576]243                                                                                   const float totalRenderCost,
[1625]244                                                                                   const int pvsEntries,
245                                                                                   const int memory,
246                                                                                   const float renderCostPerStorage)
[1237]247{
[1308]248        mSubdivisionStats
[1237]249                        << "#Splits\n" << splits << endl
250                        << "#RenderCostDecrease\n" << renderCostDecr << endl
[1577]251                        << "#TotalEntriesInPvs\n" << pvsEntries << endl
[1625]252                        << "#TotalRenderCost\n" << totalRenderCost << endl
253                        << "#Memory\n" << memory << endl
254                        << "#RcPerMb\n" << renderCostPerStorage << endl;
[1237]255}
256
257
258bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
259{
[1421]260        const bool terminationCriteriaMet =
261                (0
[1294]262                || (mHierarchyStats.Leaves() >= mTermMaxLeaves)
[1633]263                //|| (mHierarchyStats.mGlobalCostMisses >= mTermGlobalCostMissTolerance)
[1449]264                || (candidate->GlobalTerminationCriteriaMet())
[1625]265                //|| (mHierarchyStats.mRenderCostDecrease < mMinRenderCostDecrease)
[1288]266                );
[1421]267
[1610]268#if _DEBUG
269        if (terminationCriteriaMet)
[1421]270        {
271                Debug << "hierarchy global termination criteria met:" << endl;
272                Debug << "leaves: " << mHierarchyStats.Leaves() << " " << mTermMaxLeaves << endl;
[1449]273                Debug << "cost misses: " << mHierarchyStats.mGlobalCostMisses << " " << mTermGlobalCostMissTolerance << endl;
[1421]274        }
[1610]275#endif
276
[1421]277        return terminationCriteriaMet;
[1237]278}
279
280
281void HierarchyManager::Construct(const VssRayContainer &sampleRays,
[1311]282                                                                 const ObjectContainer &objects,
283                                                                 AxisAlignedBox3 *forcedViewSpace)
[1237]284{
[1627]285        switch (mConstructionType)
[1449]286        {
[1627]287        case MULTILEVEL:
[1449]288                ConstructMultiLevel(sampleRays, objects, forcedViewSpace);
[1627]289                break;
290        case INTERLEAVED:
291        case SEQUENTIAL:
[1624]292                ConstructInterleaved(sampleRays, objects, forcedViewSpace);
[1627]293                break;
294        case GRADIENT:
295                ConstructInterleavedWithGradient(sampleRays, objects, forcedViewSpace);
296                break;
297        default:
298                break;
[1624]299        }
300}
301
302
[1626]303void HierarchyManager::ConstructInterleavedWithGradient(const VssRayContainer &sampleRays,                                                                                       
304                                                                                                                const ObjectContainer &objects,
305                                                                                                                AxisAlignedBox3 *forcedViewSpace)
[1624]306{
307        mHierarchyStats.Reset();
308        mHierarchyStats.Start();
[1625]309       
[1624]310        mHierarchyStats.mNodes = 2;
311       
312        mHierarchyStats.mTotalCost = (float)objects.size();
313        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
314
315        const long startTime = GetTime();
316        cout << "Constructing view space / object space tree ... \n";
317       
318        // compute view space bounding box
319        mVspTree->ComputeBoundingBox(sampleRays, forcedViewSpace);
320
[1633]321        SplitQueue objectSpaceQueue;
322        SplitQueue viewSpaceQueue;
323
[1624]324        // use sah for evaluating osp tree construction
325        // in the first iteration of the subdivision
326        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
327        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
328
329        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
330
[1632]331        // number of initial splits
[1634]332        int minSteps = 200;
333        float renderCostDecr = Limits::Infinity;
[1625]334
[1633]335        SubdivisionCandidate *osc =
336                PrepareObjectSpaceSubdivision(sampleRays, objects);
337       
338        objectSpaceQueue.Push(osc);
339
340        /////////////////////////
341        // calulcate initial object space splits
342       
343        SubdivisionCandidateContainer dirtyVspList;
344
345        // subdivide object space first
346        // for first round, use sah splits. Once view space partition
347        // has started, use render cost heuristics instead
348        const int ospSteps =
[1634]349                RunConstruction(objectSpaceQueue, dirtyVspList, renderCostDecr, minSteps);
[1633]350
351        cout << ospSteps << " object space partition steps taken" << endl;
352
353        SubdivisionCandidate *vsc =
354                        PrepareViewSpaceSubdivision(sampleRays, objects);
355
356        viewSpaceQueue.Push(vsc);
357
358        // view space subdivision was constructed
359        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
360
361        // don't terminate on max steps
362        //maxSteps = mTermMaxLeaves;
363
[1624]364        // This method subdivides view space / object space
365        // in order to converge to some optimal cost for this partition
366        // start with object space partiton
367        // then optimizate view space partition for the current osp
368        // and vice versa until iteration depth is reached.
[1625]369
[1633]370        while (!(viewSpaceQueue.Empty() && objectSpaceQueue.Empty()))
[1624]371        {
[1633]372                // should view or object space be subdivided further?
373                if (viewSpaceQueue.Empty() ||
374                        (!objectSpaceQueue.Empty() &&
375                        (objectSpaceQueue.Top()->GetPriority() > viewSpaceQueue.Top()->GetPriority())))
376                {
377                        // use splits of one kind until rendercost slope is reached
[1634]378                        //renderCostDecr = mHierarchyStats.mRenderCostDecrease;
379                       
380                        // lower number of minsteps: this should be solved
381                        // with render cost decrease from now
382                        //minSteps = 5;
[1580]383
[1633]384                        // dirtied view space candidates
385                        SubdivisionCandidateContainer dirtyVspList;
[1624]386
[1633]387                        // subdivide object space first
388                        // for first round, use sah splits. Once view space partition
389                        // has started, use render cost heuristics instead
390                        const int ospSteps =
[1634]391                                RunConstruction(objectSpaceQueue, dirtyVspList, renderCostDecr, minSteps);
[1624]392
[1633]393                        cout << ospSteps << " object space partition steps taken" << endl;
[1625]394               
[1633]395                        // object space subdivision constructed
396                        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
[1624]397
[1633]398                        /// Repair split queue
399                        cout << "repairing queue ... " << endl;
400                        RepairQueue(dirtyVspList, viewSpaceQueue, true);
401                        cout << "repaired " << dirtyVspList.size() << " candidates" << endl;
402                }
403                else
404                {
405                        // use splits of one kind until rendercost slope is reached
[1634]406                //      renderCostDecr = mHierarchyStats.mRenderCostDecrease;
[1624]407
[1633]408                        /////////////////
409                        // subdivide view space with respect to the objects
[1625]410
[1633]411                        SubdivisionCandidateContainer dirtyOspList;
[1624]412
[1633]413                        // process view space candidates
414                        const int vspSteps =
[1634]415                                RunConstruction(viewSpaceQueue, dirtyOspList, renderCostDecr, minSteps);
[1624]416
[1633]417                        cout << vspSteps << " view space partition steps taken" << endl;
[1625]418
[1633]419                        // view space subdivision constructed
420                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
[1624]421
[1633]422                        /// Repair split queue
423                        cout << "repairing queue ... " << endl;
424                        RepairQueue(dirtyOspList, objectSpaceQueue, true);
425                        cout << "repaired " << dirtyOspList.size() << " candidates" << endl;
426                }
[1449]427        }
[1633]428
[1624]429        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
430
431        mHierarchyStats.Stop();
432        mVspTree->mVspStats.Stop();
[1625]433
[1624]434        FinishObjectSpaceSubdivision(objects);
[1449]435}
436
437
438void HierarchyManager::ConstructInterleaved(const VssRayContainer &sampleRays,
439                                                                                        const ObjectContainer &objects,
440                                                                                        AxisAlignedBox3 *forcedViewSpace)
441{
[1308]442        mHierarchyStats.Reset();
443        mHierarchyStats.Start();
[1624]444        mHierarchyStats.mNodes = 2; // two nodes for view space and object space
[1449]445
[1624]446        mHierarchyStats.mTotalCost = (float)objects.size();
447        mHierarchyStats.mRenderCostDecrease = 0;
[1237]448
[1624]449        EvalSubdivisionStats();
450        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
451
[1311]452        const long startTime = GetTime();
[1308]453        cout << "Constructing view space / object space tree ... \n";
[1237]454       
[1379]455        // compute view space bounding box
456        mVspTree->ComputeBoundingBox(sampleRays, forcedViewSpace);
457
[1633]458        // use objects for evaluating vsp tree construction in the
459        // first levels of the subdivision
[1323]460        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
461        mObjectSpaceSubdivisionType = NO_OBJ_SUBDIV;
462
[1370]463        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
464        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
465
[1635]466        // create just one view cell
467        SubdivisionCandidate *vspSc =
468                PrepareViewSpaceSubdivision(sampleRays, objects);
469
[1632]470        // start view space subdivison immediately?
[1329]471        if (StartViewSpaceSubdivision())
472        {
[1624]473                // prepare vsp tree for traversal
[1329]474                mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
[1632]475                mTQueue.Push(vspSc);
[1329]476        }
477       
[1323]478        // start object space subdivision immediately?
479        if (StartObjectSpaceSubdivision())
480        {
481                mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
[1632]482                SubdivisionCandidate *ospSc =
483                        PrepareObjectSpaceSubdivision(sampleRays, objects);
484                mTQueue.Push(ospSc);
[1323]485        }
[1632]486
[1624]487        // begin subdivision
[1634]488        RunConstruction(mRepairQueue,
489                                        sampleRays,
490                                        objects,
[1635]491                                        forcedViewSpace,//
492                                        vspSc);
[1308]493       
[1418]494        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[1370]495
[1548]496        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
497        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
498
[1313]499        mHierarchyStats.Stop();
[1259]500        mVspTree->mVspStats.Stop();
[1418]501        FinishObjectSpaceSubdivision(objects);
[1237]502}
503
504
[1625]505SubdivisionCandidate *HierarchyManager::PrepareViewSpaceSubdivision(const VssRayContainer &sampleRays,
506                                                                                                                                        const ObjectContainer &objects)
[1311]507{
[1632]508        cout << "\npreparing view space hierarchy construction ... " << endl;
[1625]509
[1580]510        // hack: reset global cost misses
[1548]511        mHierarchyStats.mGlobalCostMisses = 0;
[1625]512
[1311]513        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
514        SubdivisionCandidate *vsc =
[1379]515                mVspTree->PrepareConstruction(sampleRays, *viewSpaceRays);
[1311]516
[1624]517        mHierarchyStats.mTotalCost = mVspTree->mTotalCost;
518        cout << "\nreseting cost for vsp, new total cost: " << mHierarchyStats.mTotalCost << endl;
[1421]519
[1625]520        return vsc;
[1311]521}
522
523
[1625]524SubdivisionCandidate *HierarchyManager::PrepareObjectSpaceSubdivision(const VssRayContainer &sampleRays,
525                                                                                                                                          const ObjectContainer &objects)
[1308]526{
[1625]527        // hack: reset global cost misses
528        mHierarchyStats.mGlobalCostMisses = 0;
[1522]529
[1308]530        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
531        {
[1625]532                return PrepareOspTree(sampleRays, objects);
[1308]533        }
534        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
535        {
[1625]536                return PrepareBvHierarchy(sampleRays, objects);
[1308]537        }
[1625]538       
539        return NULL;
[1308]540}
[1294]541
[1308]542
[1625]543SubdivisionCandidate *HierarchyManager::PrepareBvHierarchy(const VssRayContainer &sampleRays,
544                                                                                                                   const ObjectContainer &objects)
[1294]545{
[1421]546        const long startTime = GetTime();
547
548        cout << "preparing bv hierarchy construction ... " << endl;
[1548]549       
[1294]550        // compute first candidate
551        SubdivisionCandidate *sc =
552                mBvHierarchy->PrepareConstruction(sampleRays, objects);
553
[1624]554        mHierarchyStats.mTotalCost = mBvHierarchy->mTotalCost;
555        Debug << "\nreseting cost, new total cost: " << mHierarchyStats.mTotalCost << endl;
[1294]556
[1548]557        cout << "finished bv hierarchy preparation in "
558                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[1625]559         
560        return sc;
[1294]561}
562
563
[1625]564SubdivisionCandidate *HierarchyManager::PrepareOspTree(const VssRayContainer &sampleRays,
565                                                                                                           const ObjectContainer &objects)
[1294]566{
[1370]567        cout << "starting osp tree construction ... " << endl;
568
[1294]569        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
570
571        // start with one big kd cell - all objects can be seen from everywhere
572        // note: only true for view space = object space
573
574        // compute first candidate
575        SubdivisionCandidate *osc =
576                mOspTree->PrepareConstruction(sampleRays, objects, *objectSpaceRays);
577
[1624]578        mHierarchyStats.mTotalCost = mOspTree->mTotalCost;
[1625]579        Debug << "\nreseting cost for osp, new total cost: " << mHierarchyStats.mTotalCost << endl;
[1294]580       
[1625]581    return osc;
[1294]582}
583
584
[1624]585bool HierarchyManager::ApplySubdivisionCandidate(SubdivisionCandidate *sc,
[1625]586                                                                                                 SplitQueue &splitQueue,
[1624]587                                                                                                 const bool repairQueue)
[1237]588{
[1624]589        const bool terminationCriteriaMet = GlobalTerminationCriteriaMet(sc);
[1237]590
[1633]591        const bool success = sc->Apply(splitQueue, terminationCriteriaMet);
[1444]592
[1610]593        if (!success) // split was not taken
594        {
595                return false;
596        }
597
598        ///////////////
[1624]599        //-- split was successful => update stats and queue
[1610]600
601    // cost ratio of cost decrease / totalCost
[1624]602        const float costRatio = sc->GetRenderCostDecrease() / mHierarchyStats.mTotalCost;
[1610]603        //Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
604       
605        if (costRatio < mTermMinGlobalCostRatio)
606        {
607                ++ mHierarchyStats.mGlobalCostMisses;
608        }
609       
[1624]610        mHierarchyStats.mTotalCost -= sc->GetRenderCostDecrease();
[1610]611       
[1580]612        cout << sc->Type() << " ";
613               
614        // update stats
[1624]615        mHierarchyStats.mNodes += 2;
[1580]616       
617        const int pvsEntries = sc->GetPvsEntriesIncr();
[1624]618        mHierarchyStats.mPvsEntries += pvsEntries;
[1580]619       
620        //cout << "pvs entries: " << pvsEntries << " " << mHierarchyStats.pvsEntries << endl;
[1624]621        mHierarchyStats.mMemory += 0; // TODO
622        mHierarchyStats.mRenderCostDecrease = sc->GetRenderCostDecrease();
623
[1580]624        // subdivision successful
[1624]625        EvalSubdivisionStats();
[1580]626               
627        if (repairQueue)
[1624]628        {
629                // reevaluate candidates affected by the split for view space splits,
630                // this would be object space splits and other way round
[1625]631                vector<SubdivisionCandidate *> dirtyList;
[1633]632                sc->CollectDirtyCandidates(dirtyList, false);
[1624]633
[1633]634                RepairQueue(dirtyList, splitQueue, mRecomputeSplitPlaneOnRepair);
[1580]635        }
636
[1416]637        return true;
[1237]638}
639
640
[1370]641int HierarchyManager::GetObjectSpaceSubdivisionDepth() const
642{
643        int maxDepth = 0;
644
645        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
646        {
647                maxDepth = mOspTree->mOspStats.maxDepth;
648        }
649        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
650        {
651                maxDepth = mBvHierarchy->mBvhStats.maxDepth;
652        }
653
654        return maxDepth;
655}
656
657
[1308]658bool HierarchyManager::StartObjectSpaceSubdivision() const
[1237]659{
[1370]660        // view space construction already started
661        if (ObjectSpaceSubdivisionConstructed())
662                return false;
663
664        // start immediately with object space subdivision?
665        if (mStartWithObjectSpace)
666                return true;
667
668        // is the queue empty again?
669        if (ViewSpaceSubdivisionConstructed() && mTQueue.Empty())
670                return true;
671
672        // has the depth for subdivision been reached?
673        return
674                ((mConstructionType == INTERLEAVED) &&
675                 (mMinDepthForObjectSpaceSubdivion <= mVspTree->mVspStats.maxDepth));
[1308]676}
677
678
[1329]679bool HierarchyManager::StartViewSpaceSubdivision() const
680{
[1370]681        // view space construction already started
682        if (ViewSpaceSubdivisionConstructed())
683                return false;
684
685        // start immediately with view space subdivision?
686        if (!mStartWithObjectSpace)
687                return true;
688
689        // is the queue empty again?
690        if (ObjectSpaceSubdivisionConstructed() && mTQueue.Empty())
691                return true;
692
693        // has the depth for subdivision been reached?
694        return
695                ((mConstructionType == INTERLEAVED) &&
696                 (mMinDepthForViewSpaceSubdivion <= GetObjectSpaceSubdivisionDepth()));
[1329]697}
698
699
[1449]700void HierarchyManager::RunConstruction(const bool repairQueue,
701                                                                           const VssRayContainer &sampleRays,
[1311]702                                                                           const ObjectContainer &objects,
[1635]703                                                                           AxisAlignedBox3 *forcedViewSpace,
704                                                                           SubdivisionCandidate *firstVsp)
[1308]705{
[1313]706        while (!FinishedConstruction())
707        {
[1625]708                SubdivisionCandidate *sc = NextSubdivisionCandidate(mTQueue);   
[1632]709       
[1415]710                ///////////////////
[1237]711                //-- subdivide leaf node
[1415]712
[1625]713                ApplySubdivisionCandidate(sc, mTQueue, repairQueue);
[1580]714                               
[1313]715                // we use objects for evaluating vsp tree construction until
[1415]716                // a certain depth once a certain depth existiert ...
[1313]717                if (StartObjectSpaceSubdivision())
718                {
[1323]719                        mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
[1314]720
[1415]721                        cout << "\nstarting object space subdivision at depth "
[1329]722                                 << mVspTree->mVspStats.maxDepth << " ("
723                                 << mMinDepthForObjectSpaceSubdivion << ") " << endl;
724
[1632]725                        SubdivisionCandidate *ospSc = PrepareObjectSpaceSubdivision(sampleRays, objects);
726                        mTQueue.Push(ospSc);
[1314]727
[1313]728                        cout << "reseting queue ... ";
729                        ResetQueue();
730                        cout << "finished" << endl;
731                }
732
[1329]733                if (StartViewSpaceSubdivision())
734                {
735                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
736
[1415]737                        cout << "\nstarting view space subdivision at depth "
[1370]738                                 << GetObjectSpaceSubdivisionDepth() << " ("
739                                 << mMinDepthForViewSpaceSubdivion << ") " << endl;
[1329]740
[1635]741                        //SubdivisionCandidate *vspSc = PrepareViewSpaceSubdivision(sampleRays, objects);
742                        mTQueue.Push(firstVsp);
[1329]743
744                        cout << "reseting queue ... ";
745                        ResetQueue();
746                        cout << "finished" << endl;
747                }
748
[1624]749                DEL_PTR(sc);
[1237]750        }
751}
752
753
[1449]754void HierarchyManager::RunConstruction(const bool repairQueue)
755{
[1624]756        //int i = 0;
[1580]757        // main loop
[1449]758        while (!FinishedConstruction())
759        {
[1625]760                SubdivisionCandidate *sc = NextSubdivisionCandidate(mTQueue);   
[1449]761                       
[1624]762                ////////
763                //-- subdivide leaf node of either type
[1625]764                ApplySubdivisionCandidate(sc, mTQueue, repairQueue);
[1624]765                DEL_PTR(sc);
[1449]766        }
767}
768
769
[1625]770int HierarchyManager::RunConstruction(SplitQueue &splitQueue,
[1633]771                                                                          SubdivisionCandidateContainer &dirtyCandidates,
[1625]772                                                                          const float minRenderCostDecr,
[1634]773                                                                          const int minSteps)
[1624]774{
[1625]775        int steps = 0;
[1633]776        SubdivisionCandidate::NewMail();
[1625]777
[1624]778        // main loop
[1634]779        while (!splitQueue.Empty())
[1624]780        {
[1625]781                SubdivisionCandidate *sc = NextSubdivisionCandidate(splitQueue);
782               
783                // minimum slope reached
[1634]784                if ((sc->GetRenderCostDecrease() < minRenderCostDecr) &&
785                        !(steps < minSteps))
786                        break;
[1625]787
[1624]788                ////////
789                //-- subdivide leaf node of either type
790
[1625]791                const bool repairQueue = false;
[1633]792                const bool success = ApplySubdivisionCandidate(sc, splitQueue, repairQueue);
[1625]793
[1632]794                if (success)
795                {
[1633]796                        sc->CollectDirtyCandidates(dirtyCandidates, true);
797                        //cout << "collected " << dirtyCandidates.size() << "dirty candidates" << endl;
798                        ++ steps;
[1632]799                }
[1624]800        }
[1625]801
802        return steps;
[1624]803}
804
805
[1625]806SubdivisionCandidate *HierarchyManager::ResetObjectSpaceSubdivision(const VssRayContainer &sampleRays,
807                                                                                                                                        const ObjectContainer &objects)
[1580]808{       
809        // no object space subdivision yet
[1557]810        if (!ObjectSpaceSubdivisionConstructed())
811        {
812                return PrepareObjectSpaceSubdivision(sampleRays, objects);
813        }
814
[1632]815        SubdivisionCandidate *firstCandidate;
[1625]816
[1580]817        // object space partition constructed => reconstruct
[1557]818        switch (mObjectSpaceSubdivisionType)
819        {
820        case BV_BASED_OBJ_SUBDIV:
[1580]821                {
822                        cout << "\nreseting bv hierarchy" << endl;
823                        Debug << "old bv hierarchy:\n " << mBvHierarchy->mBvhStats << endl;
[1557]824       
[1632]825                        firstCandidate = mBvHierarchy->Reset(sampleRays, objects);
[1633]826               
[1625]827                        mHierarchyStats.mTotalCost = mBvHierarchy->mTotalCost;
[1580]828
[1625]829                        mHierarchyStats.mNodes = 2;
830                        mHierarchyStats.mPvsEntries = 0;
831                        mHierarchyStats.mRenderCostDecrease = 0;
[1624]832
[1625]833                        // evaluate stats before first subdivision
834                        EvalSubdivisionStats();
[1580]835                }
[1548]836                break;
[1557]837
[1548]838        case KD_BASED_OBJ_SUBDIV:
839                // TODO
840        default:
[1632]841                firstCandidate = NULL;
[1548]842                break;
843        }
[1633]844
[1625]845        return firstCandidate;
[1449]846}
847
848
[1625]849SubdivisionCandidate *HierarchyManager::ResetViewSpaceSubdivision(const VssRayContainer &sampleRays,
850                                                                                                                                  const ObjectContainer &objects)
[1557]851{
[1580]852        ViewCellsManager *vc = mVspTree->mViewCellsManager;
[1557]853
[1624]854        // HACK: rather not destroy vsp tree
[1580]855        DEL_PTR(mVspTree);
856        mVspTree = new VspTree();
857        mVspTree->mHierarchyManager = this;
858        mVspTree->mViewCellsManager = vc;
859
[1625]860        SubdivisionCandidate *vsc = PrepareViewSpaceSubdivision(sampleRays, objects);
[1580]861       
[1624]862        mHierarchyStats.mNodes = 2;
863        mHierarchyStats.mPvsEntries = 0;
864        mHierarchyStats.mRenderCostDecrease = 0;
[1580]865
[1624]866        EvalSubdivisionStats();
[1625]867
868        return vsc;
[1557]869}
870
871
[1449]872void HierarchyManager::ConstructMultiLevel(const VssRayContainer &sampleRays,                                                                                   
873                                                                                   const ObjectContainer &objects,
874                                                                                   AxisAlignedBox3 *forcedViewSpace)
875{
876        mHierarchyStats.Reset();
877        mHierarchyStats.Start();
[1624]878        mHierarchyStats.mNodes = 2;
[1449]879       
[1624]880        mHierarchyStats.mTotalCost = (float)objects.size();
881        Debug << "setting total cost to " << mHierarchyStats.mTotalCost << endl;
[1449]882
883        const long startTime = GetTime();
884        cout << "Constructing view space / object space tree ... \n";
885       
886        // compute view space bounding box
887        mVspTree->ComputeBoundingBox(sampleRays, forcedViewSpace);
888
[1580]889        // use sah for evaluating osp tree construction
890        // in the first iteration of the subdivision
891       
[1449]892        mSavedViewSpaceSubdivisionType = mViewSpaceSubdivisionType;
893        mViewSpaceSubdivisionType = NO_VIEWSPACE_SUBDIV;
[1635]894       
895        // first view cell
896        SubdivisionCandidate *vspVc = PrepareViewSpaceSubdivision(sampleRays, objects);
[1580]897
898        mSavedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
899        //mObjectSpaceSubdivisionType = NO_OBJ_SUBDIV;
900
901        const int limit = mNumMultiLevels;
[1557]902        int i = 0;
[1449]903
[1624]904        // This method subdivides view space / object space
905        // in order to converge to some optimal cost for this partition
[1557]906        // start with object space partiton
907        // then optimizate view space partition for the current osp
908        // and vice versa until iteration depth is reached.
909        while (1)
[1548]910        {
[1580]911                char subdivisionStatsLog[100];
912                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", i);
913                mSubdivisionStats.open(subdivisionStatsLog);
914
[1624]915                // subdivide object space first
[1548]916                ResetObjectSpaceSubdivision(sampleRays, objects);
[1624]917
[1548]918                // process object space candidates
919                RunConstruction(false);
[1449]920
[1580]921                // object space subdivision constructed
922                mObjectSpaceSubdivisionType = mSavedObjectSpaceSubdivisionType;
923
924                cout << "iteration " << i << " of " << limit << " finished" << endl;
925
926                mSubdivisionStats.close();
[1635]927
[1580]928                if ((i ++) >= limit)
[1557]929                        break;
930
[1580]931                sprintf(subdivisionStatsLog, "tests/i3d/subdivision-%04d.log", i);
932                mSubdivisionStats.open(subdivisionStatsLog);
933
[1557]934                /////////////////
[1580]935                // subdivide view space with respect to the objects
936
[1636]937                if (!ViewSpaceSubdivisionConstructed())
938                {
939                        mTQueue.Push(vspVc);
940                       
941                        // view space subdivision constructed
942                        mViewSpaceSubdivisionType = mSavedViewSpaceSubdivisionType;
943                }
944                else
945                {
946                        ResetViewSpaceSubdivision(sampleRays, objects);
947                }
[1624]948
[1548]949                // process view space candidates
950                RunConstruction(false);
[1624]951
[1580]952                cout << "iteration " << i << " of " << limit << " finished" << endl;
953
954                mSubdivisionStats.close();
955
956                if ((i ++) >= limit)
[1557]957                        break;
[1548]958        }
959       
[1449]960        cout << "\nfinished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
961
[1563]962/*#if _DEBUG
[1449]963        cout << "view space: " << GetViewSpaceBox() << endl;
964        cout << "object space:  " << GetObjectSpaceBox() << endl;
[1563]965#endif*/
[1449]966
967        mHierarchyStats.Stop();
968        mVspTree->mVspStats.Stop();
969        FinishObjectSpaceSubdivision(objects);
970}
971
972
[1237]973bool HierarchyManager::FinishedConstruction() const
974{
975        return mTQueue.Empty();
976}
977
978
[1313]979bool HierarchyManager::ObjectSpaceSubdivisionConstructed() const
[1311]980{
981        switch (mObjectSpaceSubdivisionType)
982        {
983        case KD_BASED_OBJ_SUBDIV:
984                return mOspTree && mOspTree->GetRoot();
985        case BV_BASED_OBJ_SUBDIV:
[1344]986                return mBvHierarchy && mBvHierarchy->GetRoot();
[1311]987        default:
[1580]988                return false;
[1311]989        }
990}
991
992
[1329]993bool HierarchyManager::ViewSpaceSubdivisionConstructed() const
994{
[1635]995        return mViewSpaceSubdivisionType != NO_VIEWSPACE_SUBDIV;
996        //return mVspTree && mVspTree->GetRoot();
[1329]997}
998
999
[1625]1000void HierarchyManager::CollectDirtyCandidates(const SubdivisionCandidateContainer &chosenCandidates,
1001                                                                                          SubdivisionCandidateContainer &dirtyList)
[1237]1002{
[1625]1003        SubdivisionCandidateContainer::const_iterator sit, sit_end = chosenCandidates.end();
[1633]1004        SubdivisionCandidate::NewMail();
[1625]1005
1006        for (sit = chosenCandidates.begin(); sit != sit_end; ++ sit)
1007        {
[1633]1008                (*sit)->CollectDirtyCandidates(dirtyList, true);
[1625]1009        }
1010}
1011
1012
[1633]1013void HierarchyManager::RepairQueue(const SubdivisionCandidateContainer &dirtyList,
1014                                                                   SplitQueue &splitQueue,
1015                                                                   const bool recomputeSplitPlaneOnRepair)
[1625]1016{
[1237]1017        // for each update of the view space partition:
1018        // the candidates from object space partition which
1019        // have been afected by the view space split (the kd split candidates
1020        // which saw the view cell which was split) must be reevaluated
1021        // (maybe not locally, just reinsert them into the queue)
1022        //
1023        // vice versa for the view cells
1024        // for each update of the object space partition
1025        // reevaluate split candidate for view cells which saw the split kd cell
1026        //
1027        // the priority queue update can be solved by implementing a binary heap
1028        // (explicit data structure, binary tree)
1029        // *) inserting and removal is efficient
1030        // *) search is not efficient => store queue position with each
1031        // split candidate
1032
1033        // collect list of "dirty" candidates
[1580]1034        const long startTime = GetTime();
[1625]1035        if (0) cout << "repairing " << (int)dirtyList.size() << " candidates ... ";
[1313]1036       
[1624]1037
[1415]1038        /////////////////////////////////
[1305]1039        //-- reevaluate the dirty list
[1415]1040
[1313]1041        SubdivisionCandidateContainer::const_iterator sit, sit_end = dirtyList.end();
[1302]1042       
[1237]1043        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
1044        {
1045                SubdivisionCandidate* sc = *sit;
[1305]1046                const float rcd = sc->GetRenderCostDecrease();
[1302]1047               
[1625]1048                splitQueue.Erase(sc); // erase from queue
[1633]1049                sc->EvalPriority(recomputeSplitPlaneOnRepair); // reevaluate
[1302]1050               
[1580]1051#ifdef _DEBUG
[1305]1052                Debug << "candidate " << sc << " reevaluated\n"
1053                          << "render cost decrease diff " <<  rcd - sc->GetRenderCostDecrease()
[1580]1054                          << " old: " << rcd << " new " << sc->GetRenderCostDecrease() << endl;
1055#endif 
[1625]1056                splitQueue.Push(sc); // reinsert
[1580]1057                cout << ".";
[1237]1058        }
[1313]1059
[1625]1060        const long endTime = GetTime();
1061        const Real timeDiff = TimeDiff(startTime, endTime);
1062
[1624]1063        mHierarchyStats.mRepairTime += timeDiff;
[1313]1064
[1633]1065        if (0) cout << "repaired in " << timeDiff * 1e-3f << " secs" << endl;
[1237]1066}
1067
[1259]1068
[1313]1069void HierarchyManager::ResetQueue()
1070{
1071        SubdivisionCandidateContainer mCandidateBuffer;
1072
1073        // remove from queue
1074        while (!mTQueue.Empty())
1075        {
[1625]1076                SubdivisionCandidate *candidate = NextSubdivisionCandidate(mTQueue);
1077                 // reevaluate local split plane and priority
1078                candidate->EvalPriority();
[1313]1079                cout << ".";
1080                mCandidateBuffer.push_back(candidate);
1081        }
1082
1083        // put back into queue
1084        SubdivisionCandidateContainer::const_iterator sit, sit_end = mCandidateBuffer.end();
1085    for (sit = mCandidateBuffer.begin(); sit != sit_end; ++ sit)
[1580]1086        {
[1313]1087                mTQueue.Push(*sit);
1088        }
1089}
1090
1091
[1279]1092void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
1093{
1094        // the type of the view cells hierarchy
[1308]1095        switch (mObjectSpaceSubdivisionType)
[1279]1096        {
1097        case KD_BASED_OBJ_SUBDIV:
1098                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
1099                mOspTree->Export(stream);
1100                stream << endl << "</ObjectSpaceHierarchy>" << endl;
[1305]1101                break;         
[1279]1102        case BV_BASED_OBJ_SUBDIV:
1103                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
1104                mBvHierarchy->Export(stream);
1105                stream << endl << "</ObjectSpaceHierarchy>" << endl;
1106                break;
1107        }
1108}
1109
1110
1111bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
1112                                                                          const Vector3 &hitPoint,
1113                                                                          ViewCell *vc,
1114                                                                          const float pdf,
1115                                                                          float &contribution) const
1116{
1117        if (!obj) return false;
1118
[1308]1119        switch (mObjectSpaceSubdivisionType)
[1279]1120        {
1121        case NO_OBJ_SUBDIV:
[1486]1122                {
1123                        // potentially visible objects
1124                        return vc->AddPvsSample(obj, pdf, contribution);
1125                }
[1279]1126        case KD_BASED_OBJ_SUBDIV:
1127                {
1128                        // potentially visible kd cells
1129                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
1130                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
1131                }
1132        case BV_BASED_OBJ_SUBDIV:
1133                {
1134                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
[1370]1135                        BvhIntersectable *bvhObj = mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
1136                       
1137                        return vc->AddPvsSample(bvhObj, pdf, contribution);
[1279]1138                }
1139        default:
1140                return false;
1141        }
1142}
1143
1144
[1421]1145void HierarchyManager::PrintHierarchyStatistics(ostream &stream) const
[1279]1146{
[1313]1147        stream << mHierarchyStats << endl;
1148        stream << "\nview space:" << endl << endl;
1149        stream << mVspTree->GetStatistics() << endl;
1150        stream << "\nobject space:" << endl << endl;
[1370]1151
[1308]1152        switch (mObjectSpaceSubdivisionType)
[1279]1153        {
1154        case KD_BASED_OBJ_SUBDIV:
1155                {
[1313]1156                        stream << mOspTree->GetStatistics() << endl;
[1279]1157                        break;
1158                }
1159        case BV_BASED_OBJ_SUBDIV:
1160                {
[1313]1161                        stream << mBvHierarchy->GetStatistics() << endl;
[1279]1162                        break;
1163                }
1164        default:
1165                break;
1166        }
1167}
1168
1169
[1287]1170void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
[1416]1171                                                                                                  const ObjectContainer &objects,
[1418]1172                                                                                                  const AxisAlignedBox3 *bbox,
1173                                                                                                  const bool exportBounds) const
[1279]1174{
[1308]1175        switch (mObjectSpaceSubdivisionType)
[1286]1176        {
1177        case KD_BASED_OBJ_SUBDIV:
[1279]1178                {
[1287]1179                        ExportOspTree(exporter, objects);
[1286]1180                        break;
1181                }
1182        case BV_BASED_OBJ_SUBDIV:
1183                {
[1418]1184                        exporter->ExportBvHierarchy(*mBvHierarchy, 0, bbox, exportBounds);
[1286]1185                        break;
1186                }
1187        default:
1188                break;
1189        }
1190}
[1279]1191
[1286]1192
[1287]1193void HierarchyManager::ExportOspTree(Exporter *exporter,
1194                                                                         const ObjectContainer &objects) const
[1286]1195{
[1287]1196        if (0) exporter->ExportGeometry(objects);
[1279]1197                       
[1287]1198        exporter->SetWireframe();
1199        exporter->ExportOspTree(*mOspTree, 0);
[1286]1200}
1201
1202
[1418]1203Intersectable *HierarchyManager::GetIntersectable(const VssRay &ray,
1204                                                                                                  const bool isTermination) const
1205{
1206
1207        Intersectable *obj;
1208        Vector3 pt;
1209        KdNode *node;
1210
1211        ray.GetSampleData(isTermination, pt, &obj, &node);
1212       
1213        if (!obj) return NULL;
1214
1215        switch (mObjectSpaceSubdivisionType)
1216        {
1217        case HierarchyManager::KD_BASED_OBJ_SUBDIV:
1218                {
1219                        KdLeaf *leaf = mOspTree->GetLeaf(pt, node);
1220                        return mOspTree->GetOrCreateKdIntersectable(leaf);
1221                }
1222        case HierarchyManager::BV_BASED_OBJ_SUBDIV:
1223                {
1224                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
1225                        return mBvHierarchy->GetOrCreateBvhIntersectable(leaf);
1226                }
1227        default:
1228                return obj;
1229        }
1230}
1231
1232
[1313]1233void HierarchyStatistics::Print(ostream &app) const
1234{
1235        app << "=========== Hierarchy statistics ===============\n";
1236
1237        app << setprecision(4);
1238
1239        app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
1240       
[1624]1241        app << "#N_RTIME  ( Repair time [s] )\n" << mRepairTime * 1e-3f << " \n";
[1313]1242
[1624]1243        app << "#N_NODES ( Number of nodes )\n" << mNodes << "\n";
[1313]1244
1245        app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
1246
1247        app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
1248
[1624]1249        app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << mMaxDepth << endl;
[1449]1250
1251        app << "#N_GLOBALCOSTMISSES ( Global cost misses )\n" << mGlobalCostMisses << endl;
[1313]1252       
1253        app << "========== END OF Hierarchy statistics ==========\n";
1254}
1255
1256
[1418]1257static void RemoveRayRefs(const ObjectContainer &objects)
[1370]1258{
[1418]1259        ObjectContainer::const_iterator oit, oit_end = objects.end();
1260        for (oit = objects.begin(); oit != oit_end; ++ oit)
1261        {
1262                (*oit)->mVssRays.clear();
1263        }
1264}
1265
1266
1267void HierarchyManager::FinishObjectSpaceSubdivision(const ObjectContainer &objects) const
1268{
[1370]1269        switch (mObjectSpaceSubdivisionType)
1270        {
1271        case KD_BASED_OBJ_SUBDIV:
1272                {
1273                        mOspTree->mOspStats.Stop();
1274                        break;
1275                }
1276        case BV_BASED_OBJ_SUBDIV:
1277                {
1278                        mBvHierarchy->mBvhStats.Stop();
[1418]1279                        RemoveRayRefs(objects);
[1370]1280                        break;
1281                }
1282        default:
1283                break;
1284        }
1285}
1286
[1614]1287
1288void HierarchyManager::ExportBoundingBoxes(OUT_STREAM &stream, const ObjectContainer &objects)
1289{
1290        stream << "<BoundingBoxes>" << endl;
1291           
1292        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
1293        {
1294                KdIntersectableMap::const_iterator kit, kit_end = mOspTree->mKdIntersectables.end();
1295
1296                int id = 0;
1297                for (kit = mOspTree->mKdIntersectables.begin(); kit != kit_end; ++ kit, ++ id)
1298                {
1299                        Intersectable *obj = (*kit).second;
1300                        const AxisAlignedBox3 box = obj->GetBox();
1301               
1302                        obj->SetId(id);
1303
1304                        stream << "<BoundingBox" << " id=\"" << id << "\""
1305                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
1306                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
1307                }
1308        }
1309        else
1310        {
1311                ObjectContainer::const_iterator oit, oit_end = objects.end();
1312
1313                for (oit = objects.begin(); oit != oit_end; ++ oit)
1314                {
1315                        const AxisAlignedBox3 box = (*oit)->GetBox();
1316               
1317                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
1318                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
1319                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
1320                }
1321        }
1322               
1323        stream << "</BoundingBoxes>" << endl;
1324}
1325
[1237]1326}
Note: See TracBrowser for help on using the repository browser.