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

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