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

Revision 1843, 60.8 KB checked in by mattausch, 18 years ago (diff)

warning! changed pvs output because of paper hack

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