source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp @ 613

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