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

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