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

Revision 728, 47.9 KB checked in by mattausch, 18 years ago (diff)

added histogram (not tested)
last version before updating render cost evaluation

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