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

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