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

Revision 694, 47.1 KB checked in by mattausch, 18 years ago (diff)

added means for rotating scene

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