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

Revision 801, 50.8 KB checked in by mattausch, 19 years ago (diff)

debug version for testing subdivision

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