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

Revision 1707, 60.8 KB checked in by mattausch, 18 years ago (diff)

worked on full render cost evaluation
warning: some change sin render cost evaluation for pvs which could have bugs

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