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

Revision 1586, 57.6 KB checked in by mattausch, 18 years ago (diff)

resolved bug for object space distribution using triangles
fixed biasing bug for mesh::GetRandomSurfacePoint? method and
GetRandomVisibleSurfacePoint?.

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