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

Revision 863, 51.3 KB checked in by mattausch, 18 years ago (diff)

working on preprocessor integration
added iv stuff

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