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

Revision 1706, 60.9 KB checked in by mattausch, 18 years ago (diff)

worked on full evaluation framework

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