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

Revision 703, 47.1 KB checked in by mattausch, 18 years ago (diff)

started implementation of visibility filter

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