source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCell.cpp @ 1706

Revision 1706, 60.9 KB checked in by mattausch, 18 years ago (diff)

worked on full evaluation framework

RevLine 
[1010]1#include <time.h>
2#include <iomanip>
3#include <stack>
4
5
[235]6#include "ViewCell.h"
7#include "Mesh.h"
[308]8#include "Intersectable.h"
[1121]9#include "KdTree.h"
[235]10#include "Triangle3.h"
[580]11#include "common.h"
12#include "Environment.h"
13#include "ViewCellsManager.h"
14#include "Exporter.h"
[1614]15#include "BvHierarchy.h"
[580]16
[235]17
[1614]18
[863]19namespace GtpVisibilityPreprocessor {
[580]20
21
[955]22
[580]23template <typename T> class myless
24{
25public:
26        bool operator() (T v1, T v2) const
27        {
[600]28                return (v1->GetMergeCost() < v2->GetMergeCost());
[580]29        }
30};
31
32
[1121]33typedef priority_queue<ViewCell *, vector<ViewCell *>,
34                                           myless<vector<ViewCell *>::value_type> > TraversalQueue;
[580]35
[1633]36int ViewCell::sMailId = 10000;//2147483647;
[580]37int ViewCell::sReservedMailboxes = 1;
38
[882]39
[580]40float MergeCandidate::sRenderCostWeight = 0;
41
42
43// pvs penalty can be different from pvs size
[882]44inline static float EvalPvsPenalty(const int pvs,
45                                                                   const int lower,
46                                                                   const int upper)
[580]47{
48        // clamp to minmax values
[728]49        if (pvs < lower)
[580]50                return (float)lower;
51        if (pvs > upper)
52                return (float)upper;
[752]53
[580]54        return (float)pvs;
55}
56
[1586]57/** Counts contribution of the view cell to the pvs.
58*/
59inline int CountPvsContribution(ViewCell *vc)
[585]60{
61        int count = 0;
62
63        ObjectPvsMap::const_iterator it, it_end = vc->GetPvs().mEntries.end();
64        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
65        {
66                if (!(*it).first->Mailed())
67                {
68                        (*it).first->Mail();
69                        ++ count;
70                }
71        }
72
73        return count;
74}
75
[1233]76
[729]77/// Fast computation of merged pvs size
[752]78static int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
[580]79{
[729]80        // add first pvs
[580]81        int pvs = pvs1.GetSize();
82
83        ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end();
84
85        Intersectable::NewMail();
86
[729]87        // mail all objects in first pvs
[580]88        for (it = pvs1.mEntries.begin(); it != it_end; ++ it)
89        {
90                (*it).first->Mail();
91        }
92
93        it_end = pvs2.mEntries.end();
94
[1189]95        // look if the entries are also in second pvs
[580]96        for (it = pvs2.mEntries.begin(); it != it_end; ++ it)
97        {
98                Intersectable *obj = (*it).first;
99                if (!obj->Mailed())
100                        ++ pvs;
101        }
102
103        return pvs;
104}
105
106
[478]107ViewCell::ViewCell():
108MeshInstance(NULL),
[551]109mArea(-1),
110mVolume(-1),
[580]111mValid(true),
112mParent(NULL),
[600]113mMergeCost(0),
[752]114mPvsSize(0),
[1160]115mEntriesInPvs(0),
[752]116mPvsSizeValid(false)
[1297]117//mMailbox(0)
[265]118{
[1570]119        mId = -100;
[265]120}
[235]121
[478]122ViewCell::ViewCell(Mesh *mesh):
123MeshInstance(mesh),
[551]124mArea(-1),
125mVolume(-1),
[580]126mValid(true),
127mParent(NULL),
[600]128mMergeCost(0),
[752]129mPvsSize(0),
130mPvsSizeValid(false)
[1297]131//mMailbox(0)
[372]132{
[1570]133        mId = -100;
[372]134}
135
[503]136
[1551]137ViewCell::~ViewCell()
138{
139}
140
141
[469]142const ObjectPvs &ViewCell::GetPvs() const
[419]143{
144        return mPvs;
145}
146
[752]147
[469]148ObjectPvs &ViewCell::GetPvs()
[372]149{
150        return mPvs;
151}
152
[503]153
[880]154void ViewCell::SetPvs(const ObjectPvs &pvs)
155{
156        mPvs = pvs;
157}
158
159
[235]160int ViewCell::Type() const
161{
[308]162        return VIEW_CELL;
[235]163}
164
[503]165
[469]166float ViewCell::GetVolume() const
167{
168        return mVolume;
169}
170
[478]171
[469]172void ViewCell::SetVolume(float volume)
173{
174        mVolume = volume;
175}
176
[503]177
178void ViewCell::SetMesh(Mesh *mesh)
179{
180        mMesh = mesh;
181}
182
183
[478]184float ViewCell::GetArea() const
185{
186        return mArea;
187}
188
189
190void ViewCell::SetArea(float area)
191{
192        mArea = area;
193}
194
195
[752]196void ViewCell::SetColor(const RgbColor &color)
197{
198        mColor = color;
199}
200
201
202RgbColor ViewCell::GetColor() const
203{
204        return mColor;
205}
206
207
[547]208void ViewCell::SetValid(const bool valid)
209{
[564]210        mValid = valid;
[547]211}
212
213
214bool ViewCell::GetValid() const
215{
216        return mValid;
217}
218
219
[580]220void ViewCell::SetParent(ViewCellInterior *parent)
221{
222        mParent = parent;
223}
224
225
226bool ViewCell::IsRoot() const
227{
228        return !mParent;
229}
230
231
232ViewCellInterior *ViewCell::GetParent() const
233{
234        return mParent;
235}
236
237
[600]238void ViewCell::SetMergeCost(const float mergeCost)
[580]239{
[600]240        mMergeCost = mergeCost;
[580]241}
242
243
[728]244float ViewCell::GetRenderCost() const
245{
[801]246        //return (float)mPvs.GetSize() * GetVolume();
247        return (float)mPvsSize * GetVolume();
[728]248}
249
250
[600]251float ViewCell::GetMergeCost() const
[580]252{
[600]253        return mMergeCost;
[580]254}
255
[1002]256
257bool ViewCell::AddPvsSample(Intersectable *sample,
258                                                        const float pdf,
259                                                        float &contribution)
260{
261        const bool result = mPvs.AddSample(sample, pdf, contribution);
[1586]262        // have to recompute pvs size
263        mPvsSizeValid = false;
[1002]264
265        return result;
266}
267
268
[1133]269
[462]270/************************************************************************/
[580]271/*                class ViewCellInterior implementation                 */
272/************************************************************************/
273
274
275ViewCellInterior::ViewCellInterior()
276{
277}
278
279
280ViewCellInterior::~ViewCellInterior()
281{
282        ViewCellContainer::const_iterator it, it_end = mChildren.end();
283
284        for (it = mChildren.begin(); it != it_end; ++ it)
[1545]285        {
[580]286                delete (*it);
[1545]287        }
[580]288}
289
290
291ViewCellInterior::ViewCellInterior(Mesh *mesh):
292ViewCell(mesh)
293{
294}
295
296
297bool ViewCellInterior::IsLeaf() const
298{
299        return false;
300}
301
302
[650]303void ViewCellInterior::SetupChildLink(ViewCell *vc)
[580]304{
[650]305    mChildren.push_back(vc);
[1002]306    vc->SetParent(this);
[580]307}
308
309
[586]310void ViewCellInterior::RemoveChildLink(ViewCell *l)
311{
312        // erase leaf from old view cell
313        ViewCellContainer::iterator it = mChildren.begin();
[580]314
[586]315        for (; (*it) != l; ++ it);
316        if (it == mChildren.end())
317                Debug << "error" << endl;
318        else
319                mChildren.erase(it);
320}
321
[703]322
[1286]323void ViewCellInterior::ReplaceChildLink(ViewCell *prev, ViewCell *cur)
324{
325        // erase leaf from old view cell
326        ViewCellContainer::iterator it = mChildren.begin();
327
328        for (; (*it) != prev; ++ it);
329        if (it == mChildren.end())
330        {
331                Debug << "error: child link not found" << endl;
332        }
333        else
334        {
335                (*it) = cur;
336        }
337}
338
339
[1551]340
[580]341/************************************************************************/
[462]342/*                class ViewCellsStatistics implementation              */
343/************************************************************************/
344
[580]345
[463]346void ViewCellsStatistics::Print(ostream &app) const
347{
348        app << "=========== View Cells Statistics ===============\n";
349
350        app << setprecision(4);
351
352        //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
353
[613]354        app << "#N_OVERALLPVS ( objects in PVS )\n" << pvsSize << endl;
[463]355
356        app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;
357
358        app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;
359
360        app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;
361
[485]362        app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
[463]363
364        app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;
365
366        app << "#N_AVGLEAVES (average number of leaves per view cell )\n" << AvgLeaves() << endl;
367
368        app << "#N_MAXLEAVES ( maximal number of leaves per view cell )\n" << maxLeaves << endl;
369       
[564]370        app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
371
[463]372        app << "========== End of View Cells Statistics ==========\n";
[580]373}
374
375
376/*************************************************************************/
377/*                    class ViewCellsTree implementation                 */
378/*************************************************************************/
379
380
[1004]381ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
[580]382mRoot(NULL),
383mUseAreaForPvs(false),
[584]384mViewCellsManager(vcm),
[752]385#if 0
386mViewCellsStorage(PVS_IN_INTERIORS)
387#else
388mViewCellsStorage(PVS_IN_LEAVES)
389#endif
[580]390{
[1264]391        ReadEnvironment();
392        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
393}
394
395
396ViewCellsTree::ViewCellsTree():
397mRoot(NULL),
398mUseAreaForPvs(false),
399mViewCellsManager(NULL),
400#if 0
401mViewCellsStorage(PVS_IN_INTERIORS)
402#else
403mViewCellsStorage(PVS_IN_LEAVES)
404#endif
405{
406        ReadEnvironment();
407        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
408}
409
410
411void ViewCellsTree::ReadEnvironment()
412{
[1004]413        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
414        Environment::GetSingleton()->GetFloatValue("ViewCells.maxStaticMemory", mMaxMemory);
[580]415
416        //-- merge options
[1004]417        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight);
418        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells);
419        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio);
420        Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.refine", mRefineViewCells);   
[582]421
[1004]422        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", mMaxMergesPerPass);
423        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", mAvgCostMaxDeviation);
[586]424
[938]425        Debug << "============= view cell tree options ================\n";
[582]426        Debug << "minimum view cells: " << mMergeMinViewCells << endl;
427        Debug << "max cost ratio: " << mMergeMaxCostRatio << endl;
428        Debug << "max memory: " << mMaxMemory << endl;
[586]429        Debug << "refining view cells: " << mRefineViewCells << endl;
[1027]430        Debug << "=========== end view cell tree options ===============\n";
[580]431}
432
433
[582]434// return memory usage in MB
435float ViewCellsTree::GetMemUsage() const
436{
[752]437        // TODO
[582]438        return 0;
439                /*(sizeof(ViewCellsTree) +
440                 mBspStats.Leaves() * sizeof(BspLeaf) +
441                 mBspStats.Interior() * sizeof(BspInterior) +
442                 mBspStats.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);*/
443}
444
445
[736]446int ViewCellsTree::GetNumInitialViewCells(ViewCell *vc) const
[580]447{
448        int vcSize = 0;
449
450        stack<ViewCell *> tstack;
451
452        tstack.push(vc);
453
454        while (!tstack.empty())
455        {
456                ViewCell *vc = tstack.top();
457                tstack.pop();
458
459                if (vc->IsLeaf())
460                {
461                        ++ vcSize;
462                }
463                else
464                {
465                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1233]466
[580]467                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1233]468                       
[580]469                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[1233]470                        {
[580]471                                tstack.push(*it);
[1233]472                        }
[580]473                       
474                }
475        }
476
477        return vcSize;
478}
479
480
481void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const
482{
483        stack<ViewCell *> tstack;
484
485        tstack.push(vc);
486
487        while (!tstack.empty())
488        {
489                ViewCell *vc = tstack.top();
490                tstack.pop();
491
492                if (vc->IsLeaf())
493                {
494                        leaves.push_back(vc);
495                }
496                else
497                {
498                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
499                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[664]500
[580]501                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[664]502                        {
[580]503                                tstack.push(*it);
[664]504                        }
[580]505                       
506                }
507        }
508}
509
510
511ViewCellsTree::~ViewCellsTree()
512{
513        DEL_PTR(mRoot);
514}
515
516
517int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays,
518                                                                          const ObjectContainer &objects)
519{
[582]520        mNumActiveViewCells = (int)mViewCellsManager->GetViewCells().size();
[580]521
522        float variance = 0;
523        int totalPvs = 0;
[600]524        float totalRenderCost = 0;
[580]525
526        //-- compute statistics values of initial view cells
[600]527        mViewCellsManager->EvaluateRenderStatistics(totalRenderCost,
[580]528                                                                                                mExpectedCost,
529                                                                                                mDeviation,
530                                                                                                variance,
531                                                                                                totalPvs,
532                                                                                                mAvgRenderCost);
533
534
535        //-- fill merge queue
536        vector<MergeCandidate> candidates;
537
538        mViewCellsManager->CollectMergeCandidates(rays, candidates);
[703]539
[580]540        while(!candidates.empty())
541        {
542                MergeCandidate mc = candidates.back();
543                candidates.pop_back();
544                EvalMergeCost(mc);
545                mMergeQueue.push(mc);
546        }
547
548        Debug << "************************* merge ***********************************" << endl; 
549        Debug << "deviation: " << mDeviation << endl;
550        Debug << "avg render cost: " << mAvgRenderCost << endl;
[600]551        Debug << "expected cost: " << mExpectedCost << endl;
[580]552
553
554        ViewCellsManager::PvsStatistics pvsStats;
555        mViewCellsManager->GetPvsStatistics(pvsStats);
556
[605]557        //static float expectedValue = pvsStats.avgPvs;
[580]558       
[881]559        //-- the current view cells are kept in this container
560        //-- we start with the current view cells from the view cell manager.
561        //-- The active view cells will change with subsequent merges
[752]562       
[720]563        // todo: should rather take initial view cells
564    ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
565       
[752]566       
[580]567        ViewCell::NewMail();
568
569        MergeStatistics mergeStats;
570        mergeStats.Start();
571       
572        long startTime = GetTime();
573
574        mergeStats.collectTime = TimeDiff(startTime, GetTime());
575        mergeStats.candidates = (int)mMergeQueue.size();
576        startTime = GetTime();
577
578        // frequency stats are updated
[650]579        const int statsOut = 500;
[734]580       
[580]581        // passes are needed for statistics, because we don't want to record
582        // every merge
583        int pass = 0;
584        int mergedPerPass = 0;
585        float realExpectedCost = mExpectedCost;
586        float realAvgRenderCost = mAvgRenderCost;
[582]587        int realNumActiveViewCells = mNumActiveViewCells;
[580]588       
589        // maximal ratio of old expected render cost to expected render
590        // when the the render queue has to be reset.
[582]591        int numMergedViewCells = 0;
[938]592               
[580]593
594        cout << "actual merge starts now ... " << endl;
[604]595
[580]596        //-- use priority queue to merge leaf pairs
[612]597
[881]598        while (!mMergeQueue.empty())
[580]599        {
600                //-- reset merge queue if the ratio of current expected cost / real expected cost
601                //   too small or after a given number of merges
[938]602                if ((mergedPerPass > mMaxMergesPerPass) ||
603                        (mAvgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
[580]604                {
605                        Debug << "************ reset queue *****************\n"
[938]606                                  << "ratios: " << mAvgCostMaxDeviation
[580]607                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
[938]608                                  << " merged per pass : " << mergedPerPass << " of maximal " << mMaxMergesPerPass << endl;
[580]609
610                        Debug << "Values before reset: " 
611                                  << " erc: " << mExpectedCost
612                                  << " avgrc: " << mAvgRenderCost
613                                  << " dev: " << mDeviation << endl;
614       
615                        // adjust render cost
616                        ++ pass;
617
618                        mergedPerPass = 0;
619                        mExpectedCost = realExpectedCost;
620                        mAvgRenderCost = realAvgRenderCost;
[582]621                        mNumActiveViewCells = realNumActiveViewCells;
[580]622                       
[582]623                        const int numMergedViewCells = UpdateActiveViewCells(activeViewCells);
624               
[1603]625                        /////////////////
626                        //-- reset / refine the view cells
[720]627                        //-- priorities are recomputed
628                        //-- the candidates are put back into merge queue
[1603]629
[586]630                        if (mRefineViewCells)
631                                RefineViewCells(rays, objects);
632                        else
633                                ResetMergeQueue();
[580]634
635                        Debug << "Values after reset: " 
636                                  << " erc: " << mExpectedCost
637                                  << " avg: " << mAvgRenderCost
638                                  << " dev: " << mDeviation << endl;
639
640                        if (mExportMergedViewCells)
641                        {
[582]642                                ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
[580]643                        }
644                }
645
646
647                MergeCandidate mc = mMergeQueue.top();
648                mMergeQueue.pop();
649       
[710]650                // both view cells equal because of previous merges
[582]651                // NOTE: do I really still need this? probably cannot happen!!
[580]652                if (mc.mLeftViewCell == mc.mRightViewCell)
653                        continue;
654
655                if (mc.IsValid())
656                {
657                        ViewCell::NewMail();
[600]658
659                        //-- update statistical values
[582]660                        -- realNumActiveViewCells;
[580]661                        ++ mergeStats.merged;
662                        ++ mergedPerPass;
663
[600]664                        const float renderCostIncr = mc.GetRenderCost();
665                        const float mergeCostIncr = mc.GetMergeCost();
[580]666
[600]667                        totalRenderCost += renderCostIncr;
[580]668                        mDeviation += mc.GetDeviationIncr();
[710]669
670                                               
671                        //-- merge the view cells of leaf1 and leaf2
[580]672                        int pvsDiff;
673                        ViewCellInterior *mergedVc =
674                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
[710]675                       
[580]676
[600]677                        // total render cost and deviation has changed
678                        // real expected cost will be larger than expected cost used for the
679                        // cost heuristics, but cannot recompute costs on each increase of the
680                        // expected cost
[580]681                        totalPvs += pvsDiff;
[600]682                        realExpectedCost = totalRenderCost / (float)realNumActiveViewCells;
683                        realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
684       
[801]685                        // set merge cost to this node for priority traversal
[837]686                        mergedVc->SetMergeCost(totalRenderCost);
687                       
688                        // check if "siblings (back and front node of the same parent)
[1706]689                        if (0) ++ mergeStats.siblings;
690
691                        // set the cost for rendering a view cell
[608]692                        mergedVc->SetCost(realExpectedCost);
[607]693
[650]694                        if ((mergeStats.merged % statsOut) == 0)
[580]695                                cout << "merged " << mergeStats.merged << " view cells" << endl;
696
697                }
698                else
699                {
700                        // merge candidate not valid, because one of the leaves was already
701                        // merged with another one => validate and reinsert into queue
[582]702                        if (ValidateMergeCandidate(mc))
703                        {
704                                EvalMergeCost(mc);
705                                mMergeQueue.push(mc);
706                        }
[580]707                }
[612]708               
[580]709        }
710
711        // adjust stats and reset queue one final time
712        mExpectedCost = realExpectedCost;
713        mAvgRenderCost = realAvgRenderCost;
[582]714        mNumActiveViewCells = realNumActiveViewCells;
[580]715
[582]716        UpdateActiveViewCells(activeViewCells);
[580]717
[586]718        // refine view cells and reset costs
719        if (mRefineViewCells)
720                RefineViewCells(rays, objects);
721        else
722                ResetMergeQueue();
723
[708]724
[580]725        // create a root node if the merge was not done till root level,
726        // else take the single node as new root
[582]727        if ((int)activeViewCells.size() > 1)
[580]728        {
[587]729                Debug << "creating root of view cell hierarchy for "
730                          << (int)activeViewCells.size() << " view cells" << endl;
[612]731               
[582]732                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
[710]733       
734                ViewCellContainer::const_iterator it, it_end = root->mChildren.end();
735
736                for (it = root->mChildren.begin(); it != it_end; ++ it)
737                        (*it)->SetParent(root);
738       
[600]739                root->SetMergeCost(totalRenderCost);
[608]740                // $$JB keep this 0 temporarilly
741                root->SetCost(0.0f);
[612]742
[580]743                mRoot = root;
744        }
[710]745        // normal case
746        else if (!activeViewCells.empty())
[580]747        {
[582]748                Debug << "setting root of the merge history" << endl;
749                mRoot = activeViewCells[0];
[580]750        }
[752]751        else
752        {
753                Debug << "big error, root is NULL" << endl;
754        }
[708]755       
[644]756        //-- empty merge queue just in case
[600]757        while (!mMergeQueue.empty())
758        {
759                mMergeQueue.pop();
760        }
[837]761
[1706]762        // test if computed volumes are correct
763        Debug << "volume of the root view cell: " << mRoot->GetVolume()
764                  << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
[837]765       
766        // TODO: delete because makes no sense here
[580]767        mergeStats.expectedRenderCost = realExpectedCost;
768        mergeStats.deviation = mDeviation;
769
770        // we want to optimize this heuristics
771        mergeStats.heuristics =
772                mDeviation * (1.0f - mRenderCostWeight) +
773                mExpectedCost * mRenderCostWeight;
774
775        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
776        mergeStats.Stop();
777        Debug << mergeStats << endl << endl;
778
[608]779        // assign colors for the view cells so that at least one is always consistent
780        AssignRandomColors();
[708]781
[580]782        //TODO: should return sample contributions?
783        return mergeStats.merged;
784}
785
786
[584]787ViewCell *ViewCellsTree::GetRoot() const
[581]788{
789        return mRoot;
790}
791
792
[580]793void ViewCellsTree::ResetMergeQueue()
794{
795        cout << "reset merge queue ... ";
796       
797        vector<MergeCandidate> buf;
798        buf.reserve(mMergeQueue.size());
799                       
800       
801        // store merge candidates in intermediate buffer
802        while (!mMergeQueue.empty())
803        {
804                MergeCandidate mc = mMergeQueue.top();
805                mMergeQueue.pop();
806               
807                // recalculate cost
[582]808                if (ValidateMergeCandidate(mc))
809                {
810                        EvalMergeCost(mc);
811                        buf.push_back(mc);                             
812                }
[580]813        }
814
815        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
816
817        // reinsert back into queue
818        for (bit = buf.begin(); bit != bit_end; ++ bit)
819        {     
820                mMergeQueue.push(*bit);
821        }
822
823        cout << "finished" << endl;
824}
825
826
[1002]827float ViewCellsTree::ComputeMergedPvsCost(const ObjectPvs &pvs1,
828                                                                                  const ObjectPvs &pvs2) const
829{
830        // computes render cost of merge
831        float renderCost = 0;
832
833        // compute new pvs size
834        ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end();
835
836        Intersectable::NewMail();
837
838        // first mail all objects in first pvs
839        for (it = pvs1.mEntries.begin(); it != it_end; ++ it)
840        {
841                Intersectable *obj = (*it).first;
842
843                obj->Mail();
844                renderCost += mViewCellsManager->EvalRenderCost(obj);
845        }
846
847        it_end = pvs2.mEntries.end();
848
849       
850        for (it = pvs2.mEntries.begin(); it != it_end; ++ it)
851        {
852                Intersectable *obj = (*it).first;
853
854                // test if object already considered   
855                if (!obj->Mailed())
856                {
857                        renderCost += mViewCellsManager->EvalRenderCost(obj);
858                }
859        }
860
861        return renderCost;
862}
863
864
[582]865int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
[580]866{
[582]867        int numMergedViewCells = 0;
[580]868
[584]869        Debug << "updating active vc: " << (int)viewCells.size() << endl;
[1141]870       
871        // find all already merged view cells and remove them from the
872        // container view cells
[582]873               
874        // sort out all view cells which are not active anymore, i.e., they
875        // were already part of a merge
[580]876        int i = 0;
877
[582]878        ViewCell::NewMail();
879
[580]880        while (1)
881        {
[582]882                // remove all merged view cells from end of the vector
883                while (!viewCells.empty() && (viewCells.back()->GetParent()))
[580]884                {
885                        viewCells.pop_back();
886                }
887
888                // all merged view cells have been found
[710]889                if (i >= (int)viewCells.size())
[580]890                        break;
891
[710]892                // already merged this view cell, put it to end of vector
[582]893                if (viewCells[i]->GetParent())
[580]894                        swap(viewCells[i], viewCells.back());
895               
[752]896                // mail view cell that it has not been merged
[710]897                viewCells[i]->Mail();
898
899                // increase loop counter
900                ++ i;
[580]901        }
902
[582]903
[580]904        // add new view cells to container only if they don't have been
905        // merged in the mean time
[582]906        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
[752]907
[582]908        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
[580]909        {
[582]910                ViewCell *vc = mMergedViewCells.back();
911                if (!vc->GetParent() && !vc->Mailed())
[580]912                {
[582]913                        vc->Mail();
914                        viewCells.push_back(vc);
915                        ++ numMergedViewCells;
[580]916                }
917        }
918
[752]919        // dispose old merged view cells
[582]920        mMergedViewCells.clear();
921
[580]922        // update standard deviation
923        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
924       
925        mDeviation = 0;
926
927        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
928        {
[728]929                const int lower = mViewCellsManager->GetMinPvsSize();
930                const int upper = mViewCellsManager->GetMaxPvsSize();
[752]931
[1168]932                const float penalty = EvalPvsPenalty((*vit)->GetPvs().CountObjectsInPvs(), lower, upper);
[580]933               
934                mDeviation += fabs(mAvgRenderCost - penalty);
935        }
936
937        mDeviation /= (float)viewCells.size();
[582]938       
939        return numMergedViewCells;
[580]940}
941
942
943void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
944                                                                                  const ObjectContainer &objects,
[582]945                                                                                  const int numMergedViewCells)
[580]946{
947       
948
949        char s[64];
950
951        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
952        Exporter *exporter = Exporter::GetExporter(s);
953
954        if (exporter)
955        {
956                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
957                exporter->ExportGeometry(objects);
958                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
959                ViewCellContainer::const_iterator it, it_end = viewCells.end();
960
961                int i = 0;
962                for (it = viewCells.begin(); it != it_end; ++ it)
963                {
964                        Material m;
965                        // assign special material to new view cells
966                        // new view cells are on the back of container
[582]967                        if (i ++ >= (viewCells.size() - numMergedViewCells))
[580]968                        {
969                                //m = RandomMaterial();
970                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
971                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
972                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
973                        }
974                        else
975                        {
976                                float col = RandomValue(0.1f, 0.4f);
977                                m.mDiffuseColor.r = col;
978                                m.mDiffuseColor.g = col;
979                                m.mDiffuseColor.b = col;
980                        }
981
982                        exporter->SetForcedMaterial(m);
[1416]983                        mViewCellsManager->ExportViewCellGeometry(exporter, *it, NULL, NULL);
[580]984                }
[1416]985
[580]986                delete exporter;
987                cout << "finished" << endl;
988        }
989}
990
991
992// TODO: should be done in view cells manager
[1141]993ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *left,
994                                                                                                ViewCell *right,
[586]995                                                                                                int &pvsDiff) //const
[580]996{
[1141]997        // create merged view cell
998        ViewCellInterior *vc =
999                mViewCellsManager->MergeViewCells(left, right);
[580]1000
1001        // if merge was unsuccessful
1002        if (!vc) return NULL;
1003
[752]1004        // set to the new parent view cell
[1141]1005        left->SetParent(vc);
1006        right->SetParent(vc);
[710]1007
[1141]1008       
[580]1009        if (mUseAreaForPvs)
[710]1010        {
[1141]1011                // set new area of view cell
1012                // not not correct, but costly to compute real area!!
1013                vc->SetArea(left->GetArea() + right->GetArea());
[710]1014        }
[580]1015        else
[1141]1016        {       // set new volume of view cell
1017                vc->SetVolume(left->GetVolume() + right->GetVolume());
[602]1018        }
[710]1019
1020       
[580]1021        // important so other merge candidates sharing this view cell
1022        // are notified that the merge cost must be updated!!
1023        vc->Mail();
1024
[1168]1025        const int pvs1 = left->GetPvs().CountObjectsInPvs();
1026        const int pvs2 = right->GetPvs().CountObjectsInPvs();
[580]1027
1028
[1141]1029        // the new view cells are stored in this container
[582]1030        mMergedViewCells.push_back(vc);
[580]1031
[1168]1032        pvsDiff = vc->GetPvs().CountObjectsInPvs() - pvs1 - pvs2;
[580]1033
[752]1034
[1141]1035        // don't store pvs in interior cells, just a scalar
[752]1036        if (mViewCellsStorage == PVS_IN_LEAVES)
1037        {
[1168]1038                // set scalars
1039                mViewCellsManager->UpdateScalarPvsSize(left,
[1586]1040                                left->GetPvs().CountObjectsInPvs(),
1041                                left->GetPvs().GetSize());
[1168]1042                       
[1141]1043                // remove pvs, we don't store interior pvss
1044                if (!left->IsLeaf())
1045                {
1046                        left->GetPvs().Clear();
1047                }
1048
[1168]1049                // set scalars
1050                mViewCellsManager->UpdateScalarPvsSize(right,
1051                        right->GetPvs().CountObjectsInPvs(),
1052                        right->GetPvs().GetSize());
1053
[1141]1054                right->mPvsSizeValid = true;
[752]1055               
[1141]1056                // remove pvs, we don't store interior pvss
1057                if (!right->IsLeaf())
1058                {
1059                        right->GetPvs().Clear();
1060                }
1061        }
[752]1062
[580]1063        return vc;
1064}
1065
1066
[586]1067int ViewCellsTree::RefineViewCells(const VssRayContainer &rays,
1068                                                                   const ObjectContainer &objects)
[580]1069{
1070        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
[586]1071
1072        // intermediate buffer for shuffled view cells
1073        vector<MergeCandidate> buf;
1074        buf.reserve(mMergeQueue.size());
1075                       
[580]1076        // Use priority queue of remaining leaf pairs
1077        // The candidates either share the same view cells or
1078        // are border leaves which share a boundary.
1079        // We test if they can be shuffled, i.e.,
1080        // either one leaf is made part of one view cell or the other
1081        // leaf is made part of the other view cell. It is tested if the
1082        // remaining view cells are "better" than the old ones.
1083       
[586]1084        const int numPasses = 3;
[580]1085        int pass = 0;
1086        int passShuffled = 0;
1087        int shuffled = 0;
1088        int shuffledViewCells = 0;
1089
1090        ViewCell::NewMail();
1091       
[586]1092        while (!mMergeQueue.empty())
[580]1093        {
[586]1094                MergeCandidate mc = mMergeQueue.top();
1095                mMergeQueue.pop();
[580]1096
[586]1097                // both view cells equal or already shuffled
1098                if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
1099                        mc.GetLeftViewCell()->IsLeaf() || mc.GetRightViewCell()->IsLeaf())
1100                {                       
1101                        continue;
1102                }
[580]1103
[586]1104                // candidate for shuffling
1105                const bool wasShuffled = ShuffleLeaves(mc);
[580]1106               
[586]1107                // shuffled or put into other queue for further refine
1108                if (wasShuffled)
1109                {
1110                        ++ passShuffled;
1111
1112                        if (!mc.GetLeftViewCell()->Mailed())
[580]1113                        {
[586]1114                                mc.GetLeftViewCell()->Mail();
1115                                ++ shuffledViewCells;
[580]1116                        }
[586]1117                        if (!mc.GetRightViewCell()->Mailed())
[580]1118                        {
[586]1119                                mc.GetRightViewCell()->Mail();
1120                                ++ shuffledViewCells;
[580]1121                        }
1122                }
1123
[586]1124                // put back into intermediate vector
1125                buf.push_back(mc);
[580]1126        }
1127
[586]1128
1129        //-- in the end, the candidates must be in the mergequeue again
1130        //   with the correct cost
1131
1132        cout << "reset merge queue ... ";
1133       
1134       
1135        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
1136       
1137        for (bit = buf.begin(); bit != bit_end; ++ bit)
1138        {   
1139                MergeCandidate mc = *bit;
1140                // recalculate cost
1141                if (ValidateMergeCandidate(mc))
1142                {
1143                        EvalMergeCost(mc);
1144                        mMergeQueue.push(mc);   
1145                }
[580]1146        }
1147
[586]1148        cout << "finished" << endl;
1149
[580]1150        return shuffledViewCells;
1151}
1152
1153
1154inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1155{
1156        return pvs1.AddPvs(pvs2);
1157}
1158
1159
1160// recomputes pvs size minus pvs of leaf l
1161#if 0
1162inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
1163{
1164        ObjectPvs pvs;
1165        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
1166        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
1167                if (*it != l)
1168                        pvs.AddPvs(*(*it)->mPvs);
1169        return pvs.GetSize();
1170}
1171#endif
1172
1173
1174// computes pvs1 minus pvs2
1175inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1176{
1177        return pvs1.SubtractPvs(pvs2);
1178}
1179
1180
1181float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
[586]1182                                                                         ViewCellInterior *vc1,
1183                                                                         ViewCellInterior *vc2) const
[580]1184{
1185        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
1186        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
1187        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
1188
1189        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
1190        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
1191
1192        const float pvsPenalty1 =
1193                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
1194
1195        const float pvsPenalty2 =
1196                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
1197
1198
1199        // don't shuffle leaves with pvs > max
1200        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
1201        {
1202                return 1e20f;
1203        }
1204
1205        float p1, p2;
1206
1207    if (mUseAreaForPvs)
1208        {
1209                p1 = vc1->GetArea() - leaf->GetArea();
1210                p2 = vc2->GetArea() + leaf->GetArea();
1211        }
1212        else
1213        {
1214                p1 = vc1->GetVolume() - leaf->GetVolume();
1215                p2 = vc2->GetVolume() + leaf->GetVolume();
1216        }
1217
1218        const float renderCost1 = pvsPenalty1 * p1;
1219        const float renderCost2 = pvsPenalty2 * p2;
1220
1221        float dev1, dev2;
1222
1223        if (1)
1224        {
1225                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1226                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1227        }
1228        else
1229        {
1230                dev1 = fabs(mExpectedCost - renderCost1);
1231                dev2 = fabs(mExpectedCost - renderCost2);
1232        }
1233       
1234        return mRenderCostWeight * (renderCost1 + renderCost2) +
[582]1235                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
[580]1236}
1237
1238
1239void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
[586]1240                                                                ViewCellInterior *vc1,
1241                                                                ViewCellInterior *vc2) const
[580]1242{
1243        // compute new pvs and area
[586]1244        // TODO change
[580]1245        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1246        vc2->GetPvs().AddPvs(leaf->GetPvs());
1247       
1248        if (mUseAreaForPvs)
1249        {
1250                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1251                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1252        }
1253        else
1254        {
1255                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1256                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1257        }
1258
[586]1259       
1260        ViewCellInterior *p = dynamic_cast<ViewCellInterior *>(leaf->GetParent());
[580]1261
[586]1262        p->RemoveChildLink(leaf);
1263        vc2->SetupChildLink(leaf);
[580]1264}
1265
1266
[586]1267bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
[580]1268{
1269        float cost1, cost2;
1270
[586]1271        ViewCellInterior *vc1 = dynamic_cast<ViewCellInterior *>(mc.GetLeftViewCell());
1272        ViewCellInterior *vc2 = dynamic_cast<ViewCellInterior *>(mc.GetRightViewCell());
1273
1274        ViewCell *leaf1 = mc.GetInitialLeftViewCell();
1275        ViewCell *leaf2 = mc.GetInitialRightViewCell();
1276
[580]1277        //-- first test if shuffling would decrease cost
[586]1278        cost1 = GetCostHeuristics(vc1);
1279        cost2 = GetCostHeuristics(vc2);
[580]1280
1281        const float oldCost = cost1 + cost2;
1282       
1283        float shuffledCost1 = Limits::Infinity;
1284        float shuffledCost2 = Limits::Infinity;
1285
[586]1286        if (leaf1)
1287                shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);       
1288        if (leaf2)
1289                shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
[580]1290
1291        // if cost of shuffle is less than old cost => shuffle
1292        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1293                return false;
1294       
1295        if (shuffledCost1 < shuffledCost2)
1296        {
[586]1297                if (leaf1)
1298                        ShuffleLeaf(leaf1, vc1, vc2);
1299                mc.mInitialLeftViewCell = NULL;
[580]1300        }
1301        else
1302        {
[586]1303                if (leaf2)
1304                        ShuffleLeaf(leaf2, vc2, vc1);
1305                mc.mInitialRightViewCell = NULL;
[580]1306        }
[586]1307
[580]1308        return true;
1309}
1310
1311
1312float ViewCellsTree::GetVariance(ViewCell *vc) const
1313{
1314        const int upper = mViewCellsManager->GetMaxPvsSize();
1315        const int lower = mViewCellsManager->GetMinPvsSize();
1316
1317        if (1)
1318        {
[752]1319                const float penalty =
1320                        EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
[1141]1321
[752]1322                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) /
1323                        (float)mNumActiveViewCells;
[580]1324        }
1325
1326    const float leafCost = GetRenderCost(vc);
1327        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1328}
1329
1330
1331float ViewCellsTree::GetDeviation(ViewCell *vc) const
1332{
1333        const int upper = mViewCellsManager->GetMaxPvsSize();
1334        const int lower = mViewCellsManager->GetMinPvsSize();
1335
1336        if (1)
1337        {
[1168]1338                const float penalty = EvalPvsPenalty(vc->GetPvs().CountObjectsInPvs(), lower, upper);
[582]1339                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
[580]1340        }
1341
1342    const float renderCost = GetRenderCost(vc);
1343        return fabs(mExpectedCost - renderCost);
1344}
1345
1346
1347float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1348{
1349        if (mUseAreaForPvs)
[1141]1350        {
[1168]1351                return vc->GetPvs().CountObjectsInPvs() * vc->GetArea();
[1141]1352        }
[580]1353
[1168]1354        return vc->GetPvs().CountObjectsInPvs() * vc->GetVolume();
[580]1355}
1356
1357
1358float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1359{
1360        return GetRenderCost(vc) * mRenderCostWeight +
1361                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1362}
1363
1364
[582]1365bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
[580]1366{
[752]1367        // propagate up so we have only the active view cells
[580]1368        while (mc.mLeftViewCell->mParent)
1369        {
1370                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1371        }
1372
1373        while (mc.mRightViewCell->mParent)
1374        {
1375                mc.mRightViewCell = mc.mRightViewCell->mParent;
1376        }
1377
[752]1378        // this view cell was already merged
1379        //return mc.mLeftViewCell && (mc.mLeftViewCell != mc.mRightViewCell);
[582]1380        return mc.mLeftViewCell != mc.mRightViewCell;
[580]1381}
1382
1383
1384void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1385{
[1586]1386        ///////////////////
[580]1387        //-- compute pvs difference
[1586]1388
[752]1389        int newPvs;
[1586]1390       
[752]1391        if (1) // not valid if not using const cost per object!!
[1586]1392        {
[752]1393                newPvs = ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
[1586]1394        }
[752]1395        else
[1586]1396        {
[752]1397                newPvs = (int)ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
[1586]1398        }
[580]1399
[1141]1400        const float newPenalty = EvalPvsPenalty(newPvs,
[729]1401                                                                                        mViewCellsManager->GetMinPvsSize(),
1402                                                                                        mViewCellsManager->GetMaxPvsSize());
1403
[580]1404        ViewCell *vc1 = mc.mLeftViewCell;
1405        ViewCell *vc2 = mc.mRightViewCell;
1406
1407        //-- compute ratio of old cost
[1586]1408        //-- (i.e., added size of left and right view cell times pvs size)
1409        //-- to new rendering cost (i.e, size of merged view cell times pvs size)
[580]1410        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1411
1412    const float newCost = mUseAreaForPvs ?
1413                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1414                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1415
1416
1417        // strong penalty if pvs size too large
1418        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1419        {
1420                mc.mRenderCost = 1e20f;
1421        }
1422        else
1423        {
1424                mc.mRenderCost = (newCost - oldCost) /
1425                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1426        }       
1427       
[1586]1428        ///////////////////////////
1429        //-- merge cost also takes deviation into account
[580]1430
1431        float newDev, oldDev;
1432
1433        if (1)
[582]1434                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
[580]1435        else
[582]1436                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
[580]1437       
1438        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1439
1440        // compute deviation increase
1441        mc.mDeviationIncr = newDev - oldDev;
1442       
1443        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1444        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1445}
1446
[752]1447
1448void ViewCellsTree::SetViewCellsStorage(int stype)
[580]1449{
[752]1450        if (mViewCellsStorage == stype)
1451                return;
1452
1453        // TODO
1454        switch (stype)
[581]1455        {
[752]1456        case COMPRESSED:
[584]1457                CompressViewCellsPvs(mRoot);
[752]1458                break;
1459        default:
1460                break;
[584]1461        }
[752]1462
1463        mViewCellsStorage = stype;
[584]1464}
[580]1465
[752]1466
[584]1467void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
1468{
1469        if (!root->IsLeaf())
1470        {
1471                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
1472
1473        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[585]1474               
[584]1475                // compress child sets first
1476                for (it = interior->mChildren.begin(); it != it_end; ++ it)
[581]1477                {
[584]1478                        CompressViewCellsPvs(*it);
[581]1479                }
[584]1480
[585]1481                // compress root node
[610]1482                PullUpVisibility(interior);
[581]1483        }
[580]1484}
1485
1486
[1166]1487void ViewCellsTree::UpdateStats(ofstream &stats,
1488                                                                const int pass,
1489                                                                const int viewCells,
1490                                                                const float renderCostDecrease,
1491                                                                const float totalRenderCost,
1492                                                                const int currentPvs,
1493                                                                const float expectedCost,
1494                                                                const float avgRenderCost,
1495                                                                const float deviation,
1496                                                                const int totalPvs,
1497                                                                const int entriesInPvs,
[1653]1498                                                                const float memoryCost,
[1166]1499                                                                const int pvsSizeDecr,
1500                                                                const float volume)
1501{
1502         stats << "#Pass\n" << pass << endl
[1660]1503                   << "#Splits\n" << viewCells << endl
[1653]1504                   << "#RenderCostDecrease\n" << renderCostDecrease << endl // TODO
1505                   << "#TotalRenderCost\n" << totalRenderCost << endl
1506                   << "#CurrentPvs\n" << currentPvs << endl
1507                   << "#ExpectedCost\n" << expectedCost << endl
1508                   << "#AvgRenderCost\n" << avgRenderCost << endl
1509                   << "#Deviation\n" << deviation << endl
1510                   << "#TotalPvs\n" << totalPvs << endl
1511                   << "#TotalEntriesInPvs\n" << entriesInPvs << endl
1512                   << "#Memory\n" << memoryCost << endl
1513                   << "#PvsSizeDecrease\n" << pvsSizeDecr << endl
1514                   << "#Volume\n" << volume << endl
1515                   << endl;
[1166]1516}
1517
[1489]1518
[660]1519void ViewCellsTree::ExportStats(const string &mergeStats)
[650]1520{
1521        TraversalQueue tqueue;
1522        tqueue.push(mRoot);
[1666]1523
[1695]1524        //cout << "exporting stats ... " << endl;
[650]1525        int numViewCells = 1;
1526       
1527        const AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1528        const float vol = box.GetVolume();
1529
[752]1530        const int rootPvs = GetPvsSize(mRoot);
[1161]1531        const int rootEntries = GetPvsEntries(mRoot);
[651]1532        float totalRenderCost, avgRenderCost, expectedCost;
[650]1533
1534        float deviation = 0;
[1166]1535        int totalPvs = rootPvs;
1536        int entriesInPvs = rootEntries;
1537
[752]1538        totalRenderCost = avgRenderCost = expectedCost = (float)rootPvs;
[650]1539
1540        ofstream stats;
[660]1541        stats.open(mergeStats.c_str());
[650]1542
[1667]1543        const float memoryCost = (float)entriesInPvs * ObjectPvs::GetEntrySize();
[1653]1544
[1603]1545        /////////////
[752]1546        //-- first view cell
[1603]1547
[1166]1548        UpdateStats(stats,
[1653]1549                                0,
1550                                numViewCells,
1551                                0,
1552                                totalRenderCost,
1553                                rootPvs,
1554                                expectedCost,
1555                                avgRenderCost,
1556                                deviation,
1557                                totalPvs,
1558                                entriesInPvs,
1559                                memoryCost,
1560                                0,
1561                                mRoot->GetVolume());
[1166]1562               
[650]1563
[1161]1564        //-- go through tree in the order of render cost decrease
1565        //-- which is the same order as the view cells were merged
1566        //-- or the reverse order of subdivision for subdivision-only
1567        //-- view cell hierarchies.
[650]1568
1569        while (!tqueue.empty())
1570        {
1571                ViewCell *vc = tqueue.top();
1572                tqueue.pop();
1573
1574                if (!vc->IsLeaf())
1575                {       
1576                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1166]1577
[752]1578                        const int parentPvs = GetPvsSize(interior);
[1166]1579                        const int parentPvsEntries = GetPvsEntries(interior);
1580            const float parentCost = (float)parentPvs * interior->GetVolume();
1581
[650]1582                        float childCost = 0;
1583                        int childPvs = 0;
[1166]1584                        int childPvsEntries = 0;
[650]1585
1586                        -- numViewCells;
1587
1588                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1179]1589
[650]1590                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1591                        {
[1166]1592                                ViewCell *vc = *it;
[1168]1593
[1166]1594                                const int pvsSize = GetPvsSize(vc);
1595                                const int pvsEntries = GetPvsEntries(vc);
1596
1597                                childCost += (float) pvsSize * vc->GetVolume();
[752]1598                                childPvs += pvsSize;
[1166]1599                                childPvsEntries += pvsEntries;
[650]1600
[1166]1601                                tqueue.push(vc);
[650]1602                                ++ numViewCells;
1603                        }
1604
[1603]1605                        // update stats for this view cell
[650]1606                        const float costDecr = (parentCost - childCost) / vol;
1607
1608                        totalRenderCost -= costDecr;
1609                        totalPvs += childPvs - parentPvs;
[1166]1610                        entriesInPvs += childPvsEntries - parentPvsEntries;
1611
[650]1612                        expectedCost = totalRenderCost / (float)numViewCells;
1613                        avgRenderCost = (float)totalPvs / (float)numViewCells;
1614
[1667]1615                        const float memoryCost = (float)entriesInPvs * ObjectPvs::GetEntrySize();
[1653]1616
[1166]1617                        UpdateStats(stats,
[1653]1618                                                0,
1619                                                numViewCells,
1620                                                costDecr,
1621                                                totalRenderCost,
1622                                                parentPvs,
1623                                                expectedCost,
1624                                                avgRenderCost,
1625                                                deviation,
1626                        totalPvs,
1627                                                entriesInPvs,
1628                                                memoryCost,
1629                                                childPvs - parentPvs,
[1166]1630                                                vc->GetVolume());
[650]1631                }
1632        }
1633
1634        stats.close();
1635}
1636
1637
1638void ViewCellsTree::SetRoot(ViewCell *root)
1639{
1640        mRoot = root;
1641}
1642
[660]1643
[581]1644void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1645                                                                                   const int numViewCells)
[580]1646{
1647        TraversalQueue tqueue;
[581]1648        tqueue.push(mRoot);
[582]1649       
[580]1650        while (!tqueue.empty())
1651        {
1652                ViewCell *vc = tqueue.top();
[650]1653                tqueue.pop();
1654
[582]1655                // save the view cells if it is a leaf or if enough view cells have already been traversed
1656                // because of the priority queue, this will be the optimal set of v
[650]1657                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size() + 1) >= numViewCells))
[581]1658                {
1659                        viewCells.push_back(vc);
1660                }
[582]1661                else
1662                {       
[581]1663                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[580]1664
[581]1665                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1666
1667                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1668                        {
1669                                tqueue.push(*it);
1670                        }
1671                }
[580]1672        }
1673}
[581]1674       
[580]1675
[610]1676void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
[581]1677{
[584]1678        Intersectable::NewMail((int)interior->mChildren.size());
[580]1679
[581]1680        ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
1681
1682        ObjectPvsMap::const_iterator oit;
1683
1684        // mail all objects in the leaf sets
[584]1685        // we are interested in the objects which are present in all leaves
1686        // => count how often an object is part of a child set
[581]1687        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1688        {
1689                ViewCell *vc = *cit;
1690
1691                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1692
1693                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1694                {
[584]1695                        Intersectable *obj = (*oit).first;
1696                        if ((cit == interior->mChildren.begin()) && !obj->Mailed())
1697                                obj->Mail();
[581]1698                       
[584]1699                        int incm = obj->IncMail();
[581]1700                }
1701        }
1702
[1189]1703        interior->GetPvs().Clear();
[581]1704       
[584]1705       
[581]1706        // only the objects which are present in all leaf pvs
1707        // should remain in the parent pvs
[584]1708        // these are the objects which have been mailed in all children
[581]1709        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1710        {
1711                ViewCell *vc = *cit;
1712
1713                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1714
1715                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
[585]1716                {               
[581]1717                        if ((*oit).first->Mailed((int)interior->mChildren.size()))
1718                        {       
1719                                interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
1720                        }
1721                }
1722        }
1723
[584]1724
1725        // delete all the objects from the leaf sets which were moved to parent pvs
[581]1726        ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
1727
1728        for (oit = interior->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1729        {
1730                for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1731                {
[584]1732                        if (!(*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity))
[1189]1733                        {
[584]1734                                Debug << "should not come here!" << endl;
[1189]1735                        }
[581]1736                }
1737        }
1738}
1739
[1168]1740
[1166]1741// TODO matt: implement this function for different storing methods
[584]1742void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
1743{
[1161]1744        // pvs is stored in each cell => just return pvs
[752]1745        if (mViewCellsStorage == PVS_IN_INTERIORS)
[801]1746        {
[585]1747                pvs = vc->GetPvs();
[801]1748                return;
1749        }
[585]1750
[1161]1751
1752        //-- pvs is not stored with the interiors => reconstruct
[801]1753        Intersectable::NewMail();
1754
[585]1755        int pvsSize = 0;
1756        ViewCell *root = vc;
1757       
[883]1758        // add pvs from this view cell to root
[585]1759        while (root->GetParent())
[584]1760        {
[585]1761                root = root->GetParent();
1762                pvs.AddPvs(root->GetPvs());
1763        }
[584]1764
[883]1765        // add pvs from leaves
[585]1766        stack<ViewCell *> tstack;
1767        tstack.push(vc);
[584]1768
[585]1769        while (!tstack.empty())
1770        {
1771                vc = tstack.top();
1772                tstack.pop();
1773
[1161]1774                // add newly found pvs to merged pvs
[585]1775                pvs.AddPvs(vc->GetPvs());
1776
[1161]1777                if (!vc->IsLeaf()) // interior cells: go down to leaf level
[584]1778                {
1779                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[585]1780
[584]1781                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1782
1783                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1784                        {
[585]1785                                tstack.push(*it);
1786                        }               
[584]1787                }
1788        }
1789}
1790
1791
[1166]1792int ViewCellsTree::GetPvsSizeForLeafStorage(ViewCell *vc) const
[584]1793{
[1166]1794        // pvs is always stored directly in leaves
1795        if (vc->IsLeaf())
1796        {
[1168]1797                return vc->GetPvs().CountObjectsInPvs();
[1166]1798        }
[1168]1799       
1800        // interior nodes: pvs is either stored as a scalar or
1801        // has to be reconstructed from the leaves
1802        // the stored pvs size is the valid pvs size => just return scalar
1803        if (vc->mPvsSizeValid)
[1166]1804        {
[1168]1805                return vc->mPvsSize;
1806        }
1807       
1808        // if no valid pvs size stored as a scalar =>
1809        // compute current pvs size of interior from it's leaf nodes
1810        ViewCellContainer leaves;
1811        CollectLeaves(vc, leaves);
[1121]1812
[1168]1813        ViewCellContainer::const_iterator it, it_end = leaves.end();
[1166]1814
[1168]1815        Intersectable::NewMail();
1816        ObjectPvs newPvs;
[1166]1817
[1586]1818        // sum up uniquely found intersectables
[1168]1819        for (it = leaves.begin(); it != it_end; ++ it)
1820        {
1821                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1822
1823                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
[1166]1824                {
[1168]1825                        Intersectable *intersect = (*oit).first;
1826
1827                        if (!intersect->Mailed())
1828                        {
1829                                intersect->Mail();
1830                                newPvs.AddSample(intersect, (*oit).second.mSumPdf);
1831                        }
[1166]1832                }
1833        }
1834
[1168]1835        return newPvs.CountObjectsInPvs();
[1166]1836}
1837
1838
1839int ViewCellsTree::GetEntriesInPvsForLeafStorage(ViewCell *vc) const
1840{
1841        // pvs is always stored directly in leaves
1842        if (vc->IsLeaf())
[752]1843        {
[1168]1844                return vc->GetPvs().GetSize();
[1166]1845        }
[1168]1846       
1847        // interior node
1848
1849        // interior nodes: pvs is either stored as a scalar or
1850        // has to be reconstructed from the leaves
1851
1852        // the stored pvs size is the valid pvs size => just return scalar
1853        if (vc->mPvsSizeValid)
[1166]1854        {
[1168]1855                return vc->mEntriesInPvs;
1856        }
1857       
1858        int pvsSize = 0;
[1161]1859
[1168]1860        // if no valid pvs size stored as a scalar =>
1861        // compute current pvs size of interior from it's leaf nodes
1862        ViewCellContainer leaves;
1863        CollectLeaves(vc, leaves);
[1161]1864
[1168]1865        ViewCellContainer::const_iterator it, it_end = leaves.end();
1866        Intersectable::NewMail();
[1161]1867
[1168]1868        // sum different intersectables
1869        for (it = leaves.begin(); it != it_end; ++ it)
1870        {
1871                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
[1161]1872
[1168]1873                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
[1166]1874                {
[1168]1875                        Intersectable *intersect = (*oit).first;
1876
1877                        if (!intersect->Mailed())
1878                        {
1879                                intersect->Mail();
1880                                ++ pvsSize;
1881                        }
[1166]1882                }
1883        }
[1161]1884
[1166]1885        return pvsSize;
1886}
[1161]1887
1888
[1166]1889int ViewCellsTree::GetPvsSizeForCompressedStorage(ViewCell *vc) const
1890{
1891        int pvsSize = 0;
1892
[1545]1893        /////////////
[1166]1894        //-- compressed pvs
1895
1896        // the stored pvs size is the valid pvs size => just return scalar
1897        if (vc->mPvsSizeValid)
1898        {
1899                pvsSize = vc->mPvsSize;
1900        }
1901
1902        // if no pvs size stored, compute new one
1903        ViewCell *root = vc;
1904       
1905        // also add pvs from this view cell to root
1906        while (root->GetParent())
1907        {
1908                root = root->GetParent();
1909       
1910                // matt: bug! must evaluate kd pvss also
[1586]1911                pvsSize += CountPvsContribution(root);
[1166]1912        }
1913
1914        stack<ViewCell *> tstack;
1915        tstack.push(vc);
1916
1917        while (!tstack.empty())
1918        {
1919                vc = tstack.top();
1920                tstack.pop();
1921                // matt: bug! must evaluate kd pvss also
[1586]1922                pvsSize += CountPvsContribution(vc);
[1166]1923
1924                if (!vc->IsLeaf())
[1161]1925                {
[1166]1926                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]1927
[1166]1928                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1929
1930                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[752]1931                        {
[1166]1932                                tstack.push(*it);
1933                        }               
1934                }
1935        }
[1161]1936
[1166]1937        return pvsSize;
1938}
1939
1940
1941int ViewCellsTree::GetEntriesInPvsForCompressedStorage(ViewCell *vc) const
1942{
1943        int pvsSize = 0;
1944
[1586]1945        /////////////////
[1166]1946        //-- compressed pvs
1947
1948        // the stored pvs size is the valid pvs size => just return scalar
1949        if (vc->mPvsSizeValid)
1950        {
1951                pvsSize = vc->mEntriesInPvs;
1952        }
1953
1954        // if no pvs size stored, compute new one
1955        ViewCell *root = vc;
[752]1956       
[1166]1957        // also add pvs from this view cell to root
1958        while (root->GetParent())
1959        {
1960                root = root->GetParent();
1961                // count the pvs entries different from the already found ones 
[1586]1962                pvsSize += CountPvsContribution(root);
[1166]1963        }
[585]1964
[1166]1965        stack<ViewCell *> tstack;
1966        tstack.push(vc);
[719]1967
[1166]1968        while (!tstack.empty())
1969        {
1970                vc = tstack.top();
1971                tstack.pop();
[1161]1972       
[1166]1973                // count the pvs entries different from the already found ones 
[1586]1974                pvsSize += CountPvsContribution(vc);
[752]1975
[1166]1976                if (!vc->IsLeaf())
1977                {
1978                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]1979
[1166]1980                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1161]1981
[1166]1982                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1983                        {
1984                                tstack.push(*it);
1985                        }               
1986                }
1987        }
1988
1989        return pvsSize;
1990}
1991
1992
1993int ViewCellsTree::GetPvsSize(ViewCell *vc) const
1994{
1995        int pvsSize = 0;
1996        Intersectable::NewMail();
1997
1998        ////////////////////////////////////////////////
[1311]1999        // for interiors, pvs can be stored using different methods
[1166]2000        //
2001
2002        switch (mViewCellsStorage)
2003        {
2004        case PVS_IN_LEAVES: //-- store pvs only in leaves
[1311]2005                pvsSize = GetPvsSizeForLeafStorage(vc);                 
2006                break;
[1166]2007        case COMPRESSED:
[1311]2008                pvsSize = GetPvsSizeForCompressedStorage(vc);
2009                break;
[1161]2010        case PVS_IN_INTERIORS:
2011        default:
2012                // pvs is stored consistently in the tree up to the root
2013                // just return pvs size
[1168]2014                pvsSize = vc->GetPvs().CountObjectsInPvs();     
[1161]2015                break;
2016        }
2017
2018        return pvsSize; 
2019}
2020
2021
2022int ViewCellsTree::GetPvsEntries(ViewCell *vc) const
2023{
2024        int pvsSize = 0;
2025
2026        Intersectable::NewMail();
2027
2028        ////////////////////////////////////////////////
2029        // for interiors, pvs can be stored using different methods
2030       
2031        switch (mViewCellsStorage)
2032        {
[1622]2033        case PVS_IN_LEAVES:
2034                {
2035                        //-- store pvs only in leaves
[1166]2036                        pvsSize = GetEntriesInPvsForLeafStorage(vc);
2037                        break;
[752]2038                }
2039        case COMPRESSED:
2040                {
[1166]2041                        pvsSize = GetEntriesInPvsForCompressedStorage(vc);
[752]2042                        break;
2043                }
2044        case PVS_IN_INTERIORS:
[997]2045        default:
[1161]2046                // pvs is stored consistently in the tree up to the root
2047                // just return pvs size
2048                pvsSize = vc->GetPvs().GetSize();       
2049                break;
[752]2050        }
[584]2051
2052        return pvsSize; 
2053}
2054
2055
2056float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
2057{
[1667]2058        return (float)CountStoredPvsEntries(vc) * ObjectPvs::GetEntrySize();
[584]2059}
2060
[1586]2061//#if HAS_TO_BE_REDONE
2062int ViewCellsTree::CountStoredPvsEntries(ViewCell *root) const
[584]2063{
[1161]2064        int pvsSize = root->GetPvs().GetSize();
[584]2065
[1161]2066        // recursivly count leaves
2067        if (!root->IsLeaf())
[584]2068        {
[1161]2069                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
[584]2070
2071                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2072
2073                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2074                {
[1586]2075                        pvsSize += CountStoredPvsEntries(*it);
[584]2076                }
2077        }
2078
2079        return pvsSize;         
2080}
[1586]2081//#endif
[584]2082
[752]2083int ViewCellsTree::ViewCellsStorage() const
[584]2084{
[752]2085        return mViewCellsStorage;
[584]2086}
2087
2088
[881]2089ViewCell *ViewCellsTree::GetActiveViewCell(ViewCellLeaf *vc) const
[590]2090{
[881]2091        return vc->GetActiveViewCell();
[590]2092}
2093
2094
[651]2095void ViewCellsTree::PropagatePvs(ViewCell *vc)
[664]2096{       
2097        ViewCell *viewCell = vc;
2098
[660]2099        // propagate pvs up
[664]2100        while (viewCell->GetParent())
[610]2101        {
[664]2102                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
2103                viewCell = viewCell->GetParent();
[610]2104        }
[651]2105
2106        if (vc->IsLeaf())
2107                return;
2108
[660]2109        // propagate pvs to the leaves
[651]2110        stack<ViewCell *> tstack;
2111        tstack.push(vc);
2112
2113        while (!tstack.empty())
2114        {
2115                ViewCell *viewCell = tstack.top();
2116                tstack.pop();
2117
2118                if (viewCell != vc)
2119                {
2120                        viewCell->GetPvs().Merge(vc->GetPvs());
2121                }
2122
2123                if (!viewCell->IsLeaf())
2124                {
2125                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
[664]2126
[651]2127                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2128
2129                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2130                        {
2131                                tstack.push(*it);
2132                        }
2133                }
2134        }
[610]2135}
[605]2136
[610]2137
[650]2138void ViewCellsTree::AssignRandomColors()
[608]2139{
[675]2140        TraversalQueue tqueue;
2141        tqueue.push(mRoot);
[708]2142       
[675]2143        mRoot->SetColor(RandomColor(0.3f, 1.0f));
2144       
2145        while (!tqueue.empty())
[608]2146        {
[675]2147                ViewCell *vc = tqueue.top();
2148                tqueue.pop();
[650]2149
[675]2150                // save the view cells if it is a leaf or if enough view cells have already been traversed
2151                // because of the priority queue, this will be the optimal set of v
2152                if (!vc->IsLeaf())
2153                {       
2154                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2155                 
2156                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2157                 
2158                        float maxProbability = -1.0f;
2159                 
2160                        ViewCell *maxViewCell = NULL;
2161                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2162                        {
2163                                ViewCell *v = *it;
2164                         
2165                                // set random color
2166                                v->SetColor(RandomColor(0.3f, 1.0f));
2167                         
2168                                if (v->GetVolume() > maxProbability)
2169                                {
2170                                        maxProbability = v->GetVolume();
2171                                        maxViewCell = v;
2172                                }
2173
2174                                if (maxViewCell)
[708]2175                                {
[675]2176                                        maxViewCell->SetColor(vc->GetColor());
[708]2177                                }
[675]2178                               
2179                                tqueue.push(v);
2180                        }
2181                }       
[608]2182        }
2183}
2184
[675]2185
[1161]2186/** Get costs resulting from each merge step.
2187*/
[1603]2188void ViewCellsTree::GetCostFunction(vector<float> &costFunction)
[608]2189{
[1603]2190        TraversalQueue tqueue;
2191        tqueue.push(mRoot);
2192
2193        int numViewCells = 1;
2194
2195        const float vol = mViewCellsManager->GetViewSpaceBox().GetVolume();
2196        const int rootPvs = GetPvsSize(mRoot);
2197       
2198        float totalRenderCost;
2199
2200        int totalPvs = rootPvs;
2201        totalRenderCost = (float)rootPvs;
2202
2203        costFunction.push_back(totalRenderCost);
2204
2205        //-- go through tree in the order of render cost decrease
2206        //-- which is the same order as the view cells were merged
2207        //-- or the reverse order of subdivision for subdivision-only
2208        //-- view cell hierarchies.
2209
2210        while (!tqueue.empty())
[1161]2211        {
[1603]2212                ViewCell *vc = tqueue.top();
2213                tqueue.pop();
2214
2215                if (!vc->IsLeaf())
2216                {       
2217                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2218
2219                        const int parentPvs = GetPvsSize(interior);
2220                        const float parentCost = (float)parentPvs * interior->GetVolume();
2221
2222                        -- numViewCells;
2223
2224                        float childCost = 0;
2225                        int childPvs = 0;
2226                       
2227                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2228
2229                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2230                        {
2231                                ViewCell *vc = *it;
2232
2233                                const int pvsSize = GetPvsSize(vc);
2234                               
2235                                childCost += (float) pvsSize * vc->GetVolume();
2236                                childPvs += pvsSize;
2237                               
2238                                tqueue.push(vc);
2239                                ++ numViewCells;
2240                        }
2241
2242                        // update stats for this view cell
2243                        const float costDecr = (parentCost - childCost) / vol;
2244                        totalRenderCost -= costDecr;
2245                        const float expectedCost = totalRenderCost ;/// (float)numViewCells;
[1585]2246               
[1603]2247                        costFunction.push_back(expectedCost);
[1161]2248                }
[608]2249        }
2250}
2251
2252
[1603]2253/** Get storage costs resulting from each merge step.
2254*/
2255void ViewCellsTree::GetStorageFunction(vector<int> &storageFunction)
2256{
2257        TraversalQueue tqueue;
2258        tqueue.push(mRoot);
2259
2260        int numViewCells = 1;
2261
2262        const float vol = mViewCellsManager->GetViewSpaceBox().GetVolume();
2263        const int rootEntries = GetPvsEntries(mRoot);
2264
2265        int entriesInPvs = rootEntries;
[1605]2266    const int entryStorage = sizeof(PvsData) + sizeof(int); // one entry into the pvs
[1603]2267
2268        storageFunction.push_back(rootEntries);
2269
2270        ////////////
2271        //-- go through tree in the order of render cost decrease
2272        //-- which is the same order as the view cells were merged
2273        //-- or the reverse order of subdivision for subdivision-only
2274        //-- view cell hierarchies.
2275
2276        while (!tqueue.empty())
2277        {
2278                ViewCell *vc = tqueue.top();
2279                tqueue.pop();
2280
2281                if (!vc->IsLeaf())
2282                {       
2283                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2284
2285                        const int parentPvs = GetPvsSize(interior);
2286                        const int parentPvsEntries = GetPvsEntries(interior);
2287            const float parentCost = (float)parentPvs * interior->GetVolume();
2288
2289                        float childCost = 0;
2290                        int childPvs = 0;
2291                        int childPvsEntries = 0;
2292
2293                        -- numViewCells;
2294
2295                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2296
2297                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2298                        {
2299                                ViewCell *vc = *it;
2300
2301                                //const int pvsSize = GetPvsSize(vc);
2302                                const int pvsEntries = GetPvsEntries(vc);
2303
2304                                //childPvs += pvsSize;
2305                                childPvsEntries += pvsEntries;
2306
2307                                tqueue.push(vc);
2308                                ++ numViewCells;
2309                        }
2310
2311                        // update stats for this view cell
2312                        const float costDecr = (parentCost - childCost) / vol;
2313
2314                        //totalPvs += childPvs - parentPvs;
2315                        entriesInPvs += childPvsEntries - parentPvsEntries;
2316
2317                        const int storageCost = entriesInPvs * entryStorage;
2318                        storageFunction.push_back(storageCost);
2319                }
2320        }
2321}
2322
2323
2324
[1161]2325void ViewCellsTree::UpdateViewCellsStats(ViewCell *vc,
2326                                                                                 ViewCellsStatistics &vcStat)
[605]2327{
2328        ++ vcStat.viewCells;
2329               
2330        const int pvsSize = GetPvsSize(vc);
2331
[613]2332        vcStat.pvsSize += pvsSize;
[605]2333
2334        if (pvsSize == 0)
2335                ++ vcStat.emptyPvs;
2336
2337        if (pvsSize > vcStat.maxPvs)
2338                vcStat.maxPvs = pvsSize;
2339
2340        if (pvsSize < vcStat.minPvs)
2341                vcStat.minPvs = pvsSize;
2342
2343        if (!vc->GetValid())
2344                ++ vcStat.invalid;
2345}
2346
[1161]2347
[1201]2348bool ViewCellsTree::Export(OUT_STREAM &stream, const bool exportPvs)
[610]2349{
[840]2350        // export recursivly all view cells from the root
[844]2351        ExportViewCell(mRoot, stream, exportPvs);
[605]2352
[610]2353        return true;
2354}
2355
2356
[651]2357void ViewCellsTree::CreateUniqueViewCellsIds()
[610]2358{
[651]2359        stack<ViewCell *> tstack;
[610]2360
[651]2361        int currentId = 0;
2362
2363        tstack.push(mRoot);
2364
2365        while (!tstack.empty())
[610]2366        {
[651]2367                ViewCell *vc = tstack.top();
2368                tstack.pop();
2369
[1551]2370                if (vc->GetId() != -1) // out of bounds
2371                        vc->SetId(currentId ++);
[651]2372
2373                if (!vc->IsLeaf())
2374                {
2375                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]2376                       
[651]2377                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2378                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2379                        {
2380                                tstack.push(*it);
2381                        }
2382                }
[610]2383        }
[651]2384}
[610]2385
[1201]2386
2387void ViewCellsTree::ExportPvs(ViewCell *viewCell, OUT_STREAM &stream)
[651]2388{
2389        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
2390
[837]2391        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
2392        {
[1614]2393                Intersectable *obj = (*it).first;
2394                // hack: just output full pvs
2395                if (obj->Type() == Intersectable::BVH_INTERSECTABLE)
2396                {
2397                        ObjectContainer objects;
2398                        BvhNode *node = dynamic_cast<BvhIntersectable *>(obj)->GetItem();
2399                        node->CollectObjects(objects);
2400               
2401                        ObjectContainer::const_iterator oit, oit_end = objects.end();
2402                        for (oit = objects.begin(); oit != oit_end; ++ oit)
2403                        {
2404                                stream << (*oit)->GetId() << " ";
2405                        }
2406                }
2407                else
2408                {
2409                        stream << (*it).first->GetId() << " ";
2410                }
[837]2411        }
2412}
2413
[1201]2414
2415void ViewCellsTree::ExportViewCell(ViewCell *viewCell,
2416                                                                   OUT_STREAM &stream,
2417                                                                   const bool exportPvs)
[837]2418{
[610]2419        if (viewCell->IsLeaf())
2420        {
2421                stream << "<Leaf ";
2422                stream << "id=\"" << viewCell->GetId() << "\" ";
[881]2423                stream << "active=\"" << dynamic_cast<ViewCellLeaf *>(viewCell)->GetActiveViewCell()->GetId() << "\" ";
[610]2424                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2425                stream << "pvs=\"";
[837]2426               
[1551]2427                //-- export pvs, i.e., the ids of the objects in the pvs
[844]2428                if (exportPvs)
[955]2429                {
[840]2430                        ExportPvs(viewCell, stream);
[955]2431                }
[651]2432                stream << "\" />" << endl;
[610]2433        }
2434        else
2435        {
2436                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2437       
2438                stream << "<Interior ";
2439                stream << "id=\"" << viewCell->GetId() << "\" ";
2440                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
[870]2441                stream << "pvs=\"";
2442
[1551]2443                // NOTE: do not export pvss for interior view cells because
[870]2444                // they can be completely reconstructed from the leaf pvss
[1551]2445                // on the other hand: we could store a tag with the compression scheme,
2446        // then some scheme were pvs is in the interiors could be used
2447                if (0) ExportPvs(viewCell, stream);
[870]2448               
[651]2449                stream << "\" >" << endl;
2450
[837]2451                //-- recursivly export child view cells
[610]2452                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2453
2454                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2455                {
[844]2456                        ExportViewCell(*it, stream, exportPvs);
[610]2457                }
2458
2459                stream << "</Interior>" << endl;
2460        }
2461}
2462
2463
[660]2464void ViewCellsTree::ResetPvs()
2465{
2466        stack<ViewCell *> tstack;
[610]2467
[660]2468        tstack.push(mRoot);
2469
2470        while (!tstack.empty())
2471        {
2472                ViewCell *vc = tstack.top();
2473                tstack.pop();
2474
[1189]2475                vc->GetPvs().Clear();
[666]2476               
[660]2477                if (!vc->IsLeaf())
2478                {
2479                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2480                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[666]2481
[660]2482                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2483                        {
2484                                tstack.push(*it);
2485                        }
2486                }
2487        }
2488}
2489
2490
[1551]2491void ViewCellsTree::SetViewCellsManager(ViewCellsManager *vcm)
2492{
2493        mViewCellsManager = vcm;
2494}
2495
2496
[660]2497void ViewCellsTree::SetActiveSetToLeaves()
2498{
[752]2499        // todo
[660]2500}
2501
[1603]2502
2503
[580]2504/**************************************************************************/
2505/*                     MergeCandidate implementation                      */
2506/**************************************************************************/
2507
2508
2509MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2510mRenderCost(0),
2511mDeviationIncr(0),
2512mLeftViewCell(l),
[586]2513mRightViewCell(r),
2514mInitialLeftViewCell(l),
2515mInitialRightViewCell(r)
[580]2516{
2517        //EvalMergeCost();
2518}
2519
2520
2521void MergeCandidate::SetRightViewCell(ViewCell *v)
2522{
2523        mRightViewCell = v;
2524}
2525
2526
2527void MergeCandidate::SetLeftViewCell(ViewCell *v)
2528{
2529        mLeftViewCell = v;
2530}
2531
2532
2533ViewCell *MergeCandidate::GetRightViewCell() const
2534{
2535        return mRightViewCell;
2536}
2537
2538
2539ViewCell *MergeCandidate::GetLeftViewCell() const
2540{
2541        return mLeftViewCell;
2542}
2543
2544
2545ViewCell *MergeCandidate::GetInitialRightViewCell() const
2546{
2547        return mInitialRightViewCell;
2548}
2549
2550
2551ViewCell *MergeCandidate::GetInitialLeftViewCell() const
2552{
2553        return mInitialLeftViewCell;
2554}
2555
2556
2557bool MergeCandidate::IsValid() const
2558{
[752]2559        // if one has a parent, it was already merged
[1002]2560        return !(mLeftViewCell->GetParent() || mRightViewCell->GetParent());
[580]2561}
2562
2563
2564float MergeCandidate::GetRenderCost() const
2565{
2566        return mRenderCost;
2567}
2568
2569
2570float MergeCandidate::GetDeviationIncr() const
2571{
2572        return mDeviationIncr;
2573}
2574
2575
2576float MergeCandidate::GetMergeCost() const
2577{
2578        return mRenderCost * sRenderCostWeight +
2579                   mDeviationIncr * (1.0f - sRenderCostWeight);
2580}
2581
2582
[605]2583
[580]2584/************************************************************************/
2585/*                    MergeStatistics implementation                    */
2586/************************************************************************/
2587
2588
2589void MergeStatistics::Print(ostream &app) const
2590{
2591        app << "===== Merge statistics ===============\n";
2592
2593        app << setprecision(4);
2594
2595        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2596
2597        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2598
2599        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2600
2601        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2602
2603        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2604
2605        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2606
2607        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2608
2609        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2610
2611        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2612
2613        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2614
2615        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2616
2617        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2618
2619        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2620       
2621
2622        app << "===== END OF BspTree statistics ==========\n";
[608]2623}
[860]2624
[1199]2625}
Note: See TracBrowser for help on using the repository browser.