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

Revision 728, 47.9 KB checked in by mattausch, 18 years ago (diff)

added histogram (not tested)
last version before updating render cost evaluation

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