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

Revision 719, 47.6 KB checked in by mattausch, 18 years ago (diff)

updating view cell hierarchy before pvs statistics

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 because of previous merges
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        // adjust stats and reset queue one final time
622        mExpectedCost = realExpectedCost;
623        mAvgRenderCost = realAvgRenderCost;
624        mNumActiveViewCells = realNumActiveViewCells;
625
626        UpdateActiveViewCells(activeViewCells);
627
628        // refine view cells and reset costs
629        if (mRefineViewCells)
630                RefineViewCells(rays, objects);
631        else
632                ResetMergeQueue();
633
634
635        // create a root node if the merge was not done till root level,
636        // else take the single node as new root
637        if ((int)activeViewCells.size() > 1)
638        {
639                Debug << "creating root of view cell hierarchy for "
640                          << (int)activeViewCells.size() << " view cells" << endl;
641               
642                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
643       
644                ViewCellContainer::const_iterator it, it_end = root->mChildren.end();
645
646                for (it = root->mChildren.begin(); it != it_end; ++ it)
647                        (*it)->SetParent(root);
648       
649                root->SetMergeCost(totalRenderCost);
650                // $$JB keep this 0 temporarilly
651                root->SetCost(0.0f);
652
653                mRoot = root;
654        }
655        // normal case
656        else if (!activeViewCells.empty())
657        {
658                Debug << "setting root of the merge history" << endl;
659                mRoot = activeViewCells[0];
660                Debug << "rootvc volume: " << mRoot->GetVolume() << endl;
661        }
662       
663        //-- empty merge queue just in case
664        while (!mMergeQueue.empty())
665        {
666                mMergeQueue.pop();
667        }
668
669        // TODO delete because makes no sense here
670        mergeStats.expectedRenderCost = realExpectedCost;
671        mergeStats.deviation = mDeviation;
672
673        // we want to optimize this heuristics
674        mergeStats.heuristics =
675                mDeviation * (1.0f - mRenderCostWeight) +
676                mExpectedCost * mRenderCostWeight;
677
678        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
679        mergeStats.Stop();
680        Debug << mergeStats << endl << endl;
681
682        // assign colors for the view cells so that at least one is always consistent
683        AssignRandomColors();
684
685        //TODO: should return sample contributions?
686        return mergeStats.merged;
687}
688
689
690ViewCell *ViewCellsTree::GetRoot() const
691{
692        return mRoot;
693}
694
695
696void ViewCellsTree::ResetMergeQueue()
697{
698        cout << "reset merge queue ... ";
699       
700        vector<MergeCandidate> buf;
701        buf.reserve(mMergeQueue.size());
702                       
703       
704        // store merge candidates in intermediate buffer
705        while (!mMergeQueue.empty())
706        {
707                MergeCandidate mc = mMergeQueue.top();
708                mMergeQueue.pop();
709               
710                // recalculate cost
711                if (ValidateMergeCandidate(mc))
712                {
713                        EvalMergeCost(mc);
714                        buf.push_back(mc);                             
715                }
716        }
717
718        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
719
720        // reinsert back into queue
721        for (bit = buf.begin(); bit != bit_end; ++ bit)
722        {     
723                mMergeQueue.push(*bit);
724        }
725
726        cout << "finished" << endl;
727}
728
729
730int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
731{
732        int numMergedViewCells = 0;
733
734        Debug << "updating active vc: " << (int)viewCells.size() << endl;
735        // find all already merged view cells and remove them from view cells
736               
737        // sort out all view cells which are not active anymore, i.e., they
738        // were already part of a merge
739        int i = 0;
740
741        ViewCell::NewMail();
742
743        while (1)
744        {
745                // remove all merged view cells from end of the vector
746                while (!viewCells.empty() && (viewCells.back()->GetParent()))
747                {
748                        viewCells.pop_back();
749                }
750
751                // all merged view cells have been found
752                if (i >= (int)viewCells.size())
753                        break;
754
755                // already merged this view cell, put it to end of vector
756                if (viewCells[i]->GetParent())
757                        swap(viewCells[i], viewCells.back());
758               
759                // mail view cell as it has not been merged
760                viewCells[i]->Mail();
761
762                // increase loop counter
763                ++ i;
764        }
765
766
767        // add new view cells to container only if they don't have been
768        // merged in the mean time
769        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
770        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
771        {
772                ViewCell *vc = mMergedViewCells.back();
773                if (!vc->GetParent() && !vc->Mailed())
774                {
775                        vc->Mail();
776                        viewCells.push_back(vc);
777                        ++ numMergedViewCells;
778                }
779        }
780
781        mMergedViewCells.clear();
782
783        // update standard deviation
784        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
785       
786        mDeviation = 0;
787
788        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
789        {
790                int lower = mViewCellsManager->GetMinPvsSize();
791                int upper = mViewCellsManager->GetMaxPvsSize();
792                float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
793               
794                mDeviation += fabs(mAvgRenderCost - penalty);
795        }
796
797        mDeviation /= (float)viewCells.size();
798       
799        return numMergedViewCells;
800}
801
802
803void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
804                                                                                  const ObjectContainer &objects,
805                                                                                  const int numMergedViewCells)
806{
807       
808
809        char s[64];
810
811        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
812        Exporter *exporter = Exporter::GetExporter(s);
813
814        if (exporter)
815        {
816                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
817                exporter->ExportGeometry(objects);
818                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
819                ViewCellContainer::const_iterator it, it_end = viewCells.end();
820
821                int i = 0;
822                for (it = viewCells.begin(); it != it_end; ++ it)
823                {
824                        Material m;
825                        // assign special material to new view cells
826                        // new view cells are on the back of container
827                        if (i ++ >= (viewCells.size() - numMergedViewCells))
828                        {
829                                //m = RandomMaterial();
830                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
831                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
832                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
833                        }
834                        else
835                        {
836                                float col = RandomValue(0.1f, 0.4f);
837                                m.mDiffuseColor.r = col;
838                                m.mDiffuseColor.g = col;
839                                m.mDiffuseColor.b = col;
840                        }
841
842                        exporter->SetForcedMaterial(m);
843                        mViewCellsManager->ExportViewCellGeometry(exporter, *it);
844                }
845                delete exporter;
846                cout << "finished" << endl;
847        }
848}
849
850
851// TODO: should be done in view cells manager
852ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l,
853                                                                                                ViewCell *r,
854                                                                                                int &pvsDiff) //const
855{
856        ViewCellInterior *vc = mViewCellsManager->MergeViewCells(l, r);
857
858        // if merge was unsuccessful
859        if (!vc) return NULL;
860
861        l->SetParent(vc);
862        r->SetParent(vc);
863
864        // set new size of view cell
865        if (mUseAreaForPvs)
866        {
867                vc->SetArea(l->GetArea() + l->GetArea());
868        }
869        else
870        {
871                vc->SetVolume(r->GetVolume() + l->GetVolume());
872        }
873
874       
875        // important so other merge candidates sharing this view cell
876        // are notified that the merge cost must be updated!!
877        vc->Mail();
878
879        const int pvs1 = l->GetPvs().GetSize();
880        const int pvs2 = r->GetPvs().GetSize();
881
882
883        // new view cells are stored in this vector
884        mMergedViewCells.push_back(vc);
885
886        pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
887
888        return vc;
889}
890
891
892
893int ViewCellsTree::RefineViewCells(const VssRayContainer &rays,
894                                                                   const ObjectContainer &objects)
895{
896        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
897
898        // intermediate buffer for shuffled view cells
899        vector<MergeCandidate> buf;
900        buf.reserve(mMergeQueue.size());
901                       
902        // Use priority queue of remaining leaf pairs
903        // The candidates either share the same view cells or
904        // are border leaves which share a boundary.
905        // We test if they can be shuffled, i.e.,
906        // either one leaf is made part of one view cell or the other
907        // leaf is made part of the other view cell. It is tested if the
908        // remaining view cells are "better" than the old ones.
909       
910        const int numPasses = 3;
911        int pass = 0;
912        int passShuffled = 0;
913        int shuffled = 0;
914        int shuffledViewCells = 0;
915
916        ViewCell::NewMail();
917       
918        while (!mMergeQueue.empty())
919        {
920                MergeCandidate mc = mMergeQueue.top();
921                mMergeQueue.pop();
922
923                // both view cells equal or already shuffled
924                if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
925                        mc.GetLeftViewCell()->IsLeaf() || mc.GetRightViewCell()->IsLeaf())
926                {                       
927                        continue;
928                }
929
930                // candidate for shuffling
931                const bool wasShuffled = ShuffleLeaves(mc);
932               
933                // shuffled or put into other queue for further refine
934                if (wasShuffled)
935                {
936                        ++ passShuffled;
937
938                        if (!mc.GetLeftViewCell()->Mailed())
939                        {
940                                mc.GetLeftViewCell()->Mail();
941                                ++ shuffledViewCells;
942                        }
943                        if (!mc.GetRightViewCell()->Mailed())
944                        {
945                                mc.GetRightViewCell()->Mail();
946                                ++ shuffledViewCells;
947                        }
948                }
949
950                // put back into intermediate vector
951                buf.push_back(mc);
952        }
953
954
955        //-- in the end, the candidates must be in the mergequeue again
956        //   with the correct cost
957
958        cout << "reset merge queue ... ";
959       
960       
961        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
962       
963        for (bit = buf.begin(); bit != bit_end; ++ bit)
964        {   
965                MergeCandidate mc = *bit;
966                // recalculate cost
967                if (ValidateMergeCandidate(mc))
968                {
969                        EvalMergeCost(mc);
970                        mMergeQueue.push(mc);   
971                }
972        }
973
974        cout << "finished" << endl;
975
976        return shuffledViewCells;
977}
978
979
980inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
981{
982        return pvs1.AddPvs(pvs2);
983}
984
985
986// recomputes pvs size minus pvs of leaf l
987#if 0
988inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
989{
990        ObjectPvs pvs;
991        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
992        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
993                if (*it != l)
994                        pvs.AddPvs(*(*it)->mPvs);
995        return pvs.GetSize();
996}
997#endif
998
999
1000// computes pvs1 minus pvs2
1001inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1002{
1003        return pvs1.SubtractPvs(pvs2);
1004}
1005
1006
1007float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
1008                                                                         ViewCellInterior *vc1,
1009                                                                         ViewCellInterior *vc2) const
1010{
1011        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
1012        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
1013        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
1014
1015        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
1016        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
1017
1018        const float pvsPenalty1 =
1019                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
1020
1021        const float pvsPenalty2 =
1022                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
1023
1024
1025        // don't shuffle leaves with pvs > max
1026        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
1027        {
1028                return 1e20f;
1029        }
1030
1031        float p1, p2;
1032
1033    if (mUseAreaForPvs)
1034        {
1035                p1 = vc1->GetArea() - leaf->GetArea();
1036                p2 = vc2->GetArea() + leaf->GetArea();
1037        }
1038        else
1039        {
1040                p1 = vc1->GetVolume() - leaf->GetVolume();
1041                p2 = vc2->GetVolume() + leaf->GetVolume();
1042        }
1043
1044        const float renderCost1 = pvsPenalty1 * p1;
1045        const float renderCost2 = pvsPenalty2 * p2;
1046
1047        float dev1, dev2;
1048
1049        if (1)
1050        {
1051                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1052                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1053        }
1054        else
1055        {
1056                dev1 = fabs(mExpectedCost - renderCost1);
1057                dev2 = fabs(mExpectedCost - renderCost2);
1058        }
1059       
1060        return mRenderCostWeight * (renderCost1 + renderCost2) +
1061                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
1062}
1063
1064
1065void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
1066                                                                ViewCellInterior *vc1,
1067                                                                ViewCellInterior *vc2) const
1068{
1069        // compute new pvs and area
1070        // TODO change
1071        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1072        vc2->GetPvs().AddPvs(leaf->GetPvs());
1073       
1074        if (mUseAreaForPvs)
1075        {
1076                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1077                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1078        }
1079        else
1080        {
1081                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1082                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1083        }
1084
1085       
1086        ViewCellInterior *p = dynamic_cast<ViewCellInterior *>(leaf->GetParent());
1087
1088        p->RemoveChildLink(leaf);
1089        vc2->SetupChildLink(leaf);
1090}
1091
1092
1093bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
1094{
1095        float cost1, cost2;
1096
1097        ViewCellInterior *vc1 = dynamic_cast<ViewCellInterior *>(mc.GetLeftViewCell());
1098        ViewCellInterior *vc2 = dynamic_cast<ViewCellInterior *>(mc.GetRightViewCell());
1099
1100        ViewCell *leaf1 = mc.GetInitialLeftViewCell();
1101        ViewCell *leaf2 = mc.GetInitialRightViewCell();
1102
1103        //-- first test if shuffling would decrease cost
1104        cost1 = GetCostHeuristics(vc1);
1105        cost2 = GetCostHeuristics(vc2);
1106
1107        const float oldCost = cost1 + cost2;
1108       
1109        float shuffledCost1 = Limits::Infinity;
1110        float shuffledCost2 = Limits::Infinity;
1111
1112        if (leaf1)
1113                shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);       
1114        if (leaf2)
1115                shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
1116
1117        // if cost of shuffle is less than old cost => shuffle
1118        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1119                return false;
1120       
1121        if (shuffledCost1 < shuffledCost2)
1122        {
1123                if (leaf1)
1124                        ShuffleLeaf(leaf1, vc1, vc2);
1125                mc.mInitialLeftViewCell = NULL;
1126        }
1127        else
1128        {
1129                if (leaf2)
1130                        ShuffleLeaf(leaf2, vc2, vc1);
1131                mc.mInitialRightViewCell = NULL;
1132        }
1133
1134        return true;
1135}
1136
1137
1138float ViewCellsTree::GetVariance(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 (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
1147        }
1148
1149    const float leafCost = GetRenderCost(vc);
1150        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1151}
1152
1153
1154float ViewCellsTree::GetDeviation(ViewCell *vc) const
1155{
1156        const int upper = mViewCellsManager->GetMaxPvsSize();
1157        const int lower = mViewCellsManager->GetMinPvsSize();
1158
1159        if (1)
1160        {
1161                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1162                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
1163        }
1164
1165    const float renderCost = GetRenderCost(vc);
1166        return fabs(mExpectedCost - renderCost);
1167}
1168
1169
1170
1171float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1172{
1173        if (mUseAreaForPvs)
1174                return vc->GetPvs().GetSize() * vc->GetArea();
1175
1176        return vc->GetPvs().GetSize() * vc->GetVolume();
1177}
1178
1179
1180float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1181{
1182        return GetRenderCost(vc) * mRenderCostWeight +
1183                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1184}
1185
1186
1187bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
1188{
1189        while (mc.mLeftViewCell->mParent)
1190        {
1191                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1192        }
1193
1194        while (mc.mRightViewCell->mParent)
1195        {
1196                mc.mRightViewCell = mc.mRightViewCell->mParent;
1197        }
1198
1199        return mc.mLeftViewCell != mc.mRightViewCell;
1200}
1201
1202
1203void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1204{
1205        //-- compute pvs difference
1206        const int newPvs =
1207                ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(),
1208                                                         mc.mRightViewCell->GetPvs());
1209                       
1210        const float newPenalty =
1211                EvalPvsPenalty(newPvs,
1212                                           mViewCellsManager->GetMinPvsSize(),
1213                                           mViewCellsManager->GetMaxPvsSize());
1214
1215        ViewCell *vc1 = mc.mLeftViewCell;
1216        ViewCell *vc2 = mc.mRightViewCell;
1217
1218        //-- compute ratio of old cost
1219        //   (i.e., added size of left and right view cell times pvs size)
1220        //   to new rendering cost (i.e, size of merged view cell times pvs size)
1221        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1222
1223    const float newCost = mUseAreaForPvs ?
1224                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1225                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1226
1227
1228        // strong penalty if pvs size too large
1229        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1230        {
1231                mc.mRenderCost = 1e20f;
1232        }
1233        else
1234        {
1235                mc.mRenderCost = (newCost - oldCost) /
1236                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1237        }       
1238       
1239
1240        //-- merge cost also takes deviation into account
1241        float newDev, oldDev;
1242
1243        if (1)
1244                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
1245        else
1246                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
1247       
1248        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1249
1250        // compute deviation increase
1251        mc.mDeviationIncr = newDev - oldDev;
1252       
1253        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1254        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1255}
1256
1257void ViewCellsTree::CompressViewCellsPvs()
1258{
1259        if (!mIsCompressed)
1260        {
1261                mIsCompressed = true;
1262                CompressViewCellsPvs(mRoot);
1263        }
1264}
1265
1266void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
1267{
1268        if (!root->IsLeaf())
1269        {
1270                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
1271
1272        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1273               
1274                // compress child sets first
1275                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1276                {
1277                        CompressViewCellsPvs(*it);
1278                }
1279
1280                // compress root node
1281                PullUpVisibility(interior);
1282        }
1283}
1284
1285
1286void ViewCellsTree::ExportStats(const string &mergeStats)
1287{
1288        TraversalQueue tqueue;
1289
1290        tqueue.push(mRoot);
1291        int numViewCells = 1;
1292       
1293        const AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1294        const float vol = box.GetVolume();
1295
1296        Debug << "vsb volume: " << vol << endl;
1297        Debug << "root volume: " << mRoot->GetVolume() << endl;
1298        Debug << "root pvs: " << mRoot->GetPvs().GetSize() << endl;
1299
1300        int totalPvs;
1301        float totalRenderCost, avgRenderCost, expectedCost;
1302
1303        float deviation = 0;
1304        totalPvs = (int)mRoot->GetPvs().GetSize();
1305        totalRenderCost = avgRenderCost = expectedCost = (float)mRoot->GetPvs().GetSize();
1306
1307        ofstream stats;
1308        stats.open(mergeStats.c_str());
1309
1310        stats
1311                << "#Pass\n" << 0 << endl
1312                //<< "#Merged\n" << mergeStats.merged << endl
1313                << "#ViewCells\n" << numViewCells << endl
1314        << "#RenderCostDecrease\n" << 0 << endl // TODO
1315                << "#TotalRenderCost\n" << totalRenderCost << endl
1316                << "#CurrentPvs\n" << mRoot->GetPvs().GetSize() << endl
1317                << "#ExpectedCost\n" << expectedCost << endl
1318                << "#AvgRenderCost\n" << avgRenderCost << endl
1319                << "#Deviation\n" << deviation << endl
1320                << "#TotalPvs\n" << totalPvs << endl
1321                << "#PvsSizeDecrease\n" << 0 << endl // TODO
1322                << "#Volume\n" << mRoot->GetVolume() << endl
1323                << endl;
1324
1325
1326        while (!tqueue.empty())
1327        {
1328                ViewCell *vc = tqueue.top();
1329                tqueue.pop();
1330
1331                if (!vc->IsLeaf())
1332                {       
1333                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1334                       
1335                        const int parentPvs = interior->GetPvs().GetSize();
1336                        const float parentCost = (float)parentPvs * interior->GetVolume();
1337                        float childCost = 0;
1338                        int childPvs = 0;
1339
1340                        -- numViewCells;
1341
1342                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1343
1344                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1345                        {
1346                                childCost += (float)(*it)->GetPvs().GetSize() * (*it)->GetVolume();
1347                                childPvs += (*it)->GetPvs().GetSize();
1348
1349                                tqueue.push(*it);
1350                                ++ numViewCells;
1351                        }
1352
1353               
1354                        const float costDecr = (parentCost - childCost) / vol;
1355
1356                        totalRenderCost -= costDecr;
1357                        totalPvs += childPvs - parentPvs;
1358                       
1359                        expectedCost = totalRenderCost / (float)numViewCells;
1360                        avgRenderCost = (float)totalPvs / (float)numViewCells;
1361
1362                        stats
1363                                << "#Pass\n" << 0 << endl
1364                                //<< "#Merged\n" << mergeStats.merged << endl
1365                                << "#ViewCells\n" << numViewCells << endl
1366                                << "#RenderCostDecrease\n" << costDecr << endl // TODO
1367                                << "#TotalRenderCost\n" << totalRenderCost << endl
1368                                << "#CurrentPvs\n" << vc->GetPvs().GetSize() << endl
1369                                << "#ExpectedCost\n" << expectedCost << endl
1370                                << "#AvgRenderCost\n" << avgRenderCost << endl
1371                                << "#Deviation\n" << deviation << endl
1372                                << "#TotalPvs\n" << totalPvs << endl
1373                                << "#PvsSizeDecrease\n" << childPvs - parentPvs << endl // TODO
1374                                << "#Volume\n" << vc->GetVolume() << endl
1375                                << endl;
1376
1377                }
1378        }
1379
1380        stats.close();
1381}
1382
1383
1384#if 0
1385float ViewCellsTree::ComputeVolume(ViewCell *vc)
1386{
1387        if (vc->IsLeaf())
1388        {
1389                return vc->GetVolume();
1390        }
1391        else
1392        {
1393                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1394
1395                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1396
1397                float volume = 0;
1398
1399                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1400                {
1401                        volume += ComputeVolume(*it);   
1402                }
1403
1404                interior->SetVolume(volume);
1405                return volume;
1406        }
1407}
1408#endif
1409
1410void ViewCellsTree::SetRoot(ViewCell *root)
1411{
1412        mRoot = root;
1413}
1414
1415
1416void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1417                                                                                   const int numViewCells)
1418{
1419        TraversalQueue tqueue;
1420        tqueue.push(mRoot);
1421       
1422        while (!tqueue.empty())
1423        {
1424                ViewCell *vc = tqueue.top();
1425                tqueue.pop();
1426
1427                // save the view cells if it is a leaf or if enough view cells have already been traversed
1428                // because of the priority queue, this will be the optimal set of v
1429                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size() + 1) >= numViewCells))
1430                {
1431                        viewCells.push_back(vc);
1432                }
1433                else
1434                {       
1435                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1436
1437                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1438
1439                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1440                        {
1441                                tqueue.push(*it);
1442                        }
1443                }
1444        }
1445}
1446       
1447
1448void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
1449{
1450        Intersectable::NewMail((int)interior->mChildren.size());
1451
1452        ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
1453
1454        ObjectPvsMap::const_iterator oit;
1455
1456        // mail all objects in the leaf sets
1457        // we are interested in the objects which are present in all leaves
1458        // => count how often an object is part of a child set
1459        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1460        {
1461                ViewCell *vc = *cit;
1462
1463                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1464
1465                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1466                {
1467                        Intersectable *obj = (*oit).first;
1468                        if ((cit == interior->mChildren.begin()) && !obj->Mailed())
1469                                obj->Mail();
1470                       
1471                        int incm = obj->IncMail();
1472                }
1473        }
1474
1475        interior->GetPvs().mEntries.clear();
1476       
1477       
1478        // only the objects which are present in all leaf pvs
1479        // should remain in the parent pvs
1480        // these are the objects which have been mailed in all children
1481        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1482        {
1483                ViewCell *vc = *cit;
1484
1485                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1486
1487                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1488                {               
1489                        if ((*oit).first->Mailed((int)interior->mChildren.size()))
1490                        {       
1491                                interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
1492                        }
1493                }
1494        }
1495
1496
1497
1498        // delete all the objects from the leaf sets which were moved to parent pvs
1499        ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
1500
1501        for (oit = interior->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1502        {
1503                for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1504                {
1505                        if (!(*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity))
1506                                Debug << "should not come here!" << endl;
1507                }
1508        }
1509
1510        int dummy = interior->GetPvs().GetSize();
1511
1512        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1513        {
1514                dummy += (*cit)->GetPvs().GetSize();
1515        }
1516
1517}
1518
1519
1520void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
1521{
1522        Intersectable::NewMail();
1523
1524        if (!mIsCompressed)
1525                pvs = vc->GetPvs();
1526
1527        int pvsSize = 0;
1528        ViewCell *root = vc;
1529       
1530        // also add pvs from this view cell to root
1531        while (root->GetParent())
1532        {
1533                root = root->GetParent();
1534                pvs.AddPvs(root->GetPvs());
1535        }
1536
1537        stack<ViewCell *> tstack;
1538        tstack.push(vc);
1539
1540        while (!tstack.empty())
1541        {
1542                vc = tstack.top();
1543                tstack.pop();
1544
1545                pvs.AddPvs(vc->GetPvs());
1546
1547                if (!vc->IsLeaf())
1548                {
1549                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1550
1551                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1552
1553                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1554                        {
1555                                tstack.push(*it);
1556                        }               
1557                }
1558        }
1559}
1560
1561
1562int ViewCellsTree::GetPvsSize(ViewCell *vc) const
1563{
1564        Intersectable::NewMail();
1565
1566        if (!mIsCompressed)
1567                return vc->GetPvs().GetSize();
1568
1569
1570        ////////////////////////777
1571        //-- compressed pvs
1572
1573        int pvsSize = 0;
1574        ViewCell *root = vc;
1575       
1576        // also add pvs from this view cell to root
1577        while (root->GetParent())
1578        {
1579                root = root->GetParent();
1580                pvsSize += CountDiffPvs(root);
1581        }
1582
1583        stack<ViewCell *> tstack;
1584        tstack.push(vc);
1585
1586        while (!tstack.empty())
1587        {
1588                vc = tstack.top();
1589                tstack.pop();
1590
1591                pvsSize += CountDiffPvs(vc);
1592
1593                if (!vc->IsLeaf())
1594                {
1595                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1596
1597                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1598
1599                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1600                        {
1601                                tstack.push(*it);
1602                        }               
1603                }
1604        }
1605
1606        return pvsSize; 
1607
1608}
1609
1610
1611float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
1612{
1613        const float entrySize =
1614                sizeof(PvsData<Intersectable *>) + sizeof(Intersectable *);
1615
1616        return (float)GetNumPvsEntries(vc) * entrySize;
1617}
1618
1619
1620int ViewCellsTree::GetNumPvsEntries(ViewCell *vc) const
1621{
1622        int pvsSize = 0;
1623        // only count leaves for uncompressed method for fairness
1624        if (mIsCompressed || vc->IsLeaf())
1625                pvsSize = vc->GetPvs().GetSize();
1626
1627        if (!vc->IsLeaf())
1628        {
1629                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1630
1631                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1632
1633                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1634                {
1635                        pvsSize += GetNumPvsEntries(*it);
1636                }
1637        }
1638
1639        return pvsSize;         
1640}
1641
1642
1643bool ViewCellsTree::IsCompressed() const
1644{
1645        return mIsCompressed;
1646}
1647
1648
1649ViewCell *ViewCellsTree::GetActiveViewCell(ViewCell *vc) const
1650{
1651        while (vc->GetParent() && !vc->IsActive())
1652        {
1653                vc = vc->GetParent();
1654        }
1655
1656        return vc;
1657}
1658
1659
1660void ViewCellsTree::PropagatePvs(ViewCell *vc)
1661{       
1662        ViewCell *viewCell = vc;
1663
1664        // propagate pvs up
1665        while (viewCell->GetParent())
1666        {
1667                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
1668                viewCell = viewCell->GetParent();
1669        }
1670
1671        if (vc->IsLeaf())
1672                return;
1673
1674        // propagate pvs to the leaves
1675        stack<ViewCell *> tstack;
1676        tstack.push(vc);
1677
1678        while (!tstack.empty())
1679        {
1680                ViewCell *viewCell = tstack.top();
1681                tstack.pop();
1682
1683                if (viewCell != vc)
1684                {
1685                        viewCell->GetPvs().Merge(vc->GetPvs());
1686                }
1687
1688                if (!viewCell->IsLeaf())
1689                {
1690                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
1691
1692                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1693
1694                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1695                        {
1696                                tstack.push(*it);
1697                        }
1698                }
1699        }
1700}
1701
1702
1703void ViewCellsTree::AssignRandomColors()
1704{
1705        TraversalQueue tqueue;
1706       
1707        tqueue.push(mRoot);
1708       
1709        mRoot->SetColor(RandomColor(0.3f, 1.0f));
1710       
1711        while (!tqueue.empty())
1712        {
1713                ViewCell *vc = tqueue.top();
1714                tqueue.pop();
1715
1716                // save the view cells if it is a leaf or if enough view cells have already been traversed
1717                // because of the priority queue, this will be the optimal set of v
1718                if (!vc->IsLeaf())
1719                {       
1720                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1721                 
1722                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1723                 
1724                        float maxProbability = -1.0f;
1725                 
1726                        ViewCell *maxViewCell = NULL;
1727                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1728                        {
1729                                ViewCell *v = *it;
1730                         
1731                                // set random color
1732                                v->SetColor(RandomColor(0.3f, 1.0f));
1733                         
1734                                if (v->GetVolume() > maxProbability)
1735                                {
1736                                        maxProbability = v->GetVolume();
1737                                        maxViewCell = v;
1738                                }
1739
1740                                if (maxViewCell)
1741                                {
1742                                        maxViewCell->SetColor(vc->GetColor());
1743                                }
1744                               
1745                                tqueue.push(v);
1746                        }
1747                }       
1748        }
1749}
1750
1751
1752/** Get costs resulting from each merge step. */
1753void
1754ViewCellsTree::GetCostFunction(vector<float> &costFunction)
1755{
1756  TraversalQueue tqueue;
1757  tqueue.push(mRoot);
1758  while (!tqueue.empty()) {
1759        ViewCell *vc = tqueue.top();
1760        tqueue.pop();
1761        // save the view cells if it is a leaf or if enough view cells have already been traversed
1762        // because of the priority queue, this will be the optimal set of v
1763        if (!vc->IsLeaf()) {   
1764          ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1765          costFunction.push_back(interior->GetCost());
1766         
1767          ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1768         
1769          for (it = interior->mChildren.begin(); it != it_end; ++ it) {
1770                tqueue.push(*it);
1771          }
1772         
1773        }
1774  }
1775}
1776
1777
1778void  ViewCellsTree::UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat)
1779{
1780        ++ vcStat.viewCells;
1781               
1782        const int pvsSize = GetPvsSize(vc);
1783
1784        vcStat.pvsSize += pvsSize;
1785
1786        if (pvsSize == 0)
1787                ++ vcStat.emptyPvs;
1788
1789        if (pvsSize > vcStat.maxPvs)
1790                vcStat.maxPvs = pvsSize;
1791
1792        if (pvsSize < vcStat.minPvs)
1793                vcStat.minPvs = pvsSize;
1794
1795        if (!vc->GetValid())
1796                ++ vcStat.invalid;
1797
1798        /*ViewCellsContainer leaves;
1799        CollectLeaves(vc, leaves);
1800
1801        vcStat.leaves = (int)leaves.size();*/
1802}
1803
1804
1805bool ViewCellsTree::Export(ofstream &stream)
1806{
1807        ExportViewCell(mRoot, stream);
1808
1809        return true;
1810}
1811
1812
1813void ViewCellsTree::CreateUniqueViewCellsIds()
1814{
1815        stack<ViewCell *> tstack;
1816
1817        int currentId = 0;
1818
1819        tstack.push(mRoot);
1820
1821        while (!tstack.empty())
1822        {
1823                ViewCell *vc = tstack.top();
1824                tstack.pop();
1825
1826                vc->SetId(currentId ++);
1827
1828                if (!vc->IsLeaf())
1829                {
1830                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1831                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1832                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1833                        {
1834                                tstack.push(*it);
1835                        }
1836                }
1837        }
1838}
1839
1840
1841void ViewCellsTree::ExportViewCell(ViewCell *viewCell, ofstream &stream)
1842{
1843        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
1844
1845        if (viewCell->IsLeaf())
1846        {
1847                stream << "<Leaf ";
1848                stream << "id=\"" << viewCell->GetId() << "\" ";
1849                stream << "active=\"" << viewCell->IsActive() << "\" ";
1850                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
1851                stream << "pvs=\"";
1852                if (0)// test with empty pvs
1853                        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
1854                        {
1855                                stream << (*it).first->GetId() << " ";
1856                        }
1857
1858       
1859                stream << "\" />" << endl;
1860                //stream << " </Leaf>" << endl;
1861        }
1862        else
1863        {
1864                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
1865       
1866                stream << "<Interior ";
1867                stream << "id=\"" << viewCell->GetId() << "\" ";
1868                stream << "active=\"" << viewCell->IsActive() << "\" ";
1869                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
1870                stream << "pvs=\"";
1871
1872                if (0)// test with empty pvs
1873                        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
1874                        {
1875                                stream << (*it).first->GetId() << " ";
1876                        }
1877
1878                stream << "\" >" << endl;
1879
1880                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1881
1882                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1883                {
1884                        ExportViewCell(*it, stream);
1885                }
1886
1887                stream << "</Interior>" << endl;
1888        }
1889}
1890
1891
1892void ViewCellsTree::ResetPvs()
1893{
1894        stack<ViewCell *> tstack;
1895
1896        tstack.push(mRoot);
1897
1898        while (!tstack.empty())
1899        {
1900                ViewCell *vc = tstack.top();
1901                tstack.pop();
1902
1903                vc->GetPvs().mEntries.clear();
1904               
1905                if (!vc->IsLeaf())
1906                {
1907                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1908                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1909
1910                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1911                        {
1912                                tstack.push(*it);
1913                        }
1914                }
1915        }
1916}
1917
1918
1919void ViewCellsTree::SetActiveSetToLeaves()
1920{
1921}
1922
1923/**************************************************************************/
1924/*                     MergeCandidate implementation                      */
1925/**************************************************************************/
1926
1927
1928MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
1929mRenderCost(0),
1930mDeviationIncr(0),
1931mLeftViewCell(l),
1932mRightViewCell(r),
1933mInitialLeftViewCell(l),
1934mInitialRightViewCell(r)
1935{
1936        //EvalMergeCost();
1937}
1938
1939
1940void MergeCandidate::SetRightViewCell(ViewCell *v)
1941{
1942        mRightViewCell = v;
1943}
1944
1945
1946void MergeCandidate::SetLeftViewCell(ViewCell *v)
1947{
1948        mLeftViewCell = v;
1949}
1950
1951
1952ViewCell *MergeCandidate::GetRightViewCell() const
1953{
1954        return mRightViewCell;
1955}
1956
1957
1958ViewCell *MergeCandidate::GetLeftViewCell() const
1959{
1960        return mLeftViewCell;
1961}
1962
1963
1964ViewCell *MergeCandidate::GetInitialRightViewCell() const
1965{
1966        return mInitialRightViewCell;
1967}
1968
1969
1970ViewCell *MergeCandidate::GetInitialLeftViewCell() const
1971{
1972        return mInitialLeftViewCell;
1973}
1974
1975
1976bool MergeCandidate::IsValid() const
1977{
1978        return !(mLeftViewCell->mParent || mRightViewCell->mParent);
1979}
1980
1981
1982float MergeCandidate::GetRenderCost() const
1983{
1984        return mRenderCost;
1985}
1986
1987
1988float MergeCandidate::GetDeviationIncr() const
1989{
1990        return mDeviationIncr;
1991}
1992
1993
1994float MergeCandidate::GetMergeCost() const
1995{
1996        return mRenderCost * sRenderCostWeight +
1997                   mDeviationIncr * (1.0f - sRenderCostWeight);
1998}
1999
2000
2001
2002
2003
2004
2005/************************************************************************/
2006/*                    MergeStatistics implementation                    */
2007/************************************************************************/
2008
2009
2010void MergeStatistics::Print(ostream &app) const
2011{
2012        app << "===== Merge statistics ===============\n";
2013
2014        app << setprecision(4);
2015
2016        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2017
2018        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2019
2020        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2021
2022        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2023
2024        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2025
2026        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2027
2028        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2029
2030        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2031
2032        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2033
2034        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2035
2036        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2037
2038        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2039
2040        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2041       
2042
2043        app << "===== END OF BspTree statistics ==========\n";
2044}
Note: See TracBrowser for help on using the repository browser.