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

Revision 1640, 41.7 KB checked in by mattausch, 18 years ago (diff)

worked on vsp osp methodsd

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