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

Revision 746, 48.9 KB checked in by bittner, 19 years ago (diff)

visualization of the render cost and pvs sizes for viewcells

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