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

Revision 1586, 57.6 KB checked in by mattausch, 18 years ago (diff)

resolved bug for object space distribution using triangles
fixed biasing bug for mesh::GetRandomSurfacePoint? method and
GetRandomVisibleSurfacePoint?.

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