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

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