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

Revision 1551, 57.4 KB checked in by mattausch, 18 years ago (diff)

updated view cells loading. probably no optimal for performance

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