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

Revision 1311, 57.0 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 nodes: pvs is either stored as a scalar or
1765        // has to be reconstructed from the leaves
1766        // the stored pvs size is the valid pvs size => just return scalar
1767        if (vc->mPvsSizeValid)
1768        {
1769                return vc->mPvsSize;
1770        }
1771       
1772        // if no valid pvs size stored as a scalar =>
1773        // compute current pvs size of interior from it's leaf nodes
1774        ViewCellContainer leaves;
1775        CollectLeaves(vc, leaves);
1776
1777        ViewCellContainer::const_iterator it, it_end = leaves.end();
1778
1779        Intersectable::NewMail();
1780        ObjectPvs newPvs;
1781
1782        // sum different intersectables
1783        for (it = leaves.begin(); it != it_end; ++ it)
1784        {
1785                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1786
1787                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1788                {
1789                        Intersectable *intersect = (*oit).first;
1790
1791                        if (!intersect->Mailed())
1792                        {
1793                                intersect->Mail();
1794                                newPvs.AddSample(intersect, (*oit).second.mSumPdf);
1795                        }
1796                }
1797        }
1798
1799        return newPvs.CountObjectsInPvs();
1800}
1801
1802
1803int ViewCellsTree::GetEntriesInPvsForLeafStorage(ViewCell *vc) const
1804{
1805        // pvs is always stored directly in leaves
1806        if (vc->IsLeaf())
1807        {
1808                return vc->GetPvs().GetSize();
1809        }
1810       
1811        // interior node
1812
1813        // interior nodes: pvs is either stored as a scalar or
1814        // has to be reconstructed from the leaves
1815
1816        // the stored pvs size is the valid pvs size => just return scalar
1817        if (vc->mPvsSizeValid)
1818        {
1819                return vc->mEntriesInPvs;
1820        }
1821       
1822        int pvsSize = 0;
1823
1824        // if no valid pvs size stored as a scalar =>
1825        // compute current pvs size of interior from it's leaf nodes
1826        ViewCellContainer leaves;
1827        CollectLeaves(vc, leaves);
1828
1829        ViewCellContainer::const_iterator it, it_end = leaves.end();
1830        Intersectable::NewMail();
1831
1832        // sum different intersectables
1833        for (it = leaves.begin(); it != it_end; ++ it)
1834        {
1835                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1836
1837                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1838                {
1839                        Intersectable *intersect = (*oit).first;
1840
1841                        if (!intersect->Mailed())
1842                        {
1843                                intersect->Mail();
1844                                ++ pvsSize;
1845                        }
1846                }
1847        }
1848
1849        return pvsSize;
1850}
1851
1852
1853int ViewCellsTree::GetPvsSizeForCompressedStorage(ViewCell *vc) const
1854{
1855        int pvsSize = 0;
1856
1857        //-- compressed pvs
1858
1859        // the stored pvs size is the valid pvs size => just return scalar
1860        if (vc->mPvsSizeValid)
1861        {
1862                pvsSize = vc->mPvsSize;
1863        }
1864
1865        // if no pvs size stored, compute new one
1866        ViewCell *root = vc;
1867       
1868        // also add pvs from this view cell to root
1869        while (root->GetParent())
1870        {
1871                root = root->GetParent();
1872       
1873                // matt: bug! must evaluate kd pvss also
1874                pvsSize += CountDiffPvs(root);
1875        }
1876
1877        stack<ViewCell *> tstack;
1878        tstack.push(vc);
1879
1880        while (!tstack.empty())
1881        {
1882                vc = tstack.top();
1883                tstack.pop();
1884                // matt: bug! must evaluate kd pvss also
1885                pvsSize += CountDiffPvs(vc);
1886
1887                if (!vc->IsLeaf())
1888                {
1889                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1890
1891                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1892
1893                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1894                        {
1895                                tstack.push(*it);
1896                        }               
1897                }
1898        }
1899
1900        return pvsSize;
1901}
1902
1903
1904int ViewCellsTree::GetEntriesInPvsForCompressedStorage(ViewCell *vc) const
1905{
1906        int pvsSize = 0;
1907
1908        //-- compressed pvs
1909
1910        // the stored pvs size is the valid pvs size => just return scalar
1911        if (vc->mPvsSizeValid)
1912        {
1913                pvsSize = vc->mEntriesInPvs;
1914        }
1915
1916        // if no pvs size stored, compute new one
1917        ViewCell *root = vc;
1918       
1919        // also add pvs from this view cell to root
1920        while (root->GetParent())
1921        {
1922                root = root->GetParent();
1923                // count the pvs entries different from the already found ones 
1924                pvsSize += CountDiffPvs(root);
1925        }
1926
1927        stack<ViewCell *> tstack;
1928        tstack.push(vc);
1929
1930        while (!tstack.empty())
1931        {
1932                vc = tstack.top();
1933                tstack.pop();
1934       
1935                // count the pvs entries different from the already found ones 
1936                pvsSize += CountDiffPvs(vc);
1937
1938                if (!vc->IsLeaf())
1939                {
1940                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1941
1942                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1943
1944                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1945                        {
1946                                tstack.push(*it);
1947                        }               
1948                }
1949        }
1950
1951        return pvsSize;
1952}
1953
1954
1955int ViewCellsTree::GetPvsSize(ViewCell *vc) const
1956{
1957        int pvsSize = 0;
1958        Intersectable::NewMail();
1959
1960        ////////////////////////////////////////////////
1961        // for interiors, pvs can be stored using different methods
1962        //
1963
1964        switch (mViewCellsStorage)
1965        {
1966        case PVS_IN_LEAVES: //-- store pvs only in leaves
1967                pvsSize = GetPvsSizeForLeafStorage(vc);                 
1968                break;
1969        case COMPRESSED:
1970                pvsSize = GetPvsSizeForCompressedStorage(vc);
1971                break;
1972        case PVS_IN_INTERIORS:
1973        default:
1974                // pvs is stored consistently in the tree up to the root
1975                // just return pvs size
1976                pvsSize = vc->GetPvs().CountObjectsInPvs();     
1977                break;
1978        }
1979
1980        return pvsSize; 
1981}
1982
1983
1984int ViewCellsTree::GetPvsEntries(ViewCell *vc) const
1985{
1986        int pvsSize = 0;
1987
1988        Intersectable::NewMail();
1989
1990        ////////////////////////////////////////////////
1991        // for interiors, pvs can be stored using different methods
1992       
1993        switch (mViewCellsStorage)
1994        {
1995        case PVS_IN_LEAVES: //-- store pvs only in leaves
1996                {                       
1997                        pvsSize = GetEntriesInPvsForLeafStorage(vc);
1998                        break;
1999                }
2000        case COMPRESSED:
2001                {
2002                        pvsSize = GetEntriesInPvsForCompressedStorage(vc);
2003                        break;
2004                }
2005        case PVS_IN_INTERIORS:
2006        default:
2007                // pvs is stored consistently in the tree up to the root
2008                // just return pvs size
2009                pvsSize = vc->GetPvs().GetSize();       
2010                break;
2011        }
2012
2013        return pvsSize; 
2014}
2015
2016
2017float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
2018{
2019        const float entrySize =
2020                sizeof(PvsData) + sizeof(Intersectable *);
2021
2022        return (float)GetStoredPvsEntriesNum(vc) * entrySize;
2023}
2024
2025
2026int ViewCellsTree::GetStoredPvsEntriesNum(ViewCell *root) const
2027{
2028        int pvsSize = root->GetPvs().GetSize();
2029
2030        // recursivly count leaves
2031        if (!root->IsLeaf())
2032        {
2033                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
2034
2035                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2036
2037                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2038                {
2039                        pvsSize += GetStoredPvsEntriesNum(*it);
2040                }
2041        }
2042
2043        return pvsSize;         
2044}
2045
2046
2047int ViewCellsTree::ViewCellsStorage() const
2048{
2049        return mViewCellsStorage;
2050}
2051
2052
2053ViewCell *ViewCellsTree::GetActiveViewCell(ViewCellLeaf *vc) const
2054{
2055        return vc->GetActiveViewCell();
2056}
2057
2058
2059void ViewCellsTree::PropagatePvs(ViewCell *vc)
2060{       
2061        ViewCell *viewCell = vc;
2062
2063        // propagate pvs up
2064        while (viewCell->GetParent())
2065        {
2066                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
2067                viewCell = viewCell->GetParent();
2068        }
2069
2070        if (vc->IsLeaf())
2071                return;
2072
2073        // propagate pvs to the leaves
2074        stack<ViewCell *> tstack;
2075        tstack.push(vc);
2076
2077        while (!tstack.empty())
2078        {
2079                ViewCell *viewCell = tstack.top();
2080                tstack.pop();
2081
2082                if (viewCell != vc)
2083                {
2084                        viewCell->GetPvs().Merge(vc->GetPvs());
2085                }
2086
2087                if (!viewCell->IsLeaf())
2088                {
2089                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2090
2091                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2092
2093                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2094                        {
2095                                tstack.push(*it);
2096                        }
2097                }
2098        }
2099}
2100
2101
2102void ViewCellsTree::AssignRandomColors()
2103{
2104        TraversalQueue tqueue;
2105       
2106        tqueue.push(mRoot);
2107       
2108        mRoot->SetColor(RandomColor(0.3f, 1.0f));
2109       
2110        while (!tqueue.empty())
2111        {
2112                ViewCell *vc = tqueue.top();
2113                tqueue.pop();
2114
2115                // save the view cells if it is a leaf or if enough view cells have already been traversed
2116                // because of the priority queue, this will be the optimal set of v
2117                if (!vc->IsLeaf())
2118                {       
2119                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2120                 
2121                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2122                 
2123                        float maxProbability = -1.0f;
2124                 
2125                        ViewCell *maxViewCell = NULL;
2126                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2127                        {
2128                                ViewCell *v = *it;
2129                         
2130                                // set random color
2131                                v->SetColor(RandomColor(0.3f, 1.0f));
2132                         
2133                                if (v->GetVolume() > maxProbability)
2134                                {
2135                                        maxProbability = v->GetVolume();
2136                                        maxViewCell = v;
2137                                }
2138
2139                                if (maxViewCell)
2140                                {
2141                                        maxViewCell->SetColor(vc->GetColor());
2142                                }
2143                               
2144                                tqueue.push(v);
2145                        }
2146                }       
2147        }
2148}
2149
2150
2151/** Get costs resulting from each merge step.
2152*/
2153void
2154ViewCellsTree::GetCostFunction(vector<float> &costFunction)
2155{
2156        TraversalQueue tqueue;
2157        tqueue.push(mRoot);
2158       
2159        while (!tqueue.empty())
2160        {
2161                ViewCell *vc = tqueue.top();
2162                tqueue.pop();
2163                // save the view cells if it is a leaf or if enough view cells have already been traversed
2164                // because of the priority queue, this will be the optimal set of v
2165                if (!vc->IsLeaf()) {   
2166                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2167                        costFunction.push_back(interior->GetMergeCost());
2168
2169                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2170
2171                        for (it = interior->mChildren.begin(); it != it_end; ++ it) {
2172                                tqueue.push(*it);
2173                        }
2174
2175                }
2176        }
2177}
2178
2179
2180void ViewCellsTree::UpdateViewCellsStats(ViewCell *vc,
2181                                                                                 ViewCellsStatistics &vcStat)
2182{
2183        ++ vcStat.viewCells;
2184               
2185        const int pvsSize = GetPvsSize(vc);
2186
2187        vcStat.pvsSize += pvsSize;
2188
2189        if (pvsSize == 0)
2190                ++ vcStat.emptyPvs;
2191
2192        if (pvsSize > vcStat.maxPvs)
2193                vcStat.maxPvs = pvsSize;
2194
2195        if (pvsSize < vcStat.minPvs)
2196                vcStat.minPvs = pvsSize;
2197
2198        if (!vc->GetValid())
2199                ++ vcStat.invalid;
2200}
2201
2202
2203bool ViewCellsTree::Export(OUT_STREAM &stream, const bool exportPvs)
2204{
2205        // export recursivly all view cells from the root
2206        ExportViewCell(mRoot, stream, exportPvs);
2207
2208        return true;
2209}
2210
2211
2212void ViewCellsTree::CreateUniqueViewCellsIds()
2213{
2214        stack<ViewCell *> tstack;
2215
2216        int currentId = 0;
2217
2218        tstack.push(mRoot);
2219
2220        while (!tstack.empty())
2221        {
2222                ViewCell *vc = tstack.top();
2223                tstack.pop();
2224
2225                vc->SetId(currentId ++);
2226
2227                if (!vc->IsLeaf())
2228                {
2229                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2230                       
2231                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2232                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2233                        {
2234                                tstack.push(*it);
2235                        }
2236                }
2237        }
2238}
2239
2240
2241void ViewCellsTree::ExportPvs(ViewCell *viewCell, OUT_STREAM &stream)
2242{
2243        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
2244
2245        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
2246        {
2247                stream << (*it).first->GetId() << " ";
2248        }
2249}
2250
2251
2252void ViewCellsTree::ExportViewCell(ViewCell *viewCell,
2253                                                                   OUT_STREAM &stream,
2254                                                                   const bool exportPvs)
2255{
2256        if (viewCell->IsLeaf())
2257        {
2258                stream << "<Leaf ";
2259                stream << "id=\"" << viewCell->GetId() << "\" ";
2260                stream << "active=\"" << dynamic_cast<ViewCellLeaf *>(viewCell)->GetActiveViewCell()->GetId() << "\" ";
2261                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2262                stream << "pvs=\"";
2263               
2264                //-- export pvs
2265                if (exportPvs)
2266                {
2267                        ExportPvs(viewCell, stream);
2268                }
2269
2270                stream << "\" />" << endl;
2271        }
2272        else
2273        {
2274                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2275       
2276                stream << "<Interior ";
2277                stream << "id=\"" << viewCell->GetId() << "\" ";
2278                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2279                stream << "pvs=\"";
2280
2281                //-- NOTE: do not export pvss for interior view cells because
2282                // they can be completely reconstructed from the leaf pvss
2283                if (0)
2284                        ExportPvs(viewCell, stream);
2285               
2286                stream << "\" >" << endl;
2287
2288                //-- recursivly export child view cells
2289                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2290
2291                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2292                {
2293                        ExportViewCell(*it, stream, exportPvs);
2294                }
2295
2296                stream << "</Interior>" << endl;
2297        }
2298}
2299
2300
2301void ViewCellsTree::ResetPvs()
2302{
2303        stack<ViewCell *> tstack;
2304
2305        tstack.push(mRoot);
2306
2307        while (!tstack.empty())
2308        {
2309                ViewCell *vc = tstack.top();
2310                tstack.pop();
2311
2312                vc->GetPvs().Clear();
2313               
2314                if (!vc->IsLeaf())
2315                {
2316                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2317                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2318
2319                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2320                        {
2321                                tstack.push(*it);
2322                        }
2323                }
2324        }
2325}
2326
2327
2328void ViewCellsTree::SetActiveSetToLeaves()
2329{
2330        // todo
2331}
2332
2333/**************************************************************************/
2334/*                     MergeCandidate implementation                      */
2335/**************************************************************************/
2336
2337
2338MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2339mRenderCost(0),
2340mDeviationIncr(0),
2341mLeftViewCell(l),
2342mRightViewCell(r),
2343mInitialLeftViewCell(l),
2344mInitialRightViewCell(r)
2345{
2346        //EvalMergeCost();
2347}
2348
2349
2350void MergeCandidate::SetRightViewCell(ViewCell *v)
2351{
2352        mRightViewCell = v;
2353}
2354
2355
2356void MergeCandidate::SetLeftViewCell(ViewCell *v)
2357{
2358        mLeftViewCell = v;
2359}
2360
2361
2362ViewCell *MergeCandidate::GetRightViewCell() const
2363{
2364        return mRightViewCell;
2365}
2366
2367
2368ViewCell *MergeCandidate::GetLeftViewCell() const
2369{
2370        return mLeftViewCell;
2371}
2372
2373
2374ViewCell *MergeCandidate::GetInitialRightViewCell() const
2375{
2376        return mInitialRightViewCell;
2377}
2378
2379
2380ViewCell *MergeCandidate::GetInitialLeftViewCell() const
2381{
2382        return mInitialLeftViewCell;
2383}
2384
2385
2386bool MergeCandidate::IsValid() const
2387{
2388        // if one has a parent, it was already merged
2389        return !(mLeftViewCell->GetParent() || mRightViewCell->GetParent());
2390}
2391
2392
2393float MergeCandidate::GetRenderCost() const
2394{
2395        return mRenderCost;
2396}
2397
2398
2399float MergeCandidate::GetDeviationIncr() const
2400{
2401        return mDeviationIncr;
2402}
2403
2404
2405float MergeCandidate::GetMergeCost() const
2406{
2407        return mRenderCost * sRenderCostWeight +
2408                   mDeviationIncr * (1.0f - sRenderCostWeight);
2409}
2410
2411
2412
2413
2414
2415
2416/************************************************************************/
2417/*                    MergeStatistics implementation                    */
2418/************************************************************************/
2419
2420
2421void MergeStatistics::Print(ostream &app) const
2422{
2423        app << "===== Merge statistics ===============\n";
2424
2425        app << setprecision(4);
2426
2427        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2428
2429        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2430
2431        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2432
2433        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2434
2435        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2436
2437        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2438
2439        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2440
2441        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2442
2443        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2444
2445        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2446
2447        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2448
2449        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2450
2451        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2452       
2453
2454        app << "===== END OF BspTree statistics ==========\n";
2455}
2456
2457}
Note: See TracBrowser for help on using the repository browser.