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

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