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

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