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

Revision 880, 51.4 KB checked in by mattausch, 18 years ago (diff)

added filter to online stuff (not fully working, too slow
)

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