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

Revision 1201, 56.8 KB checked in by mattausch, 18 years ago (diff)

added loader for osp trees

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