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

Revision 837, 51.9 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
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                       
667                        // HACK
668                        //mergedVc->SetMergeCost(1.0f / (float)realNumActiveViewCells);
669
670                        // check if "siblings (back and front node of the same parent)
671                        if (0 && mViewCellsManager->EqualToSpatialNode(mergedVc))
672                                ++ mergeStats.siblings;
673                        // set the coŽst for rendering a view cell
674                        mergedVc->SetCost(realExpectedCost);
675
676                        if ((mergeStats.merged % statsOut) == 0)
677                                cout << "merged " << mergeStats.merged << " view cells" << endl;
678
679                }
680                else
681                {
682                        // merge candidate not valid, because one of the leaves was already
683                        // merged with another one => validate and reinsert into queue
684                        if (ValidateMergeCandidate(mc))
685                        {
686                                EvalMergeCost(mc);
687                                mMergeQueue.push(mc);
688                        }
689                }
690               
691        }
692
693        // adjust stats and reset queue one final time
694        mExpectedCost = realExpectedCost;
695        mAvgRenderCost = realAvgRenderCost;
696        mNumActiveViewCells = realNumActiveViewCells;
697
698        UpdateActiveViewCells(activeViewCells);
699
700        // refine view cells and reset costs
701        if (mRefineViewCells)
702                RefineViewCells(rays, objects);
703        else
704                ResetMergeQueue();
705
706
707        // create a root node if the merge was not done till root level,
708        // else take the single node as new root
709        if ((int)activeViewCells.size() > 1)
710        {
711                Debug << "creating root of view cell hierarchy for "
712                          << (int)activeViewCells.size() << " view cells" << endl;
713               
714                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
715       
716                ViewCellContainer::const_iterator it, it_end = root->mChildren.end();
717
718                for (it = root->mChildren.begin(); it != it_end; ++ it)
719                        (*it)->SetParent(root);
720       
721                root->SetMergeCost(totalRenderCost);
722                // $$JB keep this 0 temporarilly
723                root->SetCost(0.0f);
724
725                mRoot = root;
726        }
727        // normal case
728        else if (!activeViewCells.empty())
729        {
730                Debug << "setting root of the merge history" << endl;
731                mRoot = activeViewCells[0];
732        }
733        else
734        {
735                Debug << "big error, root is NULL" << endl;
736        }
737       
738        //-- empty merge queue just in case
739        while (!mMergeQueue.empty())
740        {
741                mMergeQueue.pop();
742        }
743
744        // test if voluje is equal
745        Debug << "volume of the root view cell: " << mRoot->GetVolume() << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
746
747        //hack!!
748        //mRoot->GetPvs().Clear();
749       
750        // TODO: delete because makes no sense here
751        mergeStats.expectedRenderCost = realExpectedCost;
752        mergeStats.deviation = mDeviation;
753
754        // we want to optimize this heuristics
755        mergeStats.heuristics =
756                mDeviation * (1.0f - mRenderCostWeight) +
757                mExpectedCost * mRenderCostWeight;
758
759        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
760        mergeStats.Stop();
761        Debug << mergeStats << endl << endl;
762
763        // assign colors for the view cells so that at least one is always consistent
764        AssignRandomColors();
765
766        //TODO: should return sample contributions?
767        return mergeStats.merged;
768}
769
770
771ViewCell *ViewCellsTree::GetRoot() const
772{
773        return mRoot;
774}
775
776
777void ViewCellsTree::ResetMergeQueue()
778{
779        cout << "reset merge queue ... ";
780       
781        vector<MergeCandidate> buf;
782        buf.reserve(mMergeQueue.size());
783                       
784       
785        // store merge candidates in intermediate buffer
786        while (!mMergeQueue.empty())
787        {
788                MergeCandidate mc = mMergeQueue.top();
789                mMergeQueue.pop();
790               
791                // recalculate cost
792                if (ValidateMergeCandidate(mc))
793                {
794                        EvalMergeCost(mc);
795                        buf.push_back(mc);                             
796                }
797        }
798
799        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
800
801        // reinsert back into queue
802        for (bit = buf.begin(); bit != bit_end; ++ bit)
803        {     
804                mMergeQueue.push(*bit);
805        }
806
807        cout << "finished" << endl;
808}
809
810
811int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
812{
813        int numMergedViewCells = 0;
814
815        Debug << "updating active vc: " << (int)viewCells.size() << endl;
816        // find all already merged view cells and remove them from view cells
817               
818        // sort out all view cells which are not active anymore, i.e., they
819        // were already part of a merge
820        int i = 0;
821
822        ViewCell::NewMail();
823
824        while (1)
825        {
826                // remove all merged view cells from end of the vector
827                while (!viewCells.empty() && (viewCells.back()->GetParent()))
828                {
829                        viewCells.pop_back();
830                }
831
832                // all merged view cells have been found
833                if (i >= (int)viewCells.size())
834                        break;
835
836                // already merged this view cell, put it to end of vector
837                if (viewCells[i]->GetParent())
838                        swap(viewCells[i], viewCells.back());
839               
840                // mail view cell that it has not been merged
841                viewCells[i]->Mail();
842
843                // increase loop counter
844                ++ i;
845        }
846
847
848        // add new view cells to container only if they don't have been
849        // merged in the mean time
850        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
851
852        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
853        {
854                ViewCell *vc = mMergedViewCells.back();
855                if (!vc->GetParent() && !vc->Mailed())
856                {
857                        vc->Mail();
858                        viewCells.push_back(vc);
859                        ++ numMergedViewCells;
860                }
861        }
862
863        // dispose old merged view cells
864        mMergedViewCells.clear();
865
866        // update standard deviation
867        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
868       
869        mDeviation = 0;
870
871        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
872        {
873                const int lower = mViewCellsManager->GetMinPvsSize();
874                const int upper = mViewCellsManager->GetMaxPvsSize();
875
876                const float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
877               
878                mDeviation += fabs(mAvgRenderCost - penalty);
879        }
880
881        mDeviation /= (float)viewCells.size();
882       
883        return numMergedViewCells;
884}
885
886
887void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
888                                                                                  const ObjectContainer &objects,
889                                                                                  const int numMergedViewCells)
890{
891       
892
893        char s[64];
894
895        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
896        Exporter *exporter = Exporter::GetExporter(s);
897
898        if (exporter)
899        {
900                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
901                exporter->ExportGeometry(objects);
902                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
903                ViewCellContainer::const_iterator it, it_end = viewCells.end();
904
905                int i = 0;
906                for (it = viewCells.begin(); it != it_end; ++ it)
907                {
908                        Material m;
909                        // assign special material to new view cells
910                        // new view cells are on the back of container
911                        if (i ++ >= (viewCells.size() - numMergedViewCells))
912                        {
913                                //m = RandomMaterial();
914                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
915                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
916                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
917                        }
918                        else
919                        {
920                                float col = RandomValue(0.1f, 0.4f);
921                                m.mDiffuseColor.r = col;
922                                m.mDiffuseColor.g = col;
923                                m.mDiffuseColor.b = col;
924                        }
925
926                        exporter->SetForcedMaterial(m);
927                        mViewCellsManager->ExportViewCellGeometry(exporter, *it);
928                }
929                delete exporter;
930                cout << "finished" << endl;
931        }
932}
933
934
935// TODO: should be done in view cells manager
936ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l,
937                                                                                                ViewCell *r,
938                                                                                                int &pvsDiff) //const
939{
940        ViewCellInterior *vc = mViewCellsManager->MergeViewCells(l, r);
941
942        // if merge was unsuccessful
943        if (!vc) return NULL;
944
945        // set to the new parent view cell
946        l->SetParent(vc);
947        r->SetParent(vc);
948
949        // set new size of view cell
950        if (mUseAreaForPvs)
951        {
952                vc->SetArea(l->GetArea() + l->GetArea());
953        }
954        else
955        {
956                vc->SetVolume(r->GetVolume() + l->GetVolume());
957        }
958
959       
960        // important so other merge candidates sharing this view cell
961        // are notified that the merge cost must be updated!!
962        vc->Mail();
963
964        const int pvs1 = l->GetPvs().GetSize();
965        const int pvs2 = r->GetPvs().GetSize();
966
967
968        // new view cells are stored in this vector
969        mMergedViewCells.push_back(vc);
970
971        pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
972
973
974
975        //Ždon't store intermediate pvs
976        if (mViewCellsStorage == PVS_IN_LEAVES)
977        {
978                l->mPvsSize = l->GetPvs().GetSize();
979                l->mPvsSizeValid = true;
980               
981                if (!l->IsLeaf())
982                        l->GetPvs().Clear();
983               
984                r->mPvsSize = r->GetPvs().GetSize();
985                r->mPvsSizeValid = true;
986               
987                if (!r->IsLeaf())
988                        r->GetPvs().Clear();
989       
990}
991
992
993        return vc;
994}
995
996
997int ViewCellsTree::RefineViewCells(const VssRayContainer &rays,
998                                                                   const ObjectContainer &objects)
999{
1000        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
1001
1002        // intermediate buffer for shuffled view cells
1003        vector<MergeCandidate> buf;
1004        buf.reserve(mMergeQueue.size());
1005                       
1006        // Use priority queue of remaining leaf pairs
1007        // The candidates either share the same view cells or
1008        // are border leaves which share a boundary.
1009        // We test if they can be shuffled, i.e.,
1010        // either one leaf is made part of one view cell or the other
1011        // leaf is made part of the other view cell. It is tested if the
1012        // remaining view cells are "better" than the old ones.
1013       
1014        const int numPasses = 3;
1015        int pass = 0;
1016        int passShuffled = 0;
1017        int shuffled = 0;
1018        int shuffledViewCells = 0;
1019
1020        ViewCell::NewMail();
1021       
1022        while (!mMergeQueue.empty())
1023        {
1024                MergeCandidate mc = mMergeQueue.top();
1025                mMergeQueue.pop();
1026
1027                // both view cells equal or already shuffled
1028                if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
1029                        mc.GetLeftViewCell()->IsLeaf() || mc.GetRightViewCell()->IsLeaf())
1030                {                       
1031                        continue;
1032                }
1033
1034                // candidate for shuffling
1035                const bool wasShuffled = ShuffleLeaves(mc);
1036               
1037                // shuffled or put into other queue for further refine
1038                if (wasShuffled)
1039                {
1040                        ++ passShuffled;
1041
1042                        if (!mc.GetLeftViewCell()->Mailed())
1043                        {
1044                                mc.GetLeftViewCell()->Mail();
1045                                ++ shuffledViewCells;
1046                        }
1047                        if (!mc.GetRightViewCell()->Mailed())
1048                        {
1049                                mc.GetRightViewCell()->Mail();
1050                                ++ shuffledViewCells;
1051                        }
1052                }
1053
1054                // put back into intermediate vector
1055                buf.push_back(mc);
1056        }
1057
1058
1059        //-- in the end, the candidates must be in the mergequeue again
1060        //   with the correct cost
1061
1062        cout << "reset merge queue ... ";
1063       
1064       
1065        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
1066       
1067        for (bit = buf.begin(); bit != bit_end; ++ bit)
1068        {   
1069                MergeCandidate mc = *bit;
1070                // recalculate cost
1071                if (ValidateMergeCandidate(mc))
1072                {
1073                        EvalMergeCost(mc);
1074                        mMergeQueue.push(mc);   
1075                }
1076        }
1077
1078        cout << "finished" << endl;
1079
1080        return shuffledViewCells;
1081}
1082
1083
1084inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1085{
1086        return pvs1.AddPvs(pvs2);
1087}
1088
1089
1090// recomputes pvs size minus pvs of leaf l
1091#if 0
1092inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
1093{
1094        ObjectPvs pvs;
1095        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
1096        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
1097                if (*it != l)
1098                        pvs.AddPvs(*(*it)->mPvs);
1099        return pvs.GetSize();
1100}
1101#endif
1102
1103
1104// computes pvs1 minus pvs2
1105inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1106{
1107        return pvs1.SubtractPvs(pvs2);
1108}
1109
1110
1111float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
1112                                                                         ViewCellInterior *vc1,
1113                                                                         ViewCellInterior *vc2) const
1114{
1115        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
1116        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
1117        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
1118
1119        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
1120        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
1121
1122        const float pvsPenalty1 =
1123                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
1124
1125        const float pvsPenalty2 =
1126                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
1127
1128
1129        // don't shuffle leaves with pvs > max
1130        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
1131        {
1132                return 1e20f;
1133        }
1134
1135        float p1, p2;
1136
1137    if (mUseAreaForPvs)
1138        {
1139                p1 = vc1->GetArea() - leaf->GetArea();
1140                p2 = vc2->GetArea() + leaf->GetArea();
1141        }
1142        else
1143        {
1144                p1 = vc1->GetVolume() - leaf->GetVolume();
1145                p2 = vc2->GetVolume() + leaf->GetVolume();
1146        }
1147
1148        const float renderCost1 = pvsPenalty1 * p1;
1149        const float renderCost2 = pvsPenalty2 * p2;
1150
1151        float dev1, dev2;
1152
1153        if (1)
1154        {
1155                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1156                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1157        }
1158        else
1159        {
1160                dev1 = fabs(mExpectedCost - renderCost1);
1161                dev2 = fabs(mExpectedCost - renderCost2);
1162        }
1163       
1164        return mRenderCostWeight * (renderCost1 + renderCost2) +
1165                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
1166}
1167
1168
1169void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
1170                                                                ViewCellInterior *vc1,
1171                                                                ViewCellInterior *vc2) const
1172{
1173        // compute new pvs and area
1174        // TODO change
1175        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1176        vc2->GetPvs().AddPvs(leaf->GetPvs());
1177       
1178        if (mUseAreaForPvs)
1179        {
1180                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1181                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1182        }
1183        else
1184        {
1185                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1186                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1187        }
1188
1189       
1190        ViewCellInterior *p = dynamic_cast<ViewCellInterior *>(leaf->GetParent());
1191
1192        p->RemoveChildLink(leaf);
1193        vc2->SetupChildLink(leaf);
1194}
1195
1196
1197bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
1198{
1199        float cost1, cost2;
1200
1201        ViewCellInterior *vc1 = dynamic_cast<ViewCellInterior *>(mc.GetLeftViewCell());
1202        ViewCellInterior *vc2 = dynamic_cast<ViewCellInterior *>(mc.GetRightViewCell());
1203
1204        ViewCell *leaf1 = mc.GetInitialLeftViewCell();
1205        ViewCell *leaf2 = mc.GetInitialRightViewCell();
1206
1207        //-- first test if shuffling would decrease cost
1208        cost1 = GetCostHeuristics(vc1);
1209        cost2 = GetCostHeuristics(vc2);
1210
1211        const float oldCost = cost1 + cost2;
1212       
1213        float shuffledCost1 = Limits::Infinity;
1214        float shuffledCost2 = Limits::Infinity;
1215
1216        if (leaf1)
1217                shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);       
1218        if (leaf2)
1219                shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
1220
1221        // if cost of shuffle is less than old cost => shuffle
1222        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1223                return false;
1224       
1225        if (shuffledCost1 < shuffledCost2)
1226        {
1227                if (leaf1)
1228                        ShuffleLeaf(leaf1, vc1, vc2);
1229                mc.mInitialLeftViewCell = NULL;
1230        }
1231        else
1232        {
1233                if (leaf2)
1234                        ShuffleLeaf(leaf2, vc2, vc1);
1235                mc.mInitialRightViewCell = NULL;
1236        }
1237
1238        return true;
1239}
1240
1241
1242float ViewCellsTree::GetVariance(ViewCell *vc) const
1243{
1244        const int upper = mViewCellsManager->GetMaxPvsSize();
1245        const int lower = mViewCellsManager->GetMinPvsSize();
1246
1247        if (1)
1248        {
1249                const float penalty =
1250                        EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1251                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) /
1252                        (float)mNumActiveViewCells;
1253        }
1254
1255    const float leafCost = GetRenderCost(vc);
1256        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1257}
1258
1259
1260float ViewCellsTree::GetDeviation(ViewCell *vc) const
1261{
1262        const int upper = mViewCellsManager->GetMaxPvsSize();
1263        const int lower = mViewCellsManager->GetMinPvsSize();
1264
1265        if (1)
1266        {
1267                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1268                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
1269        }
1270
1271    const float renderCost = GetRenderCost(vc);
1272        return fabs(mExpectedCost - renderCost);
1273}
1274
1275
1276
1277float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1278{
1279        if (mUseAreaForPvs)
1280                return vc->GetPvs().GetSize() * vc->GetArea();
1281
1282        return vc->GetPvs().GetSize() * vc->GetVolume();
1283}
1284
1285
1286float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1287{
1288        return GetRenderCost(vc) * mRenderCostWeight +
1289                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1290}
1291
1292
1293bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
1294{
1295        // propagate up so we have only the active view cells
1296        while (mc.mLeftViewCell->mParent)
1297        {
1298                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1299        }
1300
1301        while (mc.mRightViewCell->mParent)
1302        {
1303                mc.mRightViewCell = mc.mRightViewCell->mParent;
1304        }
1305
1306        // this view cell was already merged
1307        //return mc.mLeftViewCell && (mc.mLeftViewCell != mc.mRightViewCell);
1308        return mc.mLeftViewCell != mc.mRightViewCell;
1309}
1310
1311
1312void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1313{
1314        //-- compute pvs difference
1315        int newPvs;
1316        if (1) // not valid if not using const cost per object!!
1317                newPvs = ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
1318        else
1319                newPvs = (int)ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
1320
1321        const float newPenalty = EvalPvsPenalty(newPvs,
1322                                                                                        mViewCellsManager->GetMinPvsSize(),
1323                                                                                        mViewCellsManager->GetMaxPvsSize());
1324
1325        ViewCell *vc1 = mc.mLeftViewCell;
1326        ViewCell *vc2 = mc.mRightViewCell;
1327
1328        //-- compute ratio of old cost
1329        //   (i.e., added size of left and right view cell times pvs size)
1330        //   to new rendering cost (i.e, size of merged view cell times pvs size)
1331        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1332
1333    const float newCost = mUseAreaForPvs ?
1334                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1335                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1336
1337
1338        // strong penalty if pvs size too large
1339        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1340        {
1341                mc.mRenderCost = 1e20f;
1342        }
1343        else
1344        {
1345                mc.mRenderCost = (newCost - oldCost) /
1346                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1347        }       
1348       
1349
1350        //-- merge cost also takes deviation into account
1351        float newDev, oldDev;
1352
1353        if (1)
1354                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
1355        else
1356                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
1357       
1358        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1359
1360        // compute deviation increase
1361        mc.mDeviationIncr = newDev - oldDev;
1362       
1363        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1364        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1365}
1366
1367
1368void ViewCellsTree::SetViewCellsStorage(int stype)
1369{
1370        if (mViewCellsStorage == stype)
1371                return;
1372
1373        // TODO
1374        switch (stype)
1375        {
1376        case COMPRESSED:
1377                CompressViewCellsPvs(mRoot);
1378                break;
1379        default:
1380                break;
1381        }
1382
1383        mViewCellsStorage = stype;
1384}
1385
1386
1387void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
1388{
1389        if (!root->IsLeaf())
1390        {
1391                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
1392
1393        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1394               
1395                // compress child sets first
1396                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1397                {
1398                        CompressViewCellsPvs(*it);
1399                }
1400
1401                // compress root node
1402                PullUpVisibility(interior);
1403        }
1404}
1405
1406
1407void ViewCellsTree::ExportStats(const string &mergeStats)
1408{
1409        TraversalQueue tqueue;
1410
1411        tqueue.push(mRoot);
1412        int numViewCells = 1;
1413       
1414        const AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1415        const float vol = box.GetVolume();
1416
1417        const int rootPvs = GetPvsSize(mRoot);
1418
1419        Debug << "vsb volume: " << vol << endl;
1420        Debug << "root volume: " << mRoot->GetVolume() << endl;
1421        Debug << "root pvs: " << rootPvs << endl;
1422
1423        int totalPvs;
1424        float totalRenderCost, avgRenderCost, expectedCost;
1425
1426        float deviation = 0;
1427        totalPvs = rootPvs;
1428        totalRenderCost = avgRenderCost = expectedCost = (float)rootPvs;
1429
1430        ofstream stats;
1431        stats.open(mergeStats.c_str());
1432
1433        //-- first view cell
1434        stats
1435                << "#Pass\n" << 0 << endl
1436                //<< "#Merged\n" << mergeStats.merged << endl
1437                << "#ViewCells\n" << numViewCells << endl
1438        << "#RenderCostDecrease\n" << 0 << endl // TODO
1439                << "#TotalRenderCost\n" << totalRenderCost << endl
1440                << "#CurrentPvs\n" << rootPvs << endl
1441                << "#ExpectedCost\n" << expectedCost << endl
1442                << "#AvgRenderCost\n" << avgRenderCost << endl
1443                << "#Deviation\n" << deviation << endl
1444                << "#TotalPvs\n" << totalPvs << endl
1445                << "#PvsSizeDecrease\n" << 0 << endl // TODO
1446                << "#Volume\n" << mRoot->GetVolume() << endl
1447                << endl;
1448
1449
1450        while (!tqueue.empty())
1451        {
1452                ViewCell *vc = tqueue.top();
1453                tqueue.pop();
1454
1455                if (!vc->IsLeaf())
1456                {       
1457                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1458                       
1459                        const int parentPvs = GetPvsSize(interior);
1460                        const float parentCost = (float)parentPvs * interior->GetVolume();
1461                        float childCost = 0;
1462                        int childPvs = 0;
1463
1464                        -- numViewCells;
1465
1466                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1467
1468                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1469                        {
1470                                int pvsSize = GetPvsSize(*it);
1471                                childCost += (float) pvsSize * (*it)->GetVolume();
1472                                childPvs += pvsSize;
1473
1474                                tqueue.push(*it);
1475                                ++ numViewCells;
1476                        }
1477
1478               
1479                        const float costDecr = (parentCost - childCost) / vol;
1480
1481                        totalRenderCost -= costDecr;
1482                        totalPvs += childPvs - parentPvs;
1483                       
1484                        expectedCost = totalRenderCost / (float)numViewCells;
1485                        avgRenderCost = (float)totalPvs / (float)numViewCells;
1486
1487                        stats
1488                                << "#Pass\n" << 0 << endl
1489                                //<< "#Merged\n" << mergeStats.merged << endl
1490                                << "#ViewCells\n" << numViewCells << endl
1491                                << "#RenderCostDecrease\n" << costDecr << endl // TODO
1492                                << "#TotalRenderCost\n" << totalRenderCost << endl
1493                                << "#CurrentPvs\n" << parentPvs << endl
1494                                << "#ExpectedCost\n" << expectedCost << endl
1495                                << "#AvgRenderCost\n" << avgRenderCost << endl
1496                                << "#Deviation\n" << deviation << endl
1497                                << "#TotalPvs\n" << totalPvs << endl
1498                                << "#PvsSizeDecrease\n" << childPvs - parentPvs << endl // TODO
1499                                << "#Volume\n" << vc->GetVolume() << endl
1500                                << endl;
1501
1502                }
1503        }
1504
1505        stats.close();
1506}
1507
1508
1509void ViewCellsTree::SetRoot(ViewCell *root)
1510{
1511        mRoot = root;
1512}
1513
1514
1515void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1516                                                                                   const int numViewCells)
1517{
1518        TraversalQueue tqueue;
1519        tqueue.push(mRoot);
1520       
1521        while (!tqueue.empty())
1522        {
1523                ViewCell *vc = tqueue.top();
1524                tqueue.pop();
1525
1526                // save the view cells if it is a leaf or if enough view cells have already been traversed
1527                // because of the priority queue, this will be the optimal set of v
1528                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size() + 1) >= numViewCells))
1529                {
1530                        viewCells.push_back(vc);
1531                }
1532                else
1533                {       
1534                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1535
1536                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1537
1538                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1539                        {
1540                                tqueue.push(*it);
1541                        }
1542                }
1543        }
1544}
1545       
1546
1547void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
1548{
1549        Intersectable::NewMail((int)interior->mChildren.size());
1550
1551        ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
1552
1553        ObjectPvsMap::const_iterator oit;
1554
1555        // mail all objects in the leaf sets
1556        // we are interested in the objects which are present in all leaves
1557        // => count how often an object is part of a child set
1558        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1559        {
1560                ViewCell *vc = *cit;
1561
1562                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1563
1564                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1565                {
1566                        Intersectable *obj = (*oit).first;
1567                        if ((cit == interior->mChildren.begin()) && !obj->Mailed())
1568                                obj->Mail();
1569                       
1570                        int incm = obj->IncMail();
1571                }
1572        }
1573
1574        interior->GetPvs().mEntries.clear();
1575       
1576       
1577        // only the objects which are present in all leaf pvs
1578        // should remain in the parent pvs
1579        // these are the objects which have been mailed in all children
1580        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1581        {
1582                ViewCell *vc = *cit;
1583
1584                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1585
1586                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1587                {               
1588                        if ((*oit).first->Mailed((int)interior->mChildren.size()))
1589                        {       
1590                                interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
1591                        }
1592                }
1593        }
1594
1595
1596
1597        // delete all the objects from the leaf sets which were moved to parent pvs
1598        ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
1599
1600        for (oit = interior->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1601        {
1602                for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1603                {
1604                        if (!(*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity))
1605                                Debug << "should not come here!" << endl;
1606                }
1607        }
1608
1609        /*int dummy = interior->GetPvs().GetSize();
1610
1611        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1612        {
1613                dummy += (*cit)->GetPvs().GetSize();
1614        }*/
1615
1616}
1617
1618// TODO
1619void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
1620{
1621        // pvs is stored in each cell
1622        if (mViewCellsStorage == PVS_IN_INTERIORS)
1623        {
1624                pvs = vc->GetPvs();
1625                return;
1626        }
1627
1628        Intersectable::NewMail();
1629
1630
1631        int pvsSize = 0;
1632        ViewCell *root = vc;
1633       
1634        // also add pvs from this view cell to root
1635        while (root->GetParent())
1636        {
1637                root = root->GetParent();
1638                pvs.AddPvs(root->GetPvs());
1639        }
1640
1641        stack<ViewCell *> tstack;
1642        tstack.push(vc);
1643
1644        while (!tstack.empty())
1645        {
1646                vc = tstack.top();
1647                tstack.pop();
1648
1649                // add new pvs
1650                pvs.AddPvs(vc->GetPvs());
1651
1652                if (!vc->IsLeaf())
1653                {
1654                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1655
1656                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1657
1658                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1659                        {
1660                                tstack.push(*it);
1661                        }               
1662                }
1663        }
1664}
1665
1666
1667int ViewCellsTree::GetPvsSize(ViewCell *vc) const
1668{
1669        int pvsSize = 0;
1670
1671        if (vc->IsLeaf())
1672        {
1673                pvsSize = vc->GetPvs().GetSize();
1674        }
1675       
1676
1677        Intersectable::NewMail();
1678
1679        //////////////////////////
1680        switch (mViewCellsStorage)
1681        {
1682        case PVS_IN_LEAVES: //-- store pvs only in leaves
1683                {                       
1684                        if (vc->mPvsSizeValid)
1685                        {
1686                                pvsSize = vc->mPvsSize;
1687                                break;
1688                        }
1689       
1690                        //-- if no valid pvs size stored as a scalar=> compute new pvs size
1691                        ViewCellContainer leaves;
1692                        CollectLeaves(vc, leaves);
1693
1694                        ViewCellContainer::const_iterator it, it_end = leaves.end();
1695
1696                        Intersectable::NewMail();
1697
1698                        // sum different intersectables
1699                        for (it = leaves.begin(); it != it_end; ++ it)
1700                        {
1701                                ObjectPvsMap::iterator oit, oit_end = (*it)->GetPvs().mEntries.end();
1702
1703                                // mail all from first pvs
1704                                for (oit = (*it)->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1705                                {
1706                                        Intersectable *intersect = (*oit).first;
1707
1708                                        if (!intersect->Mailed())
1709                                        {
1710                                                ++ pvsSize;
1711                                                intersect->Mail();                                     
1712                                        }
1713                                }
1714                        }
1715
1716                        break;
1717                }
1718        case COMPRESSED:
1719                {
1720                        ////////////////////////
1721        //-- compressed pvs
1722
1723                        if (vc->mPvsSizeValid)
1724                                return vc->mPvsSize;
1725
1726                        // if no pvs size stored: compute
1727        int pvsSize = 0;
1728        ViewCell *root = vc;
1729       
1730        // also add pvs from this view cell to root
1731        while (root->GetParent())
1732        {
1733                root = root->GetParent();
1734                pvsSize += CountDiffPvs(root);
1735        }
1736
1737        stack<ViewCell *> tstack;
1738        tstack.push(vc);
1739
1740        while (!tstack.empty())
1741        {
1742                vc = tstack.top();
1743                tstack.pop();
1744
1745                pvsSize += CountDiffPvs(vc);
1746
1747                if (!vc->IsLeaf())
1748                {
1749                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1750
1751                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1752
1753                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1754                        {
1755                                tstack.push(*it);
1756                        }               
1757                }
1758        }
1759                        break;
1760                }
1761        case PVS_IN_INTERIORS:
1762        default:Debug << "in interiors: " << vc->mPvsSize << " $$ " << vc->GetPvs().GetSize() << endl;
1763                pvsSize = vc->GetPvs().GetSize();               
1764        }
1765
1766        return pvsSize; 
1767}
1768
1769
1770float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
1771{
1772        const float entrySize =
1773                sizeof(PvsData<Intersectable *>) + sizeof(Intersectable *);
1774
1775        return (float)GetNumPvsEntries(vc) * entrySize;
1776}
1777
1778
1779int ViewCellsTree::GetNumPvsEntries(ViewCell *vc) const
1780{
1781        int pvsSize = 0;
1782        // only count leaves for uncompressed method for fairness
1783        if ((mViewCellsStorage == PVS_IN_INTERIORS) || vc->IsLeaf())
1784        {
1785                pvsSize = vc->GetPvs().GetSize();
1786        }
1787
1788        if (!vc->IsLeaf())
1789        {
1790                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1791
1792                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1793
1794                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1795                {
1796                        pvsSize += GetNumPvsEntries(*it);
1797                }
1798        }
1799
1800        return pvsSize;         
1801}
1802
1803
1804int ViewCellsTree::ViewCellsStorage() const
1805{
1806        return mViewCellsStorage;
1807}
1808
1809
1810ViewCell *ViewCellsTree::GetActiveViewCell(ViewCell *vc) const
1811{
1812        while (vc->GetParent() && !vc->IsActive())
1813        {
1814                vc = vc->GetParent();
1815        }
1816
1817        return vc;
1818}
1819
1820
1821void ViewCellsTree::PropagatePvs(ViewCell *vc)
1822{       
1823        ViewCell *viewCell = vc;
1824
1825        // propagate pvs up
1826        while (viewCell->GetParent())
1827        {
1828                viewCell->GetParent()->GetPvs().Merge(vc->GetPvs());
1829                viewCell = viewCell->GetParent();
1830        }
1831
1832        if (vc->IsLeaf())
1833                return;
1834
1835        // propagate pvs to the leaves
1836        stack<ViewCell *> tstack;
1837        tstack.push(vc);
1838
1839        while (!tstack.empty())
1840        {
1841                ViewCell *viewCell = tstack.top();
1842                tstack.pop();
1843
1844                if (viewCell != vc)
1845                {
1846                        viewCell->GetPvs().Merge(vc->GetPvs());
1847                }
1848
1849                if (!viewCell->IsLeaf())
1850                {
1851                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
1852
1853                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1854
1855                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1856                        {
1857                                tstack.push(*it);
1858                        }
1859                }
1860        }
1861}
1862
1863
1864void ViewCellsTree::AssignRandomColors()
1865{
1866        TraversalQueue tqueue;
1867       
1868        tqueue.push(mRoot);
1869       
1870        mRoot->SetColor(RandomColor(0.3f, 1.0f));
1871       
1872        while (!tqueue.empty())
1873        {
1874                ViewCell *vc = tqueue.top();
1875                tqueue.pop();
1876
1877                // save the view cells if it is a leaf or if enough view cells have already been traversed
1878                // because of the priority queue, this will be the optimal set of v
1879                if (!vc->IsLeaf())
1880                {       
1881                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1882                 
1883                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1884                 
1885                        float maxProbability = -1.0f;
1886                 
1887                        ViewCell *maxViewCell = NULL;
1888                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1889                        {
1890                                ViewCell *v = *it;
1891                         
1892                                // set random color
1893                                v->SetColor(RandomColor(0.3f, 1.0f));
1894                         
1895                                if (v->GetVolume() > maxProbability)
1896                                {
1897                                        maxProbability = v->GetVolume();
1898                                        maxViewCell = v;
1899                                }
1900
1901                                if (maxViewCell)
1902                                {
1903                                        maxViewCell->SetColor(vc->GetColor());
1904                                }
1905                               
1906                                tqueue.push(v);
1907                        }
1908                }       
1909        }
1910}
1911
1912
1913/** Get costs resulting from each merge step. */
1914void
1915ViewCellsTree::GetCostFunction(vector<float> &costFunction)
1916{
1917  TraversalQueue tqueue;
1918  tqueue.push(mRoot);
1919  while (!tqueue.empty()) {
1920        ViewCell *vc = tqueue.top();
1921        tqueue.pop();
1922        // save the view cells if it is a leaf or if enough view cells have already been traversed
1923        // because of the priority queue, this will be the optimal set of v
1924        if (!vc->IsLeaf()) {   
1925          ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1926          costFunction.push_back(interior->GetMergeCost());
1927         
1928          ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1929         
1930          for (it = interior->mChildren.begin(); it != it_end; ++ it) {
1931                tqueue.push(*it);
1932          }
1933         
1934        }
1935  }
1936}
1937
1938
1939void  ViewCellsTree::UpdateViewCellsStats(ViewCell *vc, ViewCellsStatistics &vcStat)
1940{
1941        ++ vcStat.viewCells;
1942               
1943        const int pvsSize = GetPvsSize(vc);
1944
1945        vcStat.pvsSize += pvsSize;
1946
1947        if (pvsSize == 0)
1948                ++ vcStat.emptyPvs;
1949
1950        if (pvsSize > vcStat.maxPvs)
1951                vcStat.maxPvs = pvsSize;
1952
1953        if (pvsSize < vcStat.minPvs)
1954                vcStat.minPvs = pvsSize;
1955
1956        if (!vc->GetValid())
1957                ++ vcStat.invalid;
1958}
1959
1960
1961bool ViewCellsTree::Export(ofstream &stream, const int pvsType)
1962{
1963        // export recurvivly all view cells from the root
1964        ExportViewCell(mRoot, stream, pvsType);
1965
1966        return true;
1967}
1968
1969
1970void ViewCellsTree::CreateUniqueViewCellsIds()
1971{
1972        stack<ViewCell *> tstack;
1973
1974        int currentId = 0;
1975
1976        tstack.push(mRoot);
1977
1978        while (!tstack.empty())
1979        {
1980                ViewCell *vc = tstack.top();
1981                tstack.pop();
1982
1983                vc->SetId(currentId ++);
1984
1985                if (!vc->IsLeaf())
1986                {
1987                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1988                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1989                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1990                        {
1991                                tstack.push(*it);
1992                        }
1993                }
1994        }
1995}
1996
1997
1998void ViewCellsTree::ExportPvs(ViewCell *viewCell, ofstream &stream, const int pvsType)
1999{
2000        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
2001
2002        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
2003        {
2004                switch (pvsType)
2005                {
2006                case EXPORT_IDS:
2007            {
2008                                stream << (*it).first->GetId() << " ";
2009                        }
2010                        break;
2011                case EXPORT_BBOXES:
2012                        {
2013                                Debug << "here24 " << pvsType << endl;
2014                                MeshInstance *mi = dynamic_cast<MeshInstance *>((*it).first);
2015                                AxisAlignedBox3 box = mi->GetBox();
2016                                stream << "<BoundingBox"
2017                                           << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
2018                                           << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
2019                        }
2020                        break;
2021                case EXPORT_EMPTY_PVS:
2022                default:
2023                        break;
2024                }
2025        }
2026}
2027
2028
2029void ViewCellsTree::ExportViewCell(ViewCell *viewCell, ofstream &stream, const int pvsType)
2030{
2031        if (viewCell->IsLeaf())
2032        {
2033                stream << "<Leaf ";
2034                stream << "id=\"" << viewCell->GetId() << "\" ";
2035                stream << "active=\"" << viewCell->IsActive() << "\" ";
2036                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2037                stream << "pvs=\"";
2038               
2039                //-- export pvs
2040                Debug << "here66 " << pvsType << endl;
2041                ExportPvs(viewCell, stream, pvsType);
2042       
2043                stream << "\" />" << endl;
2044                //stream << " </Leaf>" << endl;
2045        }
2046        else
2047        {
2048                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2049       
2050                stream << "<Interior ";
2051                stream << "id=\"" << viewCell->GetId() << "\" ";
2052                stream << "active=\"" << viewCell->IsActive() << "\" ";
2053                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2054               
2055                //-- NOTE: do not export pvss for interior view cells because
2056                // they can be compeletely reconstructed from the leaf pvss
2057                if (0)
2058                {
2059                        stream << "pvs=\"";
2060                        ExportPvs(viewCell, stream, pvsType);
2061                }
2062
2063                stream << "\" >" << endl;
2064
2065                //-- recursivly export child view cells
2066                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2067
2068                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2069                {
2070                        ExportViewCell(*it, stream, pvsType);
2071                }
2072
2073                stream << "</Interior>" << endl;
2074        }
2075}
2076
2077
2078void ViewCellsTree::ResetPvs()
2079{
2080        stack<ViewCell *> tstack;
2081
2082        tstack.push(mRoot);
2083
2084        while (!tstack.empty())
2085        {
2086                ViewCell *vc = tstack.top();
2087                tstack.pop();
2088
2089                vc->GetPvs().mEntries.clear();
2090               
2091                if (!vc->IsLeaf())
2092                {
2093                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
2094                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2095
2096                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2097                        {
2098                                tstack.push(*it);
2099                        }
2100                }
2101        }
2102}
2103
2104
2105void ViewCellsTree::SetActiveSetToLeaves()
2106{
2107        // todo
2108}
2109
2110/**************************************************************************/
2111/*                     MergeCandidate implementation                      */
2112/**************************************************************************/
2113
2114
2115MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2116mRenderCost(0),
2117mDeviationIncr(0),
2118mLeftViewCell(l),
2119mRightViewCell(r),
2120mInitialLeftViewCell(l),
2121mInitialRightViewCell(r)
2122{
2123        //EvalMergeCost();
2124}
2125
2126
2127void MergeCandidate::SetRightViewCell(ViewCell *v)
2128{
2129        mRightViewCell = v;
2130}
2131
2132
2133void MergeCandidate::SetLeftViewCell(ViewCell *v)
2134{
2135        mLeftViewCell = v;
2136}
2137
2138
2139ViewCell *MergeCandidate::GetRightViewCell() const
2140{
2141        return mRightViewCell;
2142}
2143
2144
2145ViewCell *MergeCandidate::GetLeftViewCell() const
2146{
2147        return mLeftViewCell;
2148}
2149
2150
2151ViewCell *MergeCandidate::GetInitialRightViewCell() const
2152{
2153        return mInitialRightViewCell;
2154}
2155
2156
2157ViewCell *MergeCandidate::GetInitialLeftViewCell() const
2158{
2159        return mInitialLeftViewCell;
2160}
2161
2162
2163bool MergeCandidate::IsValid() const
2164{
2165        // if one has a parent, it was already merged
2166        return !(mLeftViewCell->mParent || mRightViewCell->mParent);
2167}
2168
2169
2170float MergeCandidate::GetRenderCost() const
2171{
2172        return mRenderCost;
2173}
2174
2175
2176float MergeCandidate::GetDeviationIncr() const
2177{
2178        return mDeviationIncr;
2179}
2180
2181
2182float MergeCandidate::GetMergeCost() const
2183{
2184        return mRenderCost * sRenderCostWeight +
2185                   mDeviationIncr * (1.0f - sRenderCostWeight);
2186}
2187
2188
2189
2190
2191
2192
2193/************************************************************************/
2194/*                    MergeStatistics implementation                    */
2195/************************************************************************/
2196
2197
2198void MergeStatistics::Print(ostream &app) const
2199{
2200        app << "===== Merge statistics ===============\n";
2201
2202        app << setprecision(4);
2203
2204        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2205
2206        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2207
2208        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2209
2210        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2211
2212        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2213
2214        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2215
2216        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2217
2218        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2219
2220        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2221
2222        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2223
2224        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2225
2226        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2227
2228        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2229       
2230
2231        app << "===== END OF BspTree statistics ==========\n";
2232}
Note: See TracBrowser for help on using the repository browser.