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

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