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

Revision 666, 46.8 KB checked in by mattausch, 18 years ago (diff)

debug version for testing subdivision quality

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