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

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