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

Revision 1287, 57.1 KB checked in by mattausch, 18 years ago (diff)

implemented bv hierarchy

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