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

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