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

Revision 1135, 53.2 KB checked in by mattausch, 18 years ago (diff)

uaing rays for osp

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