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

Revision 752, 50.6 KB checked in by mattausch, 18 years ago (diff)

after rendering workshop submissioin
x3dparser can use def - use constructs
implemented improved evaluation (samples are only stored in leaves, only propagate pvs size)

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