source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCell.cpp @ 582

Revision 582, 35.4 KB checked in by mattausch, 18 years ago (diff)

fixed bug in mergueue to find root of merge and sort out doube view cells

Line 
1#include "ViewCell.h"
2#include "Mesh.h"
3#include "Intersectable.h"
4#include "MeshKdTree.h"
5#include "Triangle3.h"
6#include "common.h"
7#include "Environment.h"
8#include "ViewCellsManager.h"
9#include "Exporter.h"
10
11#include <time.h>
12#include <iomanip>
13#include <stack>
14
15
16
17template <typename T> class myless
18{
19public:
20       
21        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
22        bool operator() (T v1, T v2) const
23        {
24                return (v1->GetTimeStamp() < v2->GetTimeStamp());
25        }
26};
27
28
29typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > TraversalQueue;
30
31int ViewCell::sMailId = 21843194198;
32int ViewCell::sReservedMailboxes = 1;
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
46        if (pvs < lower)
47                return (float)lower;
48        if (pvs > upper)
49                return (float)upper;
50
51        return (float)pvs;
52}
53
54
55int ComputeMergedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
56{
57        int pvs = pvs1.GetSize();
58
59        // compute new pvs size
60        ObjectPvsMap::const_iterator it, it_end =  pvs1.mEntries.end();
61
62        Intersectable::NewMail();
63
64        for (it = pvs1.mEntries.begin(); it != it_end; ++ it)
65        {
66                (*it).first->Mail();
67        }
68
69        it_end = pvs2.mEntries.end();
70
71        for (it = pvs2.mEntries.begin(); it != it_end; ++ it)
72        {
73                Intersectable *obj = (*it).first;
74                if (!obj->Mailed())
75                        ++ pvs;
76        }
77
78        return pvs;
79}
80
81
82ViewCell::ViewCell():
83MeshInstance(NULL),
84mPiercingRays(0),
85mArea(-1),
86mVolume(-1),
87mValid(true),
88mParent(NULL),
89mTimeStamp(0)
90{
91}
92
93ViewCell::ViewCell(Mesh *mesh):
94MeshInstance(mesh),
95mPiercingRays(0),
96mArea(-1),
97mVolume(-1),
98mValid(true),
99mParent(NULL),
100mTimeStamp(0)
101{
102}
103
104
105const ObjectPvs &ViewCell::GetPvs() const
106{
107        return mPvs;
108}
109
110ObjectPvs &ViewCell::GetPvs()
111{
112        return mPvs;
113}
114
115
116int ViewCell::Type() const
117{
118        return VIEW_CELL;
119}
120
121
122float ViewCell::GetVolume() const
123{
124        return mVolume;
125}
126
127
128void ViewCell::SetVolume(float volume)
129{
130        mVolume = volume;
131}
132
133
134void ViewCell::SetMesh(Mesh *mesh)
135{
136        mMesh = mesh;
137}
138
139
140void ViewCell::UpdateViewCellsStats(ViewCellsStatistics &vcStat)
141{
142        ++ vcStat.viewCells;
143               
144        const int pvsSize = mPvs.GetSize();
145
146        vcStat.pvs += pvsSize;
147
148        if (pvsSize == 0)
149                ++ vcStat.emptyPvs;
150
151        if (pvsSize > vcStat.maxPvs)
152                vcStat.maxPvs = pvsSize;
153
154        if (pvsSize < vcStat.minPvs)
155                vcStat.minPvs = pvsSize;
156
157        if (!mValid)
158                ++ vcStat.invalid;
159}
160
161
162float ViewCell::GetArea() const
163{
164        return mArea;
165}
166
167
168void ViewCell::SetArea(float area)
169{
170        mArea = area;
171}
172
173
174void ViewCell::SetValid(const bool valid)
175{
176        mValid = valid;
177}
178
179
180bool ViewCell::GetValid() const
181{
182        return mValid;
183}
184
185
186/*bool ViewCell::IsLeaf() const
187{
188        return true;
189}*/
190
191
192void ViewCell::SetParent(ViewCellInterior *parent)
193{
194        mParent = parent;
195}
196
197
198bool ViewCell::IsRoot() const
199{
200        return !mParent;
201}
202
203
204ViewCellInterior *ViewCell::GetParent() const
205{
206        return mParent;
207}
208
209
210void ViewCell::SetTimeStamp(const int timeStamp)
211{
212        mTimeStamp = timeStamp;
213}
214
215
216int ViewCell::GetTimeStamp() const
217{
218        return mTimeStamp;
219}
220
221
222
223/************************************************************************/
224/*                class ViewCellInterior implementation                 */
225/************************************************************************/
226
227
228ViewCellInterior::ViewCellInterior()
229{
230}
231
232
233ViewCellInterior::~ViewCellInterior()
234{
235        ViewCellContainer::const_iterator it, it_end = mChildren.end();
236
237        for (it = mChildren.begin(); it != it_end; ++ it)
238                delete (*it);
239}
240
241
242ViewCellInterior::ViewCellInterior(Mesh *mesh):
243ViewCell(mesh)
244{
245}
246
247
248bool ViewCellInterior::IsLeaf() const
249{
250        return false;
251}
252
253
254void ViewCellInterior::SetupChildLink(ViewCell *l)
255{
256    mChildren.push_back(l);
257    l->mParent = this;
258}
259
260
261
262/************************************************************************/
263/*                class ViewCellsStatistics implementation              */
264/************************************************************************/
265
266
267
268
269void ViewCellsStatistics::Print(ostream &app) const
270{
271        app << "=========== View Cells Statistics ===============\n";
272
273        app << setprecision(4);
274
275        //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
276
277        app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl;
278
279        app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;
280
281        app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;
282
283        app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;
284
285        app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
286
287        app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;
288
289        app << "#N_AVGLEAVES (average number of leaves per view cell )\n" << AvgLeaves() << endl;
290
291        app << "#N_MAXLEAVES ( maximal number of leaves per view cell )\n" << maxLeaves << endl;
292       
293        app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
294
295        app << "========== End of View Cells Statistics ==========\n";
296}
297
298
299/*************************************************************************/
300/*                    class ViewCellsTree implementation                 */
301/*************************************************************************/
302
303
304ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
305mRoot(NULL),
306mUseAreaForPvs(false),
307mViewCellsManager(vcm)
308{
309        environment->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
310        environment->GetFloatValue("ViewCells.maxStaticMemory", mMaxMemory);
311
312        //-- merge options
313        environment->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight);
314        environment->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells);
315        environment->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio);
316       
317
318        Debug << "========= view cell tree options ================\n";
319        Debug << "minimum view cells: " << mMergeMinViewCells << endl;
320        Debug << "max cost ratio: " << mMergeMaxCostRatio << endl;
321        Debug << "max memory: " << mMaxMemory << endl;
322
323        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
324
325        mStats.open("mergeStats.log");
326}
327
328
329// return memory usage in MB
330float ViewCellsTree::GetMemUsage() const
331{
332        return 0;
333                /*(sizeof(ViewCellsTree) +
334                 mBspStats.Leaves() * sizeof(BspLeaf) +
335                 mBspStats.Interior() * sizeof(BspInterior) +
336                 mBspStats.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);*/
337}
338
339
340int ViewCellsTree::GetSize(ViewCell *vc) const
341{
342        int vcSize = 0;
343
344        stack<ViewCell *> tstack;
345
346        tstack.push(vc);
347
348        while (!tstack.empty())
349        {
350                ViewCell *vc = tstack.top();
351                tstack.pop();
352
353                if (vc->IsLeaf())
354                {
355                        ++ vcSize;
356                }
357                else
358                {
359                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
360                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
361                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
362                                tstack.push(*it);
363                       
364                }
365        }
366
367        return vcSize;
368}
369
370
371void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const
372{
373        stack<ViewCell *> tstack;
374
375        tstack.push(vc);
376
377        while (!tstack.empty())
378        {
379                ViewCell *vc = tstack.top();
380                tstack.pop();
381
382                if (vc->IsLeaf())
383                {
384                        leaves.push_back(vc);
385                }
386                else
387                {
388                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
389                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
390                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
391                                tstack.push(*it);
392                       
393                }
394        }
395}
396
397
398ViewCellsTree::~ViewCellsTree()
399{
400        DEL_PTR(mRoot);
401}
402
403
404int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays,
405                                                                          const ObjectContainer &objects)
406{
407        mNumActiveViewCells = (int)mViewCellsManager->GetViewCells().size();
408
409        float variance = 0;
410        int totalPvs = 0;
411        float totalCost = 0;
412
413        //-- compute statistics values of initial view cells
414        mViewCellsManager->EvaluateRenderStatistics(totalCost,
415                                                                                                mExpectedCost,
416                                                                                                mDeviation,
417                                                                                                variance,
418                                                                                                totalPvs,
419                                                                                                mAvgRenderCost);
420
421
422        //-- fill merge queue
423        vector<MergeCandidate> candidates;
424
425        mViewCellsManager->CollectMergeCandidates(rays, candidates);
426        while(!candidates.empty())
427        {
428                MergeCandidate mc = candidates.back();
429                candidates.pop_back();
430                EvalMergeCost(mc);
431                mMergeQueue.push(mc);
432        }
433
434        Debug << "************************* merge ***********************************" << endl; 
435        Debug << "deviation: " << mDeviation << endl;
436        Debug << "avg render cost: " << mAvgRenderCost << endl;
437        Debug << "expected cost: " <<mExpectedCost << endl;
438
439
440        ViewCellsManager::PvsStatistics pvsStats;
441        mViewCellsManager->GetPvsStatistics(pvsStats);
442
443        static float expectedValue = pvsStats.avgPvs;
444       
445        // the current view cells are kept in this container
446        // we start with the current view cells from the
447        // view cell manager. They will change with
448        // subsequent merges
449        ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
450
451
452        ViewCell::NewMail();
453
454        MergeStatistics mergeStats;
455        mergeStats.Start();
456       
457        long startTime = GetTime();
458
459        mergeStats.collectTime = TimeDiff(startTime, GetTime());
460        mergeStats.candidates = (int)mMergeQueue.size();
461        startTime = GetTime();
462
463        // frequency stats are updated
464        const int statsOut = 100;
465
466        // passes are needed for statistics, because we don't want to record
467        // every merge
468        int pass = 0;
469        int mergedPerPass = 0;
470        float realExpectedCost = mExpectedCost;
471        float realAvgRenderCost = mAvgRenderCost;
472        int realNumActiveViewCells = mNumActiveViewCells;
473       
474        // maximal ratio of old expected render cost to expected render
475        // when the the render queue has to be reset.
476        float avgCostMaxDeviation;
477        int maxMergesPerPass;
478        int numMergedViewCells = 0;
479
480        environment->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", maxMergesPerPass);
481        environment->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", avgCostMaxDeviation);
482
483        cout << "actual merge starts now ... " << endl;
484       
485        //ResetMergeQueue();
486
487        //-- use priority queue to merge leaf pairs
488
489        while (!mMergeQueue.empty())// && (realNumActiveViewCells > mMergeMinViewCells))
490        {
491                //-- reset merge queue if the ratio of current expected cost / real expected cost
492                //   too small or after a given number of merges
493                if ((mergedPerPass > maxMergesPerPass) ||
494                        (avgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
495                {
496                        Debug << "************ reset queue *****************\n"
497                                  << "ratios: " << avgCostMaxDeviation
498                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
499                                  << " merged per pass : " << mergedPerPass << " of maximal " << maxMergesPerPass << endl;
500
501                        Debug << "Values before reset: " 
502                                  << " erc: " << mExpectedCost
503                                  << " avgrc: " << mAvgRenderCost
504                                  << " dev: " << mDeviation << endl;
505       
506                        // adjust render cost
507                        ++ pass;
508
509                        mergedPerPass = 0;
510                        mExpectedCost = realExpectedCost;
511                        mAvgRenderCost = realAvgRenderCost;
512                        mNumActiveViewCells = realNumActiveViewCells;
513                       
514                        const int numMergedViewCells = UpdateActiveViewCells(activeViewCells);
515               
516                        // recompute priorities => reset render cost
517                    ResetMergeQueue();
518
519                       
520                        Debug << "Values after reset: " 
521                                  << " erc: " << mExpectedCost
522                                  << " avg: " << mAvgRenderCost
523                                  << " dev: " << mDeviation << endl;
524
525                        if (mExportMergedViewCells)
526                        {
527                                ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
528                        }
529                }
530
531#ifdef _DEBUG
532                Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() <<
533                          << " rel mergecost: " << mMergeQueue.top().GetRenderCost() / mExpectedCost <<
534                          << " max ratio: " << mMergeMaxCostRatio << endl
535                          << " expected value: " << realExpectedCost << endl;
536#endif
537
538       
539                MergeCandidate mc = mMergeQueue.top();
540                mMergeQueue.pop();
541       
542                // both view cells equal
543                // NOTE: do I really still need this? probably cannot happen!!
544                if (mc.mLeftViewCell == mc.mRightViewCell)
545                        continue;
546
547                if (mc.IsValid())
548                {
549                        ViewCell::NewMail();
550                                               
551                        -- realNumActiveViewCells;
552                        ++ mergeStats.merged;
553                        ++ mergedPerPass;
554
555
556                        //-- update statistical values
557
558                        // total render cost and deviation has changed
559                        // real expected cost will be larger than expected cost used for the
560                        // cost heuristics, but cannot recompute costs on each increase of the
561                        // expected cost
562
563                        totalCost += mc.GetRenderCost();
564                        mDeviation += mc.GetDeviationIncr();
565                                               
566                        realExpectedCost = totalCost / (float)realNumActiveViewCells;
567                       
568                        const float currentMergeCost = mc.GetMergeCost();
569
570                        // merge the view cells of leaf1 and leaf2
571                        int pvsDiff;
572                        ViewCellInterior *mergedVc =
573                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
574
575                        totalPvs += pvsDiff;
576
577                        // set timestamp
578                        mergedVc->SetTimeStamp(mergeStats.merged);
579
580                        realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
581#if VC_HISTORY
582                        if (mc.mLeftViewCell->IsSibling(mc.mRightViewCell))
583                                ++ mergeStats.siblings;
584#endif
585                        if (((mergeStats.merged % statsOut) == 0) ||
586                                (realNumActiveViewCells == mMergeMinViewCells))
587                        {
588                                cout << "merged " << mergeStats.merged << " view cells" << endl;
589
590                                mStats
591                                        << "#Pass\n" << pass << endl
592                                        << "#Merged\n" << mergeStats.merged << endl
593                                        << "#Viewcells\n" << realNumActiveViewCells << endl
594                                        << "#CurrentCost\n" << currentMergeCost << endl
595                                        << "#RelativeCost\n" << currentMergeCost / mOverallCost << endl
596                                        << "#CurrentPvs\n" << mc.GetLeftViewCell()->GetPvs().GetSize() << endl
597                                        << "#MergedSiblings\n" << mergeStats.siblings << endl
598                                        << "#AvgTreeDist\n" << mergeStats.AvgTreeDist() << endl
599                                        << "#UsedExpectedCost\n" << mExpectedCost << endl
600                                        << "#RealExpectedCost\n" << realExpectedCost << endl
601                                        << "#RealAvgRenderCost\n" << realAvgRenderCost << endl
602                                        << "#AvgRenderCost\n" << mAvgRenderCost << endl
603                                        << "#expectedCostRatio\n" << mExpectedCost / realExpectedCost << endl
604                                        << "#Deviation\n" << mDeviation / (float)realNumActiveViewCells << endl
605                                        << "#TotalDeviation\n" << mDeviation<< endl;
606                        }
607                }
608                else
609                {
610                        // merge candidate not valid, because one of the leaves was already
611                        // merged with another one => validate and reinsert into queue
612                        if (ValidateMergeCandidate(mc))
613                        {
614                                EvalMergeCost(mc);
615                                mMergeQueue.push(mc);
616                        }
617                }
618        }
619
620        // adjust stats and reset queue one final time
621        mExpectedCost = realExpectedCost;
622        mAvgRenderCost = realAvgRenderCost;
623        mNumActiveViewCells = realNumActiveViewCells;
624
625        UpdateActiveViewCells(activeViewCells);
626        ResetMergeQueue();
627
628        // create a root node if the merge was not done till root level,
629        // else take the single node as new root
630        if ((int)activeViewCells.size() > 1)
631        {
632                Debug << "creating root of view cell hierarchy for " << (int)activeViewCells.size() << " view cells" << endl;
633                for (int i = 0;  i < activeViewCells.size(); ++ i){
634                        Debug << "here233 " << activeViewCells[i]->GetParent() << endl;
635                        Debug << "here233 " << activeViewCells[i] << endl;
636                }
637                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
638
639                root->SetTimeStamp(mergeStats.merged + 1);
640                mRoot = root;
641        }
642        else if ((int)activeViewCells.size() == 1)
643        {
644                Debug << "setting root of the merge history" << endl;
645                mRoot = activeViewCells[0];
646        }
647
648        // TODO delete because makes no sense here
649        mergeStats.expectedRenderCost = realExpectedCost;
650        mergeStats.deviation = mDeviation;
651
652        // we want to optimize this heuristics
653        mergeStats.heuristics =
654                mDeviation * (1.0f - mRenderCostWeight) +
655                mExpectedCost * mRenderCostWeight;
656
657        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
658        mergeStats.Stop();
659
660        Debug << mergeStats << endl << endl;
661
662
663        //TODO: should return sample contributions?
664        return mergeStats.merged;
665}
666
667
668ViewCell *ViewCellsTree::GetRoot()
669{
670        return mRoot;
671}
672
673
674void ViewCellsTree::ResetMergeQueue()
675{
676        cout << "reset merge queue ... ";
677       
678        vector<MergeCandidate> buf;
679        buf.reserve(mMergeQueue.size());
680                       
681       
682        // store merge candidates in intermediate buffer
683        while (!mMergeQueue.empty())
684        {
685                MergeCandidate mc = mMergeQueue.top();
686                mMergeQueue.pop();
687               
688                // recalculate cost
689                if (ValidateMergeCandidate(mc))
690                {
691                        EvalMergeCost(mc);
692                        buf.push_back(mc);                             
693                }
694        }
695
696        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
697
698        // reinsert back into queue
699        for (bit = buf.begin(); bit != bit_end; ++ bit)
700        {     
701                mMergeQueue.push(*bit);
702        }
703
704        cout << "finished" << endl;
705}
706
707
708int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
709{
710        int numMergedViewCells = 0;
711
712        Debug << "updating active vc: " << viewCells.size() << endl;
713        // find all already merged view cells and remove them from view cells
714               
715        // sort out all view cells which are not active anymore, i.e., they
716        // were already part of a merge
717        int i = 0;
718
719        ViewCell::NewMail();
720
721        while (1)
722        {
723                // remove all merged view cells from end of the vector
724                while (!viewCells.empty() && (viewCells.back()->GetParent()))
725                {
726                        viewCells.pop_back();
727                }
728
729                // all merged view cells have been found
730                if (i >= viewCells.size())
731                        break;
732
733                // already merged view cell, put it to end of vector
734                if (viewCells[i]->GetParent())
735                        swap(viewCells[i], viewCells.back());
736               
737                viewCells[i ++]->Mail();
738        }
739
740
741        // add new view cells to container only if they don't have been
742        // merged in the mean time
743        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
744        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
745        {
746                ViewCell *vc = mMergedViewCells.back();
747                if (!vc->GetParent() && !vc->Mailed())
748                {
749                        vc->Mail();
750                        viewCells.push_back(vc);
751                        ++ numMergedViewCells;
752                }
753        }
754
755        mMergedViewCells.clear();
756
757        // update standard deviation
758        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
759       
760        mDeviation = 0;
761
762        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
763        {
764                int lower = mViewCellsManager->GetMinPvsSize();
765                int upper = mViewCellsManager->GetMaxPvsSize();
766                float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
767               
768                mDeviation += fabs(mAvgRenderCost - penalty);
769        }
770
771        mDeviation /= (float)viewCells.size();
772       
773        return numMergedViewCells;
774}
775
776
777void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
778                                                                                  const ObjectContainer &objects,
779                                                                                  const int numMergedViewCells)
780{
781       
782
783        char s[64];
784
785        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
786        Exporter *exporter = Exporter::GetExporter(s);
787
788        if (exporter)
789        {
790                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
791                exporter->ExportGeometry(objects);
792                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
793                ViewCellContainer::const_iterator it, it_end = viewCells.end();
794
795                int i = 0;
796                for (it = viewCells.begin(); it != it_end; ++ it)
797                {
798                        Material m;
799                        // assign special material to new view cells
800                        // new view cells are on the back of container
801                        if (i ++ >= (viewCells.size() - numMergedViewCells))
802                        {
803                                //m = RandomMaterial();
804                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
805                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
806                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
807                        }
808                        else
809                        {
810                                float col = RandomValue(0.1f, 0.4f);
811                                m.mDiffuseColor.r = col;
812                                m.mDiffuseColor.g = col;
813                                m.mDiffuseColor.b = col;
814                        }
815
816                        exporter->SetForcedMaterial(m);
817                        mViewCellsManager->ExportViewCellGeometry(exporter, *it);
818                }
819                delete exporter;
820                cout << "finished" << endl;
821        }
822}
823
824
825// TODO: should be done in view cells manager
826ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l, ViewCell *r, int &pvsDiff) //const
827{
828        ViewCellInterior *vc = mViewCellsManager->MergeViewCells(l, r);
829
830        // if merge was unsuccessful
831        if (!vc) return NULL;
832
833        // set new size of view cell
834        if (mUseAreaForPvs)
835                vc->SetArea(l->GetArea() + l->GetArea());
836        else
837                vc->SetVolume(r->GetVolume() + r->GetVolume());
838       
839        // important so other merge candidates sharing this view cell
840        // are notified that the merge cost must be updated!!
841        vc->Mail();
842
843        const int pvs1 = l->GetPvs().GetSize();
844        const int pvs2 = r->GetPvs().GetSize();
845
846
847        // new view cells are stored in this vector
848        mMergedViewCells.push_back(vc);
849
850        pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
851
852        return vc;
853}
854
855
856
857
858int ViewCellsTree::RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects)
859{
860        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
861       
862        // Use priority queue of remaining leaf pairs
863        // The candidates either share the same view cells or
864        // are border leaves which share a boundary.
865        // We test if they can be shuffled, i.e.,
866        // either one leaf is made part of one view cell or the other
867        // leaf is made part of the other view cell. It is tested if the
868        // remaining view cells are "better" than the old ones.
869        //
870        // repeat the merging test numPasses times. For example, it could be
871        // that a shuffle only makes sense if another pair was shuffled before.
872        // Therefore we keep two queues and shift the merge candidates between
873        // those two queues until numPasses is reached
874       
875        queue<MergeCandidate> queue1;
876        queue<MergeCandidate> queue2;
877
878        queue<MergeCandidate> *shuffleQueue = &queue1;
879        queue<MergeCandidate> *backQueue = &queue2;
880
881        while (!mMergeQueue.empty())
882        {
883                MergeCandidate mc = mMergeQueue.top();
884                shuffleQueue->push(mc);
885                mMergeQueue.pop();
886        }
887
888        const int numPasses = 5;
889        int pass = 0;
890        int passShuffled = 0;
891        int shuffled = 0;
892        int shuffledViewCells = 0;
893
894        ViewCell::NewMail();
895       
896        do
897        {
898                passShuffled = 0;
899                while (!shuffleQueue->empty())
900                {
901                        MergeCandidate mc = shuffleQueue->front();
902                        shuffleQueue->pop();
903
904                        // both view cells equal or already shuffled
905                        if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
906                                (GetSize(mc.GetLeftViewCell()) == 1) ||
907                                (GetSize(mc.GetRightViewCell()) == 1))
908                        {                       
909                                continue;
910                        }
911
912                        // candidate for shuffling
913                        const bool wasShuffled =
914                                ShuffleLeaves(mc.GetLeftViewCell(), mc.GetRightViewCell());
915               
916                        // shuffled or put into other queue for further refine
917                        if (wasShuffled)
918                        {
919                                ++ passShuffled;
920
921                                if (!mc.GetLeftViewCell()->Mailed())
922                                {
923                                        mc.GetLeftViewCell()->Mail();
924                                        ++ shuffledViewCells;
925                                }
926                                if (!mc.GetRightViewCell()->Mailed())
927                                {
928                                        mc.GetRightViewCell()->Mail();
929                                        ++ shuffledViewCells;
930                                }
931                        }
932                        else
933                        {
934                                backQueue->push(mc);
935                        }
936                }
937
938                // now the back queue is the current shuffle queue
939                swap(shuffleQueue, backQueue);
940                shuffled += passShuffled;
941                Debug << "shuffled in pass: " << passShuffled << endl;
942        }
943        while (((++ pass) < numPasses) && passShuffled);
944
945        while (!shuffleQueue->empty())
946        {
947                shuffleQueue->pop();
948        }
949
950        return shuffledViewCells;
951}
952
953
954
955
956inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
957{
958        return pvs1.AddPvs(pvs2);
959}
960
961
962// recomputes pvs size minus pvs of leaf l
963#if 0
964inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
965{
966        ObjectPvs pvs;
967        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
968        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
969                if (*it != l)
970                        pvs.AddPvs(*(*it)->mPvs);
971        return pvs.GetSize();
972}
973#endif
974
975
976// computes pvs1 minus pvs2
977inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
978{
979        return pvs1.SubtractPvs(pvs2);
980}
981
982
983float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
984                                                                         ViewCell *vc1,
985                                                                         ViewCell *vc2) const
986{
987        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
988        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
989        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
990
991        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
992        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
993
994        const float pvsPenalty1 =
995                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
996
997        const float pvsPenalty2 =
998                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
999
1000
1001        // don't shuffle leaves with pvs > max
1002        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
1003        {
1004                return 1e20f;
1005        }
1006
1007        float p1, p2;
1008
1009    if (mUseAreaForPvs)
1010        {
1011                p1 = vc1->GetArea() - leaf->GetArea();
1012                p2 = vc2->GetArea() + leaf->GetArea();
1013        }
1014        else
1015        {
1016                p1 = vc1->GetVolume() - leaf->GetVolume();
1017                p2 = vc2->GetVolume() + leaf->GetVolume();
1018        }
1019
1020        const float renderCost1 = pvsPenalty1 * p1;
1021        const float renderCost2 = pvsPenalty2 * p2;
1022
1023        float dev1, dev2;
1024
1025        if (1)
1026        {
1027                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1028                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1029        }
1030        else
1031        {
1032                dev1 = fabs(mExpectedCost - renderCost1);
1033                dev2 = fabs(mExpectedCost - renderCost2);
1034        }
1035       
1036        return mRenderCostWeight * (renderCost1 + renderCost2) +
1037                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
1038}
1039
1040
1041void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
1042                                                                ViewCell *vc1,
1043                                                                ViewCell *vc2) const
1044{
1045        // compute new pvs and area
1046        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1047        vc2->GetPvs().AddPvs(leaf->GetPvs());
1048       
1049        if (mUseAreaForPvs)
1050        {
1051                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1052                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1053        }
1054        else
1055        {
1056                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1057                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1058        }
1059
1060        // TODO
1061#if VC_HISTORY
1062        /// add to second view cell
1063        vc2->mLeaves.push_back(leaf);
1064
1065        // erase leaf from old view cell
1066        vector<BspLeaf *>::iterator it = vc1->mLeaves.begin();
1067
1068        for (; *it != leaf; ++ it);
1069        vc1->mLeaves.erase(it);
1070
1071        /*vc1->GetPvs().mEntries.clear();
1072        for (; it != vc1->mLeaves.end(); ++ it)
1073        {
1074                if (*it == leaf)
1075                        vc1->mLeaves.erase(it);
1076                else
1077                        vc1->GetPvs().AddPvs(*(*it)->mPvs);
1078        }*/
1079
1080        leaf->SetViewCell(vc2); // finally change view cell
1081#endif
1082}
1083
1084
1085bool ViewCellsTree::ShuffleLeaves(ViewCell *l, ViewCell *r) const
1086{
1087        float cost1, cost2;
1088
1089        //-- first test if shuffling would decrease cost
1090        cost1 = GetCostHeuristics(l);
1091        cost2 = GetCostHeuristics(r);
1092
1093        const float oldCost = cost1 + cost2;
1094       
1095        float shuffledCost1 = Limits::Infinity;
1096        float shuffledCost2 = Limits::Infinity;
1097
1098        // the view cell should not be empty after the shuffle
1099#if VC_HISTORY
1100        shuffledCost1 = EvalShuffleCost(l, vc1, vc2);
1101        /shuffledCost2 = EvalShuffleCost(r, vc2, vc1);
1102
1103        // if cost of shuffle is less than old cost => shuffle
1104        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1105                return false;
1106       
1107       
1108        if (shuffledCost1 < shuffledCost2)
1109        {
1110                ShuffleLeaf(leaf1, vc1, vc2);
1111                leaf1->Mail();
1112        }
1113        else
1114        {
1115                ShuffleLeaf(leaf2, vc2, vc1);
1116                leaf2->Mail();
1117        }
1118#endif
1119        return true;
1120}
1121
1122
1123float ViewCellsTree::GetVariance(ViewCell *vc) const
1124{
1125        const int upper = mViewCellsManager->GetMaxPvsSize();
1126        const int lower = mViewCellsManager->GetMinPvsSize();
1127
1128        if (1)
1129        {
1130                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1131                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
1132        }
1133
1134    const float leafCost = GetRenderCost(vc);
1135        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1136}
1137
1138
1139float ViewCellsTree::GetDeviation(ViewCell *vc) const
1140{
1141        const int upper = mViewCellsManager->GetMaxPvsSize();
1142        const int lower = mViewCellsManager->GetMinPvsSize();
1143
1144        if (1)
1145        {
1146                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1147                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
1148        }
1149
1150    const float renderCost = GetRenderCost(vc);
1151        return fabs(mExpectedCost - renderCost);
1152}
1153
1154
1155
1156float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1157{
1158        if (mUseAreaForPvs)
1159                return vc->GetPvs().GetSize() * vc->GetArea();
1160
1161        return vc->GetPvs().GetSize() * vc->GetVolume();
1162}
1163
1164
1165float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1166{
1167        return GetRenderCost(vc) * mRenderCostWeight +
1168                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1169}
1170
1171
1172bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
1173{
1174        while (mc.mLeftViewCell->mParent)
1175        {
1176                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1177        }
1178
1179        while (mc.mRightViewCell->mParent)
1180        {
1181                mc.mRightViewCell = mc.mRightViewCell->mParent;
1182        }
1183
1184        return mc.mLeftViewCell != mc.mRightViewCell;
1185}
1186
1187
1188void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1189{
1190        //-- compute pvs difference
1191        const int newPvs =
1192                ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(),
1193                                                         mc.mRightViewCell->GetPvs());
1194                       
1195        const float newPenalty =
1196                EvalPvsPenalty(newPvs,
1197                                           mViewCellsManager->GetMinPvsSize(),
1198                                           mViewCellsManager->GetMaxPvsSize());
1199
1200        ViewCell *vc1 = mc.mLeftViewCell;
1201        ViewCell *vc2 = mc.mRightViewCell;
1202
1203        //-- compute ratio of old cost
1204        //   (i.e., added size of left and right view cell times pvs size)
1205        //   to new rendering cost (i.e, size of merged view cell times pvs size)
1206        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1207
1208    const float newCost = mUseAreaForPvs ?
1209                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1210                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1211
1212
1213        // strong penalty if pvs size too large
1214        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1215        {
1216                mc.mRenderCost = 1e20f;
1217        }
1218        else
1219        {
1220                mc.mRenderCost = (newCost - oldCost) /
1221                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1222        }       
1223       
1224
1225        //-- merge cost also takes deviation into account
1226        float newDev, oldDev;
1227
1228        if (1)
1229                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
1230        else
1231                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
1232       
1233        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1234
1235        // compute deviation increase
1236        mc.mDeviationIncr = newDev - oldDev;
1237       
1238        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1239        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1240}
1241
1242
1243void ViewCellsTree::CompressViewCellsPvs()
1244{
1245        stack<ViewCell *> tstack;
1246       
1247        while (!tstack.empty())
1248        {
1249                ViewCell *viewCell = tstack.top();
1250                tstack.pop();
1251
1252                if (viewCell->IsLeaf())
1253                {
1254                       
1255                }
1256                else
1257                {
1258                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);                       
1259                        ComputeCommonPvs(interior);
1260                }
1261        }
1262}
1263
1264
1265void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1266                                                                                   const int numViewCells)
1267{
1268        TraversalQueue tqueue;
1269        tqueue.push(mRoot);
1270       
1271        while (!tqueue.empty())
1272        {
1273                ViewCell *vc = tqueue.top();
1274               
1275                // save the view cells if it is a leaf or if enough view cells have already been traversed
1276                // because of the priority queue, this will be the optimal set of v
1277                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size()) >= numViewCells))
1278                {
1279                        viewCells.push_back(vc);
1280                }
1281                else
1282                {       
1283                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
1284
1285                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1286
1287                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1288                        {
1289                                tqueue.push(*it);
1290                        }
1291                }
1292
1293                tqueue.pop();
1294        }
1295}
1296       
1297
1298void ViewCellsTree::ComputeCommonPvs(ViewCellInterior *interior)
1299{
1300        Intersectable::NewMail();
1301
1302        ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
1303
1304        ObjectPvsMap::const_iterator oit;
1305
1306        // mail all objects in the leaf sets
1307        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1308        {
1309                ViewCell *vc = *cit;
1310
1311                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1312
1313                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1314                {
1315                        if (!(*oit).first->Mailed())
1316                                (*oit).first->Mail();
1317                       
1318                        (*oit).first->IncMail();
1319                }
1320        }
1321
1322        interior->GetPvs().mEntries.clear();
1323    cit_end = interior->mChildren.end();
1324       
1325        // only the objects which are present in all leaf pvs
1326        // should remain in the parent pvs
1327
1328        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1329        {
1330                ViewCell *vc = *cit;
1331
1332                ObjectPvsMap::const_iterator oit_end = vc->GetPvs().mEntries.end();
1333
1334                for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1335                {
1336                        if ((*oit).first->Mailed((int)interior->mChildren.size()))
1337                        {       
1338                                interior->GetPvs().AddSample((*oit).first, (*oit).second.mSumPdf);
1339                                //(*oit)->remove();
1340                        }
1341                }
1342        }
1343
1344        // delete all the objects from the leaf sets which were moved
1345        // to parent pvs
1346        ObjectPvsMap::const_iterator oit_end = interior->GetPvs().mEntries.end();
1347
1348        for (oit = interior->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
1349        {
1350                for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1351                {
1352                        (*cit)->GetPvs().RemoveSample((*oit).first, Limits::Infinity);
1353                }
1354        }
1355}
1356
1357
1358/**************************************************************************/
1359/*                     MergeCandidate implementation                      */
1360/**************************************************************************/
1361
1362
1363MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
1364mRenderCost(0),
1365mDeviationIncr(0),
1366mLeftViewCell(l),
1367mRightViewCell(r)
1368{
1369        //EvalMergeCost();
1370}
1371
1372
1373void MergeCandidate::SetRightViewCell(ViewCell *v)
1374{
1375        mRightViewCell = v;
1376}
1377
1378
1379void MergeCandidate::SetLeftViewCell(ViewCell *v)
1380{
1381        mLeftViewCell = v;
1382}
1383
1384
1385ViewCell *MergeCandidate::GetRightViewCell() const
1386{
1387        return mRightViewCell;
1388}
1389
1390
1391ViewCell *MergeCandidate::GetLeftViewCell() const
1392{
1393        return mLeftViewCell;
1394}
1395
1396
1397ViewCell *MergeCandidate::GetInitialRightViewCell() const
1398{
1399        return mInitialRightViewCell;
1400}
1401
1402
1403ViewCell *MergeCandidate::GetInitialLeftViewCell() const
1404{
1405        return mInitialLeftViewCell;
1406}
1407
1408
1409bool MergeCandidate::IsValid() const
1410{
1411        return !(mLeftViewCell->mParent || mRightViewCell->mParent);
1412}
1413
1414
1415float MergeCandidate::GetRenderCost() const
1416{
1417        return mRenderCost;
1418}
1419
1420
1421float MergeCandidate::GetDeviationIncr() const
1422{
1423        return mDeviationIncr;
1424}
1425
1426
1427float MergeCandidate::GetMergeCost() const
1428{
1429        return mRenderCost * sRenderCostWeight +
1430                   mDeviationIncr * (1.0f - sRenderCostWeight);
1431}
1432
1433
1434/************************************************************************/
1435/*                    MergeStatistics implementation                    */
1436/************************************************************************/
1437
1438
1439void MergeStatistics::Print(ostream &app) const
1440{
1441        app << "===== Merge statistics ===============\n";
1442
1443        app << setprecision(4);
1444
1445        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
1446
1447        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
1448
1449        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
1450
1451        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
1452
1453        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
1454
1455        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
1456
1457        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
1458
1459        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
1460
1461        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
1462
1463        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
1464
1465        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
1466
1467        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
1468
1469        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
1470       
1471
1472        app << "===== END OF BspTree statistics ==========\n";
1473}
Note: See TracBrowser for help on using the repository browser.