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

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