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

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