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

Revision 881, 51.0 KB checked in by mattausch, 18 years ago (diff)

changing concept of active view cells

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