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

Revision 2560, 64.2 KB checked in by mattausch, 17 years ago (diff)

added functionality for visualization

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