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

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