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

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