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

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