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

Revision 1284, 56.7 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
309/************************************************************************/
310/*                class ViewCellsStatistics implementation              */
311/************************************************************************/
312
313
314
315
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
324        app << "#N_OVERALLPVS ( objects in PVS )\n" << pvsSize << endl;
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
332        app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
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       
340        app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
341
342        app << "========== End of View Cells Statistics ==========\n";
343}
344
345
346/*************************************************************************/
347/*                    class ViewCellsTree implementation                 */
348/*************************************************************************/
349
350
351ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
352mRoot(NULL),
353mUseAreaForPvs(false),
354mViewCellsManager(vcm),
355#if 0
356mViewCellsStorage(PVS_IN_INTERIORS)
357#else
358mViewCellsStorage(PVS_IN_LEAVES)
359#endif
360{
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{
383        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
384        Environment::GetSingleton()->GetFloatValue("ViewCells.maxStaticMemory", mMaxMemory);
385
386        //-- merge options
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);   
391
392        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", mMaxMergesPerPass);
393        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", mAvgCostMaxDeviation);
394
395        Debug << "============= view cell tree options ================\n";
396        Debug << "minimum view cells: " << mMergeMinViewCells << endl;
397        Debug << "max cost ratio: " << mMergeMaxCostRatio << endl;
398        Debug << "max memory: " << mMaxMemory << endl;
399        Debug << "refining view cells: " << mRefineViewCells << endl;
400        Debug << "=========== end view cell tree options ===============\n";
401}
402
403
404// return memory usage in MB
405float ViewCellsTree::GetMemUsage() const
406{
407        // TODO
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
416int ViewCellsTree::GetNumInitialViewCells(ViewCell *vc) const
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);
436
437                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
438                       
439                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
440                        {
441                                tstack.push(*it);
442                        }
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();
470
471                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
472                        {
473                                tstack.push(*it);
474                        }
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{
490        mNumActiveViewCells = (int)mViewCellsManager->GetViewCells().size();
491
492        float variance = 0;
493        int totalPvs = 0;
494        float totalRenderCost = 0;
495
496        //-- compute statistics values of initial view cells
497        mViewCellsManager->EvaluateRenderStatistics(totalRenderCost,
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);
509
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;
521        Debug << "expected cost: " << mExpectedCost << endl;
522
523
524        ViewCellsManager::PvsStatistics pvsStats;
525        mViewCellsManager->GetPvsStatistics(pvsStats);
526
527        //static float expectedValue = pvsStats.avgPvs;
528       
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
532       
533        // todo: should rather take initial view cells
534    ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
535       
536       
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
549        const int statsOut = 500;
550       
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;
557        int realNumActiveViewCells = mNumActiveViewCells;
558       
559        // maximal ratio of old expected render cost to expected render
560        // when the the render queue has to be reset.
561        int numMergedViewCells = 0;
562               
563
564        cout << "actual merge starts now ... " << endl;
565
566        //-- use priority queue to merge leaf pairs
567
568        while (!mMergeQueue.empty())
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
572                if ((mergedPerPass > mMaxMergesPerPass) ||
573                        (mAvgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
574                {
575                        Debug << "************ reset queue *****************\n"
576                                  << "ratios: " << mAvgCostMaxDeviation
577                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
578                                  << " merged per pass : " << mergedPerPass << " of maximal " << mMaxMergesPerPass << endl;
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;
591                        mNumActiveViewCells = realNumActiveViewCells;
592                       
593                        const int numMergedViewCells = UpdateActiveViewCells(activeViewCells);
594               
595                       
596                        //-- resets / refines the view cells
597                        //-- priorities are recomputed
598                        //-- the candidates are put back into merge queue
599                        if (mRefineViewCells)
600                                RefineViewCells(rays, objects);
601                        else
602                                ResetMergeQueue();
603
604                        Debug << "Values after reset: " 
605                                  << " erc: " << mExpectedCost
606                                  << " avg: " << mAvgRenderCost
607                                  << " dev: " << mDeviation << endl;
608
609                        if (mExportMergedViewCells)
610                        {
611                                ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
612                        }
613                }
614
615
616                MergeCandidate mc = mMergeQueue.top();
617                mMergeQueue.pop();
618       
619                // both view cells equal because of previous merges
620                // NOTE: do I really still need this? probably cannot happen!!
621                if (mc.mLeftViewCell == mc.mRightViewCell)
622                        continue;
623
624                if (mc.IsValid())
625                {
626                        ViewCell::NewMail();
627
628                        //-- update statistical values
629                        -- realNumActiveViewCells;
630                        ++ mergeStats.merged;
631                        ++ mergedPerPass;
632
633                        const float renderCostIncr = mc.GetRenderCost();
634                        const float mergeCostIncr = mc.GetMergeCost();
635
636                        totalRenderCost += renderCostIncr;
637                        mDeviation += mc.GetDeviationIncr();
638
639                                               
640                        //-- merge the view cells of leaf1 and leaf2
641                        int pvsDiff;
642                        ViewCellInterior *mergedVc =
643                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
644                       
645
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
650                        totalPvs += pvsDiff;
651                        realExpectedCost = totalRenderCost / (float)realNumActiveViewCells;
652                        realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
653       
654                        // set merge cost to this node for priority traversal
655                        mergedVc->SetMergeCost(totalRenderCost);
656                       
657                        // HACK
658                        //mergedVc->SetMergeCost(1.0f / (float)realNumActiveViewCells);
659
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
664                        mergedVc->SetCost(realExpectedCost);
665
666                        if ((mergeStats.merged % statsOut) == 0)
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
674                        if (ValidateMergeCandidate(mc))
675                        {
676                                EvalMergeCost(mc);
677                                mMergeQueue.push(mc);
678                        }
679                }
680               
681        }
682
683        // adjust stats and reset queue one final time
684        mExpectedCost = realExpectedCost;
685        mAvgRenderCost = realAvgRenderCost;
686        mNumActiveViewCells = realNumActiveViewCells;
687
688        UpdateActiveViewCells(activeViewCells);
689
690        // refine view cells and reset costs
691        if (mRefineViewCells)
692                RefineViewCells(rays, objects);
693        else
694                ResetMergeQueue();
695
696
697        // create a root node if the merge was not done till root level,
698        // else take the single node as new root
699        if ((int)activeViewCells.size() > 1)
700        {
701                Debug << "creating root of view cell hierarchy for "
702                          << (int)activeViewCells.size() << " view cells" << endl;
703               
704                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
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       
711                root->SetMergeCost(totalRenderCost);
712                // $$JB keep this 0 temporarilly
713                root->SetCost(0.0f);
714
715                mRoot = root;
716        }
717        // normal case
718        else if (!activeViewCells.empty())
719        {
720                Debug << "setting root of the merge history" << endl;
721                mRoot = activeViewCells[0];
722        }
723        else
724        {
725                Debug << "big error, root is NULL" << endl;
726        }
727       
728        //-- empty merge queue just in case
729        while (!mMergeQueue.empty())
730        {
731                mMergeQueue.pop();
732        }
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
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
753        // assign colors for the view cells so that at least one is always consistent
754        AssignRandomColors();
755
756        //TODO: should return sample contributions?
757        return mergeStats.merged;
758}
759
760
761ViewCell *ViewCellsTree::GetRoot() const
762{
763        return mRoot;
764}
765
766
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
782                if (ValidateMergeCandidate(mc))
783                {
784                        EvalMergeCost(mc);
785                        buf.push_back(mc);                             
786                }
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
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
839int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
840{
841        int numMergedViewCells = 0;
842
843        Debug << "updating active vc: " << (int)viewCells.size() << endl;
844       
845        // find all already merged view cells and remove them from the
846        // container view cells
847               
848        // sort out all view cells which are not active anymore, i.e., they
849        // were already part of a merge
850        int i = 0;
851
852        ViewCell::NewMail();
853
854        while (1)
855        {
856                // remove all merged view cells from end of the vector
857                while (!viewCells.empty() && (viewCells.back()->GetParent()))
858                {
859                        viewCells.pop_back();
860                }
861
862                // all merged view cells have been found
863                if (i >= (int)viewCells.size())
864                        break;
865
866                // already merged this view cell, put it to end of vector
867                if (viewCells[i]->GetParent())
868                        swap(viewCells[i], viewCells.back());
869               
870                // mail view cell that it has not been merged
871                viewCells[i]->Mail();
872
873                // increase loop counter
874                ++ i;
875        }
876
877
878        // add new view cells to container only if they don't have been
879        // merged in the mean time
880        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
881
882        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
883        {
884                ViewCell *vc = mMergedViewCells.back();
885                if (!vc->GetParent() && !vc->Mailed())
886                {
887                        vc->Mail();
888                        viewCells.push_back(vc);
889                        ++ numMergedViewCells;
890                }
891        }
892
893        // dispose old merged view cells
894        mMergedViewCells.clear();
895
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        {
903                const int lower = mViewCellsManager->GetMinPvsSize();
904                const int upper = mViewCellsManager->GetMaxPvsSize();
905
906                const float penalty = EvalPvsPenalty((*vit)->GetPvs().CountObjectsInPvs(), lower, upper);
907               
908                mDeviation += fabs(mAvgRenderCost - penalty);
909        }
910
911        mDeviation /= (float)viewCells.size();
912       
913        return numMergedViewCells;
914}
915
916
917void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
918                                                                                  const ObjectContainer &objects,
919                                                                                  const int numMergedViewCells)
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
941                        if (i ++ >= (viewCells.size() - numMergedViewCells))
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
966ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *left,
967                                                                                                ViewCell *right,
968                                                                                                int &pvsDiff) //const
969{
970        // create merged view cell
971        ViewCellInterior *vc =
972                mViewCellsManager->MergeViewCells(left, right);
973
974        // if merge was unsuccessful
975        if (!vc) return NULL;
976
977        // set to the new parent view cell
978        left->SetParent(vc);
979        right->SetParent(vc);
980
981       
982        if (mUseAreaForPvs)
983        {
984                // set new area of view cell
985                // not not correct, but costly to compute real area!!
986                vc->SetArea(left->GetArea() + right->GetArea());
987        }
988        else
989        {       // set new volume of view cell
990                vc->SetVolume(left->GetVolume() + right->GetVolume());
991        }
992
993       
994        // important so other merge candidates sharing this view cell
995        // are notified that the merge cost must be updated!!
996        vc->Mail();
997
998        const int pvs1 = left->GetPvs().CountObjectsInPvs();
999        const int pvs2 = right->GetPvs().CountObjectsInPvs();
1000
1001
1002        // the new view cells are stored in this container
1003        mMergedViewCells.push_back(vc);
1004
1005        pvsDiff = vc->GetPvs().CountObjectsInPvs() - pvs1 - pvs2;
1006
1007
1008        // don't store pvs in interior cells, just a scalar
1009        if (mViewCellsStorage == PVS_IN_LEAVES)
1010        {
1011                // set scalars
1012                mViewCellsManager->UpdateScalarPvsSize(left,
1013                        left->GetPvs().CountObjectsInPvs(),
1014                        left->GetPvs().GetSize());
1015                       
1016                // remove pvs, we don't store interior pvss
1017                if (!left->IsLeaf())
1018                {
1019                        left->GetPvs().Clear();
1020                }
1021
1022                // set scalars
1023                mViewCellsManager->UpdateScalarPvsSize(right,
1024                        right->GetPvs().CountObjectsInPvs(),
1025                        right->GetPvs().GetSize());
1026
1027                right->mPvsSizeValid = true;
1028               
1029                // remove pvs, we don't store interior pvss
1030                if (!right->IsLeaf())
1031                {
1032                        right->GetPvs().Clear();
1033                }
1034        }
1035
1036        return vc;
1037}
1038
1039
1040int ViewCellsTree::RefineViewCells(const VssRayContainer &rays,
1041                                                                   const ObjectContainer &objects)
1042{
1043        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
1044
1045        // intermediate buffer for shuffled view cells
1046        vector<MergeCandidate> buf;
1047        buf.reserve(mMergeQueue.size());
1048                       
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       
1057        const int numPasses = 3;
1058        int pass = 0;
1059        int passShuffled = 0;
1060        int shuffled = 0;
1061        int shuffledViewCells = 0;
1062
1063        ViewCell::NewMail();
1064       
1065        while (!mMergeQueue.empty())
1066        {
1067                MergeCandidate mc = mMergeQueue.top();
1068                mMergeQueue.pop();
1069
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                }
1076
1077                // candidate for shuffling
1078                const bool wasShuffled = ShuffleLeaves(mc);
1079               
1080                // shuffled or put into other queue for further refine
1081                if (wasShuffled)
1082                {
1083                        ++ passShuffled;
1084
1085                        if (!mc.GetLeftViewCell()->Mailed())
1086                        {
1087                                mc.GetLeftViewCell()->Mail();
1088                                ++ shuffledViewCells;
1089                        }
1090                        if (!mc.GetRightViewCell()->Mailed())
1091                        {
1092                                mc.GetRightViewCell()->Mail();
1093                                ++ shuffledViewCells;
1094                        }
1095                }
1096
1097                // put back into intermediate vector
1098                buf.push_back(mc);
1099        }
1100
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                }
1119        }
1120
1121        cout << "finished" << endl;
1122
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,
1155                                                                         ViewCellInterior *vc1,
1156                                                                         ViewCellInterior *vc2) const
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) +
1208                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
1209}
1210
1211
1212void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
1213                                                                ViewCellInterior *vc1,
1214                                                                ViewCellInterior *vc2) const
1215{
1216        // compute new pvs and area
1217        // TODO change
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
1232       
1233        ViewCellInterior *p = dynamic_cast<ViewCellInterior *>(leaf->GetParent());
1234
1235        p->RemoveChildLink(leaf);
1236        vc2->SetupChildLink(leaf);
1237}
1238
1239
1240bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
1241{
1242        float cost1, cost2;
1243
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
1250        //-- first test if shuffling would decrease cost
1251        cost1 = GetCostHeuristics(vc1);
1252        cost2 = GetCostHeuristics(vc2);
1253
1254        const float oldCost = cost1 + cost2;
1255       
1256        float shuffledCost1 = Limits::Infinity;
1257        float shuffledCost2 = Limits::Infinity;
1258
1259        if (leaf1)
1260                shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);       
1261        if (leaf2)
1262                shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
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        {
1270                if (leaf1)
1271                        ShuffleLeaf(leaf1, vc1, vc2);
1272                mc.mInitialLeftViewCell = NULL;
1273        }
1274        else
1275        {
1276                if (leaf2)
1277                        ShuffleLeaf(leaf2, vc2, vc1);
1278                mc.mInitialRightViewCell = NULL;
1279        }
1280
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        {
1292                const float penalty =
1293                        EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1294
1295                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) /
1296                        (float)mNumActiveViewCells;
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        {
1311                const float penalty = EvalPvsPenalty(vc->GetPvs().CountObjectsInPvs(), lower, upper);
1312                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
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)
1323        {
1324                return vc->GetPvs().CountObjectsInPvs() * vc->GetArea();
1325        }
1326
1327        return vc->GetPvs().CountObjectsInPvs() * vc->GetVolume();
1328}
1329
1330
1331float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1332{
1333        return GetRenderCost(vc) * mRenderCostWeight +
1334                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1335}
1336
1337
1338bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
1339{
1340        // propagate up so we have only the active view cells
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
1351        // this view cell was already merged
1352        //return mc.mLeftViewCell && (mc.mLeftViewCell != mc.mRightViewCell);
1353        return mc.mLeftViewCell != mc.mRightViewCell;
1354}
1355
1356
1357void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1358{
1359        //-- compute pvs difference
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());
1365
1366        const float newPenalty = EvalPvsPenalty(newPvs,
1367                                                                                        mViewCellsManager->GetMinPvsSize(),
1368                                                                                        mViewCellsManager->GetMaxPvsSize());
1369
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)
1399                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
1400        else
1401                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
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
1412
1413void ViewCellsTree::SetViewCellsStorage(int stype)
1414{
1415        if (mViewCellsStorage == stype)
1416                return;
1417
1418        // TODO
1419        switch (stype)
1420        {
1421        case COMPRESSED:
1422                CompressViewCellsPvs(mRoot);
1423                break;
1424        default:
1425                break;
1426        }
1427
1428        mViewCellsStorage = stype;
1429}
1430
1431
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();
1439               
1440                // compress child sets first
1441                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1442                {
1443                        CompressViewCellsPvs(*it);
1444                }
1445
1446                // compress root node
1447                PullUpVisibility(interior);
1448        }
1449}
1450
1451
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
1482void ViewCellsTree::ExportStats(const string &mergeStats)
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
1492        const int rootPvs = GetPvsSize(mRoot);
1493        const int rootEntries = GetPvsEntries(mRoot);
1494
1495        Debug << "******** Export stats **********" << endl;
1496        /*Debug << "vsb volume: " << vol << endl;
1497        Debug << "root volume: " << mRoot->GetVolume() << endl;
1498        Debug << "root pvs: " << rootPvs << endl;
1499        */
1500
1501        float totalRenderCost, avgRenderCost, expectedCost;
1502
1503        float deviation = 0;
1504        int totalPvs = rootPvs;
1505        int entriesInPvs = rootEntries;
1506
1507        totalRenderCost = avgRenderCost = expectedCost = (float)rootPvs;
1508
1509        ofstream stats;
1510        stats.open(mergeStats.c_str());
1511
1512        //-- first view cell
1513        UpdateStats(stats,
1514                                0, numViewCells, 0, totalRenderCost,
1515                                rootPvs, expectedCost, avgRenderCost, deviation,
1516                                totalPvs, entriesInPvs, 0, mRoot->GetVolume());
1517               
1518
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.
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);
1532
1533                        const int parentPvs = GetPvsSize(interior);
1534                        const int parentPvsEntries = GetPvsEntries(interior);
1535            const float parentCost = (float)parentPvs * interior->GetVolume();
1536
1537                        float childCost = 0;
1538                        int childPvs = 0;
1539                        int childPvsEntries = 0;
1540
1541                        -- numViewCells;
1542
1543                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1544
1545                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1546                        {
1547                                ViewCell *vc = *it;
1548
1549                                const int pvsSize = GetPvsSize(vc);
1550                                const int pvsEntries = GetPvsEntries(vc);
1551
1552                                childCost += (float) pvsSize * vc->GetVolume();
1553                                childPvs += pvsSize;
1554                                childPvsEntries += pvsEntries;
1555
1556                                tqueue.push(vc);
1557                                ++ numViewCells;
1558                        }
1559
1560
1561                        const float costDecr = (parentCost - childCost) / vol;
1562
1563                        totalRenderCost -= costDecr;
1564                        totalPvs += childPvs - parentPvs;
1565                        entriesInPvs += childPvsEntries - parentPvsEntries;
1566
1567                        expectedCost = totalRenderCost / (float)numViewCells;
1568                        avgRenderCost = (float)totalPvs / (float)numViewCells;
1569
1570                        UpdateStats(stats,
1571                                                0, numViewCells, costDecr, totalRenderCost,
1572                                                parentPvs, expectedCost, avgRenderCost, deviation,
1573                        totalPvs, entriesInPvs, childPvs - parentPvs,
1574                                                vc->GetVolume());
1575
1576                }
1577        }
1578
1579        stats.close();
1580}
1581
1582
1583void ViewCellsTree::SetRoot(ViewCell *root)
1584{
1585        mRoot = root;
1586}
1587
1588
1589void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1590                                                                                   const int numViewCells)
1591{
1592        TraversalQueue tqueue;
1593        tqueue.push(mRoot);
1594       
1595        while (!tqueue.empty())
1596        {
1597                ViewCell *vc = tqueue.top();
1598                tqueue.pop();
1599
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
1602                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size() + 1) >= numViewCells))
1603                {
1604                        viewCells.push_back(vc);
1605                }
1606                else
1607                {       
1608                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1609
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                }
1617        }
1618}
1619       
1620
1621void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
1622{
1623        Intersectable::NewMail((int)interior->mChildren.size());
1624
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
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
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                {
1640                        Intersectable *obj = (*oit).first;
1641                        if ((cit == interior->mChildren.begin()) && !obj->Mailed())
1642                                obj->Mail();
1643                       
1644                        int incm = obj->IncMail();
1645                }
1646        }
1647
1648        interior->GetPvs().Clear();
1649       
1650       
1651        // only the objects which are present in all leaf pvs
1652        // should remain in the parent pvs
1653        // these are the objects which have been mailed in all children
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)
1661                {               
1662                        if ((*oit).first->Mailed((int)interior->mChildren.size()))
1663                        {       
1664                                interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
1665                        }
1666                }
1667        }
1668
1669
1670        // delete all the objects from the leaf sets which were moved to parent pvs
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                {
1677                        if (!(*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity))
1678                        {
1679                                Debug << "should not come here!" << endl;
1680                        }
1681                }
1682        }
1683}
1684
1685
1686// TODO matt: implement this function for different storing methods
1687void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
1688{
1689        // pvs is stored in each cell => just return pvs
1690        if (mViewCellsStorage == PVS_IN_INTERIORS)
1691        {
1692                pvs = vc->GetPvs();
1693                return;
1694        }
1695
1696
1697        //-- pvs is not stored with the interiors => reconstruct
1698        Intersectable::NewMail();
1699
1700        int pvsSize = 0;
1701        ViewCell *root = vc;
1702       
1703        // add pvs from this view cell to root
1704        while (root->GetParent())
1705        {
1706                root = root->GetParent();
1707                pvs.AddPvs(root->GetPvs());
1708        }
1709
1710        // add pvs from leaves
1711        stack<ViewCell *> tstack;
1712        tstack.push(vc);
1713
1714        while (!tstack.empty())
1715        {
1716                vc = tstack.top();
1717                tstack.pop();
1718
1719                // add newly found pvs to merged pvs
1720                pvs.AddPvs(vc->GetPvs());
1721
1722                if (!vc->IsLeaf()) // interior cells: go down to leaf level
1723                {
1724                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1725
1726                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1727
1728                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1729                        {
1730                                tstack.push(*it);
1731                        }               
1732                }
1733        }
1734}
1735
1736
1737int ViewCellsTree::GetPvsSizeForLeafStorage(ViewCell *vc) const
1738{
1739        // pvs is always stored directly in leaves
1740        if (vc->IsLeaf())
1741        {
1742                return vc->GetPvs().CountObjectsInPvs();
1743        }
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)
1752        {
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);
1760
1761        ViewCellContainer::const_iterator it, it_end = leaves.end();
1762
1763        Intersectable::NewMail();
1764        ObjectPvs newPvs;
1765
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)
1772                {
1773                        Intersectable *intersect = (*oit).first;
1774
1775                        if (!intersect->Mailed())
1776                        {
1777                                intersect->Mail();
1778                                newPvs.AddSample(intersect, (*oit).second.mSumPdf);
1779                        }
1780                }
1781        }
1782
1783        return newPvs.CountObjectsInPvs();
1784}
1785
1786
1787int ViewCellsTree::GetEntriesInPvsForLeafStorage(ViewCell *vc) const
1788{
1789        // pvs is always stored directly in leaves
1790        if (vc->IsLeaf())
1791        {
1792                return vc->GetPvs().GetSize();
1793        }
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)
1802        {
1803                return vc->mEntriesInPvs;
1804        }
1805       
1806        int pvsSize = 0;
1807
1808        // if no valid pvs size stored as a scalar =>
1809        // compute current pvs size of interior from it's leaf nodes
1810        ViewCellContainer leaves;
1811        CollectLeaves(vc, leaves);
1812
1813        ViewCellContainer::const_iterator it, it_end = leaves.end();
1814        Intersectable::NewMail();
1815
1816        // sum different intersectables
1817        for (it = leaves.begin(); it != it_end; ++ it)
1818        {
1819                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1820
1821                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1822                {
1823                        Intersectable *intersect = (*oit).first;
1824
1825                        if (!intersect->Mailed())
1826                        {
1827                                intersect->Mail();
1828                                ++ pvsSize;
1829                        }
1830                }
1831        }
1832
1833        return pvsSize;
1834}
1835
1836
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())
1872                {
1873                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1874
1875                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1876
1877                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1878                        {
1879                                tstack.push(*it);
1880                        }               
1881                }
1882        }
1883
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;
1902       
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        }
1910
1911        stack<ViewCell *> tstack;
1912        tstack.push(vc);
1913
1914        while (!tstack.empty())
1915        {
1916                vc = tstack.top();
1917                tstack.pop();
1918       
1919                // count the pvs entries different from the already found ones 
1920                pvsSize += CountDiffPvs(vc);
1921
1922                if (!vc->IsLeaf())
1923                {
1924                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1925
1926                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1927
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);                 
1954                        break;
1955                }
1956        case COMPRESSED:
1957                {
1958                        pvsSize = GetPvsSizeForCompressedStorage(vc);
1959                        break;
1960                }
1961        case PVS_IN_INTERIORS:
1962        default:
1963                // pvs is stored consistently in the tree up to the root
1964                // just return pvs size
1965                pvsSize = vc->GetPvs().CountObjectsInPvs();     
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                {                       
1986                        pvsSize = GetEntriesInPvsForLeafStorage(vc);
1987                        break;
1988                }
1989        case COMPRESSED:
1990                {
1991                        pvsSize = GetEntriesInPvsForCompressedStorage(vc);
1992                        break;
1993                }
1994        case PVS_IN_INTERIORS:
1995        default:
1996                // pvs is stored consistently in the tree up to the root
1997                // just return pvs size
1998                pvsSize = vc->GetPvs().GetSize();       
1999                break;
2000        }
2001
2002        return pvsSize; 
2003}
2004
2005
2006float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
2007{
2008        const float entrySize =
2009                sizeof(PvsData) + sizeof(Intersectable *);
2010
2011        return (float)GetStoredPvsEntriesNum(vc) * entrySize;
2012}
2013
2014
2015int ViewCellsTree::GetStoredPvsEntriesNum(ViewCell *root) const
2016{
2017        int pvsSize = root->GetPvs().GetSize();
2018
2019        // recursivly count leaves
2020        if (!root->IsLeaf())
2021        {
2022                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
2023
2024                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2025
2026                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2027                {
2028                        pvsSize += GetStoredPvsEntriesNum(*it);
2029                }
2030        }
2031
2032        return pvsSize;         
2033}
2034
2035
2036int ViewCellsTree::ViewCellsStorage() const
2037{
2038        return mViewCellsStorage;
2039}
2040
2041
2042ViewCell *ViewCellsTree::GetActiveViewCell(ViewCellLeaf *vc) const
2043{
2044        return vc->GetActiveViewCell();
2045}
2046
2047
2048void ViewCellsTree::PropagatePvs(ViewCell *vc)
2049{       
2050        ViewCell *viewCell = vc;
2051
2052        // propagate pvs up
2053        while (viewCell->GetParent())
2054        {
2055                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
2056                viewCell = viewCell->GetParent();
2057        }
2058
2059        if (vc->IsLeaf())
2060                return;
2061
2062        // propagate pvs to the leaves
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);
2079
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        }
2088}
2089
2090
2091void ViewCellsTree::AssignRandomColors()
2092{
2093        TraversalQueue tqueue;
2094       
2095        tqueue.push(mRoot);
2096       
2097        mRoot->SetColor(RandomColor(0.3f, 1.0f));
2098       
2099        while (!tqueue.empty())
2100        {
2101                ViewCell *vc = tqueue.top();
2102                tqueue.pop();
2103
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)
2129                                {
2130                                        maxViewCell->SetColor(vc->GetColor());
2131                                }
2132                               
2133                                tqueue.push(v);
2134                        }
2135                }       
2136        }
2137}
2138
2139
2140/** Get costs resulting from each merge step.
2141*/
2142void
2143ViewCellsTree::GetCostFunction(vector<float> &costFunction)
2144{
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                }
2165        }
2166}
2167
2168
2169void ViewCellsTree::UpdateViewCellsStats(ViewCell *vc,
2170                                                                                 ViewCellsStatistics &vcStat)
2171{
2172        ++ vcStat.viewCells;
2173               
2174        const int pvsSize = GetPvsSize(vc);
2175
2176        vcStat.pvsSize += pvsSize;
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
2191
2192bool ViewCellsTree::Export(OUT_STREAM &stream, const bool exportPvs)
2193{
2194        // export recursivly all view cells from the root
2195        ExportViewCell(mRoot, stream, exportPvs);
2196
2197        return true;
2198}
2199
2200
2201void ViewCellsTree::CreateUniqueViewCellsIds()
2202{
2203        stack<ViewCell *> tstack;
2204
2205        int currentId = 0;
2206
2207        tstack.push(mRoot);
2208
2209        while (!tstack.empty())
2210        {
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);
2219                       
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                }
2226        }
2227}
2228
2229
2230void ViewCellsTree::ExportPvs(ViewCell *viewCell, OUT_STREAM &stream)
2231{
2232        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
2233
2234        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
2235        {
2236                stream << (*it).first->GetId() << " ";
2237        }
2238}
2239
2240
2241void ViewCellsTree::ExportViewCell(ViewCell *viewCell,
2242                                                                   OUT_STREAM &stream,
2243                                                                   const bool exportPvs)
2244{
2245        if (viewCell->IsLeaf())
2246        {
2247                stream << "<Leaf ";
2248                stream << "id=\"" << viewCell->GetId() << "\" ";
2249                stream << "active=\"" << dynamic_cast<ViewCellLeaf *>(viewCell)->GetActiveViewCell()->GetId() << "\" ";
2250                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2251                stream << "pvs=\"";
2252               
2253                //-- export pvs
2254                if (exportPvs)
2255                {
2256                        ExportPvs(viewCell, stream);
2257                }
2258
2259                stream << "\" />" << endl;
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() << "\" ";
2268                stream << "pvs=\"";
2269
2270                //-- NOTE: do not export pvss for interior view cells because
2271                // they can be completely reconstructed from the leaf pvss
2272                if (0)
2273                        ExportPvs(viewCell, stream);
2274               
2275                stream << "\" >" << endl;
2276
2277                //-- recursivly export child view cells
2278                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2279
2280                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2281                {
2282                        ExportViewCell(*it, stream, exportPvs);
2283                }
2284
2285                stream << "</Interior>" << endl;
2286        }
2287}
2288
2289
2290void ViewCellsTree::ResetPvs()
2291{
2292        stack<ViewCell *> tstack;
2293
2294        tstack.push(mRoot);
2295
2296        while (!tstack.empty())
2297        {
2298                ViewCell *vc = tstack.top();
2299                tstack.pop();
2300
2301                vc->GetPvs().Clear();
2302               
2303                if (!vc->IsLeaf())
2304                {
2305                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2306                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2307
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{
2319        // todo
2320}
2321
2322/**************************************************************************/
2323/*                     MergeCandidate implementation                      */
2324/**************************************************************************/
2325
2326
2327MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2328mRenderCost(0),
2329mDeviationIncr(0),
2330mLeftViewCell(l),
2331mRightViewCell(r),
2332mInitialLeftViewCell(l),
2333mInitialRightViewCell(r)
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{
2377        // if one has a parent, it was already merged
2378        return !(mLeftViewCell->GetParent() || mRightViewCell->GetParent());
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
2401
2402
2403
2404
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";
2444}
2445
2446}
Note: See TracBrowser for help on using the repository browser.