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

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