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

Revision 1551, 57.4 KB checked in by mattausch, 18 years ago (diff)

updated view cells loading. probably no optimal for performance

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