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

Revision 1311, 57.0 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 nodes: pvs is either stored as a scalar or
1765        // has to be reconstructed from the leaves
1766        // the stored pvs size is the valid pvs size => just return scalar
1767        if (vc->mPvsSizeValid)
[1166]1768        {
[1168]1769                return vc->mPvsSize;
1770        }
1771       
1772        // if no valid pvs size stored as a scalar =>
1773        // compute current pvs size of interior from it's leaf nodes
1774        ViewCellContainer leaves;
1775        CollectLeaves(vc, leaves);
[1121]1776
[1168]1777        ViewCellContainer::const_iterator it, it_end = leaves.end();
[1166]1778
[1168]1779        Intersectable::NewMail();
1780        ObjectPvs newPvs;
[1166]1781
[1168]1782        // sum different intersectables
1783        for (it = leaves.begin(); it != it_end; ++ it)
1784        {
1785                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1786
1787                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
[1166]1788                {
[1168]1789                        Intersectable *intersect = (*oit).first;
1790
1791                        if (!intersect->Mailed())
1792                        {
1793                                intersect->Mail();
1794                                newPvs.AddSample(intersect, (*oit).second.mSumPdf);
1795                        }
[1166]1796                }
1797        }
1798
[1168]1799        return newPvs.CountObjectsInPvs();
[1166]1800}
1801
1802
1803int ViewCellsTree::GetEntriesInPvsForLeafStorage(ViewCell *vc) const
1804{
1805        // pvs is always stored directly in leaves
1806        if (vc->IsLeaf())
[752]1807        {
[1168]1808                return vc->GetPvs().GetSize();
[1166]1809        }
[1168]1810       
1811        // interior node
1812
1813        // interior nodes: pvs is either stored as a scalar or
1814        // has to be reconstructed from the leaves
1815
1816        // the stored pvs size is the valid pvs size => just return scalar
1817        if (vc->mPvsSizeValid)
[1166]1818        {
[1168]1819                return vc->mEntriesInPvs;
1820        }
1821       
1822        int pvsSize = 0;
[1161]1823
[1168]1824        // if no valid pvs size stored as a scalar =>
1825        // compute current pvs size of interior from it's leaf nodes
1826        ViewCellContainer leaves;
1827        CollectLeaves(vc, leaves);
[1161]1828
[1168]1829        ViewCellContainer::const_iterator it, it_end = leaves.end();
1830        Intersectable::NewMail();
[1161]1831
[1168]1832        // sum different intersectables
1833        for (it = leaves.begin(); it != it_end; ++ it)
1834        {
1835                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
[1161]1836
[1168]1837                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
[1166]1838                {
[1168]1839                        Intersectable *intersect = (*oit).first;
1840
1841                        if (!intersect->Mailed())
1842                        {
1843                                intersect->Mail();
1844                                ++ pvsSize;
1845                        }
[1166]1846                }
1847        }
[1161]1848
[1166]1849        return pvsSize;
1850}
[1161]1851
1852
[1166]1853int ViewCellsTree::GetPvsSizeForCompressedStorage(ViewCell *vc) const
1854{
1855        int pvsSize = 0;
1856
1857        //-- compressed pvs
1858
1859        // the stored pvs size is the valid pvs size => just return scalar
1860        if (vc->mPvsSizeValid)
1861        {
1862                pvsSize = vc->mPvsSize;
1863        }
1864
1865        // if no pvs size stored, compute new one
1866        ViewCell *root = vc;
1867       
1868        // also add pvs from this view cell to root
1869        while (root->GetParent())
1870        {
1871                root = root->GetParent();
1872       
1873                // matt: bug! must evaluate kd pvss also
1874                pvsSize += CountDiffPvs(root);
1875        }
1876
1877        stack<ViewCell *> tstack;
1878        tstack.push(vc);
1879
1880        while (!tstack.empty())
1881        {
1882                vc = tstack.top();
1883                tstack.pop();
1884                // matt: bug! must evaluate kd pvss also
1885                pvsSize += CountDiffPvs(vc);
1886
1887                if (!vc->IsLeaf())
[1161]1888                {
[1166]1889                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]1890
[1166]1891                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1892
1893                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[752]1894                        {
[1166]1895                                tstack.push(*it);
1896                        }               
1897                }
1898        }
[1161]1899
[1166]1900        return pvsSize;
1901}
1902
1903
1904int ViewCellsTree::GetEntriesInPvsForCompressedStorage(ViewCell *vc) const
1905{
1906        int pvsSize = 0;
1907
1908        //-- compressed pvs
1909
1910        // the stored pvs size is the valid pvs size => just return scalar
1911        if (vc->mPvsSizeValid)
1912        {
1913                pvsSize = vc->mEntriesInPvs;
1914        }
1915
1916        // if no pvs size stored, compute new one
1917        ViewCell *root = vc;
[752]1918       
[1166]1919        // also add pvs from this view cell to root
1920        while (root->GetParent())
1921        {
1922                root = root->GetParent();
1923                // count the pvs entries different from the already found ones 
1924                pvsSize += CountDiffPvs(root);
1925        }
[585]1926
[1166]1927        stack<ViewCell *> tstack;
1928        tstack.push(vc);
[719]1929
[1166]1930        while (!tstack.empty())
1931        {
1932                vc = tstack.top();
1933                tstack.pop();
[1161]1934       
[1166]1935                // count the pvs entries different from the already found ones 
1936                pvsSize += CountDiffPvs(vc);
[752]1937
[1166]1938                if (!vc->IsLeaf())
1939                {
1940                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]1941
[1166]1942                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1161]1943
[1166]1944                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1945                        {
1946                                tstack.push(*it);
1947                        }               
1948                }
1949        }
1950
1951        return pvsSize;
1952}
1953
1954
1955int ViewCellsTree::GetPvsSize(ViewCell *vc) const
1956{
1957        int pvsSize = 0;
1958        Intersectable::NewMail();
1959
1960        ////////////////////////////////////////////////
[1311]1961        // for interiors, pvs can be stored using different methods
[1166]1962        //
1963
1964        switch (mViewCellsStorage)
1965        {
1966        case PVS_IN_LEAVES: //-- store pvs only in leaves
[1311]1967                pvsSize = GetPvsSizeForLeafStorage(vc);                 
1968                break;
[1166]1969        case COMPRESSED:
[1311]1970                pvsSize = GetPvsSizeForCompressedStorage(vc);
1971                break;
[1161]1972        case PVS_IN_INTERIORS:
1973        default:
1974                // pvs is stored consistently in the tree up to the root
1975                // just return pvs size
[1168]1976                pvsSize = vc->GetPvs().CountObjectsInPvs();     
[1161]1977                break;
1978        }
1979
1980        return pvsSize; 
1981}
1982
1983
1984int ViewCellsTree::GetPvsEntries(ViewCell *vc) const
1985{
1986        int pvsSize = 0;
1987
1988        Intersectable::NewMail();
1989
1990        ////////////////////////////////////////////////
1991        // for interiors, pvs can be stored using different methods
1992       
1993        switch (mViewCellsStorage)
1994        {
1995        case PVS_IN_LEAVES: //-- store pvs only in leaves
1996                {                       
[1166]1997                        pvsSize = GetEntriesInPvsForLeafStorage(vc);
1998                        break;
[752]1999                }
2000        case COMPRESSED:
2001                {
[1166]2002                        pvsSize = GetEntriesInPvsForCompressedStorage(vc);
[752]2003                        break;
2004                }
2005        case PVS_IN_INTERIORS:
[997]2006        default:
[1161]2007                // pvs is stored consistently in the tree up to the root
2008                // just return pvs size
2009                pvsSize = vc->GetPvs().GetSize();       
2010                break;
[752]2011        }
[584]2012
2013        return pvsSize; 
2014}
2015
2016
2017float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
2018{
2019        const float entrySize =
[1189]2020                sizeof(PvsData) + sizeof(Intersectable *);
[584]2021
[1161]2022        return (float)GetStoredPvsEntriesNum(vc) * entrySize;
[584]2023}
2024
2025
[1161]2026int ViewCellsTree::GetStoredPvsEntriesNum(ViewCell *root) const
[584]2027{
[1161]2028        int pvsSize = root->GetPvs().GetSize();
[584]2029
[1161]2030        // recursivly count leaves
2031        if (!root->IsLeaf())
[584]2032        {
[1161]2033                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
[584]2034
2035                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2036
2037                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2038                {
[1161]2039                        pvsSize += GetStoredPvsEntriesNum(*it);
[584]2040                }
2041        }
2042
2043        return pvsSize;         
2044}
2045
2046
[752]2047int ViewCellsTree::ViewCellsStorage() const
[584]2048{
[752]2049        return mViewCellsStorage;
[584]2050}
2051
2052
[881]2053ViewCell *ViewCellsTree::GetActiveViewCell(ViewCellLeaf *vc) const
[590]2054{
[881]2055        return vc->GetActiveViewCell();
[590]2056}
2057
2058
[651]2059void ViewCellsTree::PropagatePvs(ViewCell *vc)
[664]2060{       
2061        ViewCell *viewCell = vc;
2062
[660]2063        // propagate pvs up
[664]2064        while (viewCell->GetParent())
[610]2065        {
[664]2066                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
2067                viewCell = viewCell->GetParent();
[610]2068        }
[651]2069
2070        if (vc->IsLeaf())
2071                return;
2072
[660]2073        // propagate pvs to the leaves
[651]2074        stack<ViewCell *> tstack;
2075        tstack.push(vc);
2076
2077        while (!tstack.empty())
2078        {
2079                ViewCell *viewCell = tstack.top();
2080                tstack.pop();
2081
2082                if (viewCell != vc)
2083                {
2084                        viewCell->GetPvs().Merge(vc->GetPvs());
2085                }
2086
2087                if (!viewCell->IsLeaf())
2088                {
2089                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
[664]2090
[651]2091                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2092
2093                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2094                        {
2095                                tstack.push(*it);
2096                        }
2097                }
2098        }
[610]2099}
[605]2100
[610]2101
[650]2102void ViewCellsTree::AssignRandomColors()
[608]2103{
[675]2104        TraversalQueue tqueue;
2105       
2106        tqueue.push(mRoot);
[708]2107       
[675]2108        mRoot->SetColor(RandomColor(0.3f, 1.0f));
2109       
2110        while (!tqueue.empty())
[608]2111        {
[675]2112                ViewCell *vc = tqueue.top();
2113                tqueue.pop();
[650]2114
[675]2115                // save the view cells if it is a leaf or if enough view cells have already been traversed
2116                // because of the priority queue, this will be the optimal set of v
2117                if (!vc->IsLeaf())
2118                {       
2119                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2120                 
2121                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2122                 
2123                        float maxProbability = -1.0f;
2124                 
2125                        ViewCell *maxViewCell = NULL;
2126                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2127                        {
2128                                ViewCell *v = *it;
2129                         
2130                                // set random color
2131                                v->SetColor(RandomColor(0.3f, 1.0f));
2132                         
2133                                if (v->GetVolume() > maxProbability)
2134                                {
2135                                        maxProbability = v->GetVolume();
2136                                        maxViewCell = v;
2137                                }
2138
2139                                if (maxViewCell)
[708]2140                                {
[675]2141                                        maxViewCell->SetColor(vc->GetColor());
[708]2142                                }
[675]2143                               
2144                                tqueue.push(v);
2145                        }
2146                }       
[608]2147        }
2148}
2149
[675]2150
[1161]2151/** Get costs resulting from each merge step.
2152*/
[608]2153void
2154ViewCellsTree::GetCostFunction(vector<float> &costFunction)
2155{
[1161]2156        TraversalQueue tqueue;
2157        tqueue.push(mRoot);
2158       
2159        while (!tqueue.empty())
2160        {
2161                ViewCell *vc = tqueue.top();
2162                tqueue.pop();
2163                // save the view cells if it is a leaf or if enough view cells have already been traversed
2164                // because of the priority queue, this will be the optimal set of v
2165                if (!vc->IsLeaf()) {   
2166                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2167                        costFunction.push_back(interior->GetMergeCost());
2168
2169                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2170
2171                        for (it = interior->mChildren.begin(); it != it_end; ++ it) {
2172                                tqueue.push(*it);
2173                        }
2174
2175                }
[608]2176        }
2177}
2178
2179
[1161]2180void ViewCellsTree::UpdateViewCellsStats(ViewCell *vc,
2181                                                                                 ViewCellsStatistics &vcStat)
[605]2182{
2183        ++ vcStat.viewCells;
2184               
2185        const int pvsSize = GetPvsSize(vc);
2186
[613]2187        vcStat.pvsSize += pvsSize;
[605]2188
2189        if (pvsSize == 0)
2190                ++ vcStat.emptyPvs;
2191
2192        if (pvsSize > vcStat.maxPvs)
2193                vcStat.maxPvs = pvsSize;
2194
2195        if (pvsSize < vcStat.minPvs)
2196                vcStat.minPvs = pvsSize;
2197
2198        if (!vc->GetValid())
2199                ++ vcStat.invalid;
2200}
2201
[1161]2202
[1201]2203bool ViewCellsTree::Export(OUT_STREAM &stream, const bool exportPvs)
[610]2204{
[840]2205        // export recursivly all view cells from the root
[844]2206        ExportViewCell(mRoot, stream, exportPvs);
[605]2207
[610]2208        return true;
2209}
2210
2211
[651]2212void ViewCellsTree::CreateUniqueViewCellsIds()
[610]2213{
[651]2214        stack<ViewCell *> tstack;
[610]2215
[651]2216        int currentId = 0;
2217
2218        tstack.push(mRoot);
2219
2220        while (!tstack.empty())
[610]2221        {
[651]2222                ViewCell *vc = tstack.top();
2223                tstack.pop();
2224
2225                vc->SetId(currentId ++);
2226
2227                if (!vc->IsLeaf())
2228                {
2229                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
[1161]2230                       
[651]2231                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2232                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2233                        {
2234                                tstack.push(*it);
2235                        }
2236                }
[610]2237        }
[651]2238}
[610]2239
[1201]2240
2241void ViewCellsTree::ExportPvs(ViewCell *viewCell, OUT_STREAM &stream)
[651]2242{
2243        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
2244
[837]2245        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
2246        {
[840]2247                stream << (*it).first->GetId() << " ";
[837]2248        }
2249}
2250
[1201]2251
2252void ViewCellsTree::ExportViewCell(ViewCell *viewCell,
2253                                                                   OUT_STREAM &stream,
2254                                                                   const bool exportPvs)
[837]2255{
[610]2256        if (viewCell->IsLeaf())
2257        {
2258                stream << "<Leaf ";
2259                stream << "id=\"" << viewCell->GetId() << "\" ";
[881]2260                stream << "active=\"" << dynamic_cast<ViewCellLeaf *>(viewCell)->GetActiveViewCell()->GetId() << "\" ";
[610]2261                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2262                stream << "pvs=\"";
[837]2263               
2264                //-- export pvs
[844]2265                if (exportPvs)
[955]2266                {
[840]2267                        ExportPvs(viewCell, stream);
[955]2268                }
2269
[651]2270                stream << "\" />" << endl;
[610]2271        }
2272        else
2273        {
2274                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2275       
2276                stream << "<Interior ";
2277                stream << "id=\"" << viewCell->GetId() << "\" ";
2278                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
[870]2279                stream << "pvs=\"";
2280
[837]2281                //-- NOTE: do not export pvss for interior view cells because
[870]2282                // they can be completely reconstructed from the leaf pvss
[837]2283                if (0)
[840]2284                        ExportPvs(viewCell, stream);
[870]2285               
[651]2286                stream << "\" >" << endl;
2287
[837]2288                //-- recursivly export child view cells
[610]2289                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2290
2291                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2292                {
[844]2293                        ExportViewCell(*it, stream, exportPvs);
[610]2294                }
2295
2296                stream << "</Interior>" << endl;
2297        }
2298}
2299
2300
[660]2301void ViewCellsTree::ResetPvs()
2302{
2303        stack<ViewCell *> tstack;
[610]2304
[660]2305        tstack.push(mRoot);
2306
2307        while (!tstack.empty())
2308        {
2309                ViewCell *vc = tstack.top();
2310                tstack.pop();
2311
[1189]2312                vc->GetPvs().Clear();
[666]2313               
[660]2314                if (!vc->IsLeaf())
2315                {
2316                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2317                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[666]2318
[660]2319                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2320                        {
2321                                tstack.push(*it);
2322                        }
2323                }
2324        }
2325}
2326
2327
2328void ViewCellsTree::SetActiveSetToLeaves()
2329{
[752]2330        // todo
[660]2331}
2332
[580]2333/**************************************************************************/
2334/*                     MergeCandidate implementation                      */
2335/**************************************************************************/
2336
2337
2338MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2339mRenderCost(0),
2340mDeviationIncr(0),
2341mLeftViewCell(l),
[586]2342mRightViewCell(r),
2343mInitialLeftViewCell(l),
2344mInitialRightViewCell(r)
[580]2345{
2346        //EvalMergeCost();
2347}
2348
2349
2350void MergeCandidate::SetRightViewCell(ViewCell *v)
2351{
2352        mRightViewCell = v;
2353}
2354
2355
2356void MergeCandidate::SetLeftViewCell(ViewCell *v)
2357{
2358        mLeftViewCell = v;
2359}
2360
2361
2362ViewCell *MergeCandidate::GetRightViewCell() const
2363{
2364        return mRightViewCell;
2365}
2366
2367
2368ViewCell *MergeCandidate::GetLeftViewCell() const
2369{
2370        return mLeftViewCell;
2371}
2372
2373
2374ViewCell *MergeCandidate::GetInitialRightViewCell() const
2375{
2376        return mInitialRightViewCell;
2377}
2378
2379
2380ViewCell *MergeCandidate::GetInitialLeftViewCell() const
2381{
2382        return mInitialLeftViewCell;
2383}
2384
2385
2386bool MergeCandidate::IsValid() const
2387{
[752]2388        // if one has a parent, it was already merged
[1002]2389        return !(mLeftViewCell->GetParent() || mRightViewCell->GetParent());
[580]2390}
2391
2392
2393float MergeCandidate::GetRenderCost() const
2394{
2395        return mRenderCost;
2396}
2397
2398
2399float MergeCandidate::GetDeviationIncr() const
2400{
2401        return mDeviationIncr;
2402}
2403
2404
2405float MergeCandidate::GetMergeCost() const
2406{
2407        return mRenderCost * sRenderCostWeight +
2408                   mDeviationIncr * (1.0f - sRenderCostWeight);
2409}
2410
2411
[605]2412
[610]2413
2414
2415
[580]2416/************************************************************************/
2417/*                    MergeStatistics implementation                    */
2418/************************************************************************/
2419
2420
2421void MergeStatistics::Print(ostream &app) const
2422{
2423        app << "===== Merge statistics ===============\n";
2424
2425        app << setprecision(4);
2426
2427        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2428
2429        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2430
2431        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2432
2433        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2434
2435        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2436
2437        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2438
2439        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2440
2441        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2442
2443        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2444
2445        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2446
2447        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2448
2449        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2450
2451        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2452       
2453
2454        app << "===== END OF BspTree statistics ==========\n";
[608]2455}
[860]2456
[1199]2457}
Note: See TracBrowser for help on using the repository browser.