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

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