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

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