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

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