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

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