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

Revision 1707, 60.8 KB checked in by mattausch, 18 years ago (diff)

worked on full render cost evaluation
warning: some change sin render cost evaluation for pvs which could have bugs

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