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

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