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

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