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

Revision 580, 31.8 KB checked in by mattausch, 18 years ago (diff)

implemented variance
started implementing merge history

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/*                class ViewCellInterior implementation                 */
224/************************************************************************/
225
226
227ViewCellInterior::ViewCellInterior()
228{
229}
230
231
232ViewCellInterior::~ViewCellInterior()
233{
234        ViewCellContainer::const_iterator it, it_end = mChildren.end();
235
236        for (it = mChildren.begin(); it != it_end; ++ it)
237                delete (*it);
238}
239
240
241ViewCellInterior::ViewCellInterior(Mesh *mesh):
242ViewCell(mesh)
243{
244}
245
246
247bool ViewCellInterior::IsLeaf() const
248{
249        return false;
250}
251
252
253void ViewCellInterior::SetupChildLink(ViewCell *l)
254{
255    mChildren.push_back(l);
256    l->mParent = this;
257}
258
259
260
261/************************************************************************/
262/*                class ViewCellsStatistics implementation              */
263/************************************************************************/
264
265
266
267
268void ViewCellsStatistics::Print(ostream &app) const
269{
270        app << "=========== View Cells Statistics ===============\n";
271
272        app << setprecision(4);
273
274        //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
275
276        app << "#N_OVERALLPVS ( objects in PVS )\n" << pvs << endl;
277
278        app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;
279
280        app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;
281
282        app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;
283
284        app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
285
286        app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;
287
288        app << "#N_AVGLEAVES (average number of leaves per view cell )\n" << AvgLeaves() << endl;
289
290        app << "#N_MAXLEAVES ( maximal number of leaves per view cell )\n" << maxLeaves << endl;
291       
292        app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
293
294        app << "========== End of View Cells Statistics ==========\n";
295}
296
297
298/*************************************************************************/
299/*                    class ViewCellsTree implementation                 */
300/*************************************************************************/
301
302
303ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
304mRoot(NULL),
305mUseAreaForPvs(false),
306mViewCellsManager(vcm)
307{
308        environment->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
309
310        //-- merge options
311        environment->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight);
312        environment->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells);
313        environment->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio);
314       
315        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
316
317        mStats.open("mergeStats.log");
318}
319
320
321int ViewCellsTree::GetSize(ViewCell *vc) const
322{
323        int vcSize = 0;
324
325        stack<ViewCell *> tstack;
326
327        tstack.push(vc);
328
329        while (!tstack.empty())
330        {
331                ViewCell *vc = tstack.top();
332                tstack.pop();
333
334                if (vc->IsLeaf())
335                {
336                        ++ vcSize;
337                }
338                else
339                {
340                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
341                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
342                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
343                                tstack.push(*it);
344                       
345                }
346        }
347
348        return vcSize;
349}
350
351
352void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const
353{
354        stack<ViewCell *> tstack;
355
356        tstack.push(vc);
357
358        while (!tstack.empty())
359        {
360                ViewCell *vc = tstack.top();
361                tstack.pop();
362
363                if (vc->IsLeaf())
364                {
365                        leaves.push_back(vc);
366                }
367                else
368                {
369                        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(vc);
370                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
371                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
372                                tstack.push(*it);
373                       
374                }
375        }
376}
377
378
379ViewCellsTree::~ViewCellsTree()
380{
381        DEL_PTR(mRoot);
382}
383
384
385int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays,
386                                                                          const ObjectContainer &objects)
387{
388        // number of view cells equals the number of leaves
389        // (without the invalid ones )
390        //mNumViewCells = mBspStats.Leaves();//- mBspStats.invalidLeaves;
391        mNumViewCells = (int)mViewCellsManager->GetViewCells().size();
392
393        float variance = 0;
394        int totalPvs = 0;
395        float totalCost = 0;
396
397        //-- compute statistics values of initial view cells
398        mViewCellsManager->EvaluateRenderStatistics(totalCost,
399                                                                                                mExpectedCost,
400                                                                                                mDeviation,
401                                                                                                variance,
402                                                                                                totalPvs,
403                                                                                                mAvgRenderCost);
404
405
406        //-- fill merge queue
407        vector<MergeCandidate> candidates;
408
409        mViewCellsManager->CollectMergeCandidates(rays, candidates);
410        while(!candidates.empty())
411        {
412                MergeCandidate mc = candidates.back();
413                candidates.pop_back();
414                EvalMergeCost(mc);
415                mMergeQueue.push(mc);
416        }
417
418        Debug << "************************* merge ***********************************" << endl; 
419        Debug << "deviation: " << mDeviation << endl;
420        Debug << "avg render cost: " << mAvgRenderCost << endl;
421        Debug << "expected cost: " <<mExpectedCost << endl;
422
423
424        ViewCellsManager::PvsStatistics pvsStats;
425        mViewCellsManager->GetPvsStatistics(pvsStats);
426
427        static float expectedValue = pvsStats.avgPvs;
428       
429        // the current view cells are kept in this container
430        // we start with the current view cells from the
431        // view cell manager. They will change with
432        // subsequent merges
433        ViewCellContainer &viewCells = mViewCellsManager->GetViewCells();
434
435
436        ViewCell::NewMail();
437
438        MergeStatistics mergeStats;
439        mergeStats.Start();
440       
441        long startTime = GetTime();
442
443        mergeStats.collectTime = TimeDiff(startTime, GetTime());
444        mergeStats.candidates = (int)mMergeQueue.size();
445        startTime = GetTime();
446
447        // frequency stats are updated
448        const int statsOut = 100;
449
450        // passes are needed for statistics, because we don't want to record
451        // every merge
452        int pass = 0;
453        int mergedPerPass = 0;
454        float realExpectedCost = mExpectedCost;
455        float realAvgRenderCost = mAvgRenderCost;
456        int realNumViewCells = mNumViewCells;
457       
458        // maximal ratio of old expected render cost to expected render
459        // when the the render queue has to be reset.
460        float avgCostMaxDeviation;
461        int maxMergesPerPass;
462        int numActiveViewCells = 0;
463
464        environment->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", maxMergesPerPass);
465        environment->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", avgCostMaxDeviation);
466
467        cout << "actual merge starts now ... " << endl;
468       
469        //ResetMergeQueue();
470
471        //-- use priority queue to merge leaf pairs
472
473        while (!mMergeQueue.empty() && (realNumViewCells > mMergeMinViewCells) &&
474                   (mMergeQueue.top().GetRenderCost() < mMergeMaxCostRatio * totalCost))
475        {
476                //-- reset merge queue if the ratio of current expected cost / real expected cost
477                //   too small or after a given number of merges
478                if(0)
479                if ((mergedPerPass > maxMergesPerPass) ||
480                        (avgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
481                {
482                        Debug << "************ reset queue *****************\n"
483                                  << "ratios: " << avgCostMaxDeviation
484                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
485                                  << " merged per pass : " << mergedPerPass << " of maximal " << maxMergesPerPass << endl;
486
487                        Debug << "Values before reset: " 
488                                  << " erc: " << mExpectedCost
489                                  << " avgrc: " << mAvgRenderCost
490                                  << " dev: " << mDeviation << endl;
491       
492                        // adjust render cost
493                        ++ pass;
494
495                        mergedPerPass = 0;
496                        mExpectedCost = realExpectedCost;
497                        mAvgRenderCost = realAvgRenderCost;
498                        mNumViewCells = realNumViewCells;
499                       
500                        const int numActiveViewCells = UpdateMergedViewCells(viewCells);
501
502                    ResetMergeQueue();
503
504                       
505                        Debug << "Values after reset: " 
506                                  << " erc: " << mExpectedCost
507                                  << " avg: " << mAvgRenderCost
508                                  << " dev: " << mDeviation << endl;
509
510                        if (mExportMergedViewCells)
511                        {
512                                ExportMergedViewCells(viewCells, objects, numActiveViewCells);
513                        }
514                }
515
516#ifdef _DEBUG
517                Debug << "abs mergecost: " << mMergeQueue.top().GetMergeCost() <<
518                          << " rel mergecost: " << mMergeQueue.top().GetRenderCost() / mExpectedCost <<
519                          << " max ratio: " << mMergeMaxCostRatio << endl
520                          << " expected value: " << realExpectedCost << endl;
521#endif
522
523       
524                MergeCandidate mc = mMergeQueue.top();
525                mMergeQueue.pop();
526       
527                // both view cells equal!
528                if (mc.mLeftViewCell == mc.mRightViewCell)
529                        continue;
530
531                if (mc.IsValid())
532                {
533                        ViewCell::NewMail();
534                                               
535                        -- realNumViewCells;
536                        ++ mergeStats.merged;
537                        ++ mergedPerPass;
538
539
540                        //-- update statistical values
541
542                        // total render cost and deviation has changed
543                        // real expected cost will be larger than expected cost used for the
544                        // cost heuristics, but cannot recompute costs on each increase of the
545                        // expected cost
546
547                        totalCost += mc.GetRenderCost();
548                        mDeviation += mc.GetDeviationIncr();
549                                               
550                        realExpectedCost = totalCost / (float)realNumViewCells;
551                       
552                        const float currentMergeCost = mc.GetMergeCost();
553
554                        // merge the view cells of leaf1 and leaf2
555                        int pvsDiff;
556                        ViewCellInterior *mergedVc =
557                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
558
559                        totalPvs += pvsDiff;
560                        // set timestamp
561                        mergedVc->SetTimeStamp(mergeStats.merged);
562
563                        realAvgRenderCost = (float)totalPvs / (float)realNumViewCells;
564#if VC_HISTORY
565                        if (mc.mLeftViewCell->IsSibling(mc.mRightViewCell))
566                                ++ mergeStats.siblings;
567#endif
568                        if (((mergeStats.merged % statsOut) == 0) ||
569                                (realNumViewCells == mMergeMinViewCells))
570                        {
571                                cout << "merged " << mergeStats.merged << " view cells" << endl;
572
573                                mStats
574                                        << "#Pass\n" << pass << endl
575                                        << "#Merged\n" << mergeStats.merged << endl
576                                        << "#Viewcells\n" << realNumViewCells << endl
577                                        << "#CurrentCost\n" << currentMergeCost << endl
578                                        << "#RelativeCost\n" << currentMergeCost / mOverallCost << endl
579                                        << "#CurrentPvs\n" << mc.GetLeftViewCell()->GetPvs().GetSize() << endl
580                                        << "#MergedSiblings\n" << mergeStats.siblings << endl
581                                        << "#AvgTreeDist\n" << mergeStats.AvgTreeDist() << endl
582                                        << "#UsedExpectedCost\n" << mExpectedCost << endl
583                                        << "#RealExpectedCost\n" << realExpectedCost << endl
584                                        << "#RealAvgRenderCost\n" << realAvgRenderCost << endl
585                                        << "#AvgRenderCost\n" << mAvgRenderCost << endl
586                                        << "#expectedCostRatio\n" << mExpectedCost / realExpectedCost << endl
587                                        << "#Deviation\n" << mDeviation / (float)realNumViewCells << endl
588                                        << "#TotalDeviation\n" << mDeviation<< endl;
589                        }
590                }
591                else
592                {
593                        // merge candidate not valid, because one of the leaves was already
594                        // merged with another one => validate and reinsert into queue
595                        SetMergeCandidateValid(mc);
596                        mMergeQueue.push(mc);
597                }
598        }
599
600        // adjust stats and reset queue one final time
601        mExpectedCost = realExpectedCost;
602        mAvgRenderCost = realAvgRenderCost;
603        mNumViewCells = realNumViewCells;
604
605        UpdateMergedViewCells(viewCells);
606        ResetMergeQueue();
607
608
609        // create a root node if the merge was not done till root level,
610        // else take the single node as new root
611        if ((int)viewCells.size() > 1)
612        {
613                ViewCellInterior *root = new ViewCellInterior();
614
615                ViewCellContainer::const_iterator it, it_end = viewCells.end();
616                for (it = viewCells.begin(); it != it_end; ++ it)
617                        root->SetupChildLink(*it);
618
619                mRoot = root;
620        }
621        else if ((int)viewCells.size() == 1)
622        {
623                mRoot = viewCells[0];
624        }
625
626        mergeStats.expectedRenderCost = realExpectedCost;
627        mergeStats.deviation = mDeviation;
628
629        // we want to optimize this heuristics
630        mergeStats.heuristics =
631                mDeviation * (1.0f - mRenderCostWeight) +
632                mExpectedCost * mRenderCostWeight;
633
634        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
635        mergeStats.Stop();
636
637        Debug << mergeStats << endl << endl;
638
639
640        //TODO: should return sample contributions?
641        return mergeStats.merged;
642}
643
644
645void ViewCellsTree::ResetMergeQueue()
646{
647        cout << "reset merge queue ... ";
648       
649        vector<MergeCandidate> buf;
650        buf.reserve(mMergeQueue.size());
651                       
652       
653        // store merge candidates in intermediate buffer
654        while (!mMergeQueue.empty())
655        {
656                MergeCandidate mc = mMergeQueue.top();
657                mMergeQueue.pop();
658               
659                // recalculate cost
660                SetMergeCandidateValid(mc);
661                buf.push_back(mc);                             
662        }
663
664        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
665
666        // reinsert back into queue
667        for (bit = buf.begin(); bit != bit_end; ++ bit)
668        {     
669                mMergeQueue.push(*bit);
670        }
671
672        cout << "finished" << endl;
673}
674
675
676int ViewCellsTree::UpdateMergedViewCells(ViewCellContainer &viewCells)
677{
678        int numActiveViewCells = 0;
679
680        // find all already merged view cells and remove them from view cells
681        int i = 0;
682
683        while (1)
684        {
685                while (!viewCells.empty() && (!viewCells.back()->GetParent()))
686                {
687                        viewCells.pop_back();
688                }
689
690                // all merged view cells have been found
691                if (i >= viewCells.size())
692                        break;
693
694                // already merged view cell, put it to end of vector
695                if (!viewCells[i]->IsRoot())
696                        swap(viewCells[i], viewCells.back());
697               
698                ++ i;
699        }
700
701        // add new view cells to container only if they don't have been
702        // merged in the mean time
703        while (!mActiveViewCells.empty())
704        {
705                if (!mActiveViewCells.back()->GetParent())
706                {
707                        viewCells.push_back(mActiveViewCells.back());
708                        ++ numActiveViewCells;
709                }
710
711                mActiveViewCells.pop_back();
712        }
713
714        // update standard deviation
715        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
716       
717        mDeviation = 0;
718
719        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
720        {
721                int lower = mViewCellsManager->GetMinPvsSize();
722                int upper = mViewCellsManager->GetMaxPvsSize();
723                float penalty = EvalPvsPenalty((*vit)->GetPvs().GetSize(), lower, upper);
724               
725                mDeviation += fabs(mAvgRenderCost - penalty);
726        }
727
728        mDeviation /= (float)viewCells.size();
729
730        // clear the view cells which were merged
731        mInactiveViewCells.clear();
732        // remove the new view cells
733        mActiveViewCells.clear();
734
735        return numActiveViewCells;
736}
737
738
739void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
740                                                                                  const ObjectContainer &objects,
741                                                                                  const int numActiveViewCells)
742{
743       
744
745        char s[64];
746
747        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
748        Exporter *exporter = Exporter::GetExporter(s);
749
750        if (exporter)
751        {
752                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
753                exporter->ExportGeometry(objects);
754                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
755                ViewCellContainer::const_iterator it, it_end = viewCells.end();
756
757                int i = 0;
758                for (it = viewCells.begin(); it != it_end; ++ it)
759                {
760                        Material m;
761                        // assign special material to new view cells
762                        // new view cells are on the back of container
763                        if (i ++ >= (viewCells.size() - numActiveViewCells))
764                        {
765                                //m = RandomMaterial();
766                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
767                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
768                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
769                        }
770                        else
771                        {
772                                float col = RandomValue(0.1f, 0.4f);
773                                m.mDiffuseColor.r = col;
774                                m.mDiffuseColor.g = col;
775                                m.mDiffuseColor.b = col;
776                        }
777
778                        exporter->SetForcedMaterial(m);
779                        mViewCellsManager->ExportViewCellGeometry(exporter, *it);
780                }
781                delete exporter;
782                cout << "finished" << endl;
783        }
784}
785
786
787// TODO: should be done in view cells manager
788ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *l, ViewCell *r, int &pvsDiff) //const
789{
790        ViewCellInterior *vc = mViewCellsManager->MergeViewCells(*l, *r);
791
792        // if merge was unsuccessful
793        if (!vc) return NULL;
794
795        // set new size of view cell
796        if (mUseAreaForPvs)
797                vc->SetArea(l->GetArea() + l->GetArea());
798        else
799                vc->SetVolume(r->GetVolume() + r->GetVolume());
800       
801        // important so other merge candidates sharing this view cell
802        // are notified that the merge cost must be updated!!
803        vc->Mail();
804
805        const int pvs1 = l->GetPvs().GetSize();
806        const int pvs2 = r->GetPvs().GetSize();
807
808
809        //-- clean up old view cells
810        if (0 && !mExportMergedViewCells)
811        {
812                DEL_PTR(l);
813                DEL_PTR(r);
814        }
815        else
816        {
817                mInactiveViewCells.push_back(l);
818                mInactiveViewCells.push_back(r);
819               
820                mActiveViewCells.push_back(vc);
821        }
822
823        pvsDiff = vc->GetPvs().GetSize() - pvs1 - pvs2;
824
825        return vc;
826}
827
828
829
830
831int ViewCellsTree::RefineViewCells(const VssRayContainer &rays, const ObjectContainer &objects)
832{
833        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
834       
835        // Use priority queue of remaining leaf pairs
836        // The candidates either share the same view cells or
837        // are border leaves which share a boundary.
838        // We test if they can be shuffled, i.e.,
839        // either one leaf is made part of one view cell or the other
840        // leaf is made part of the other view cell. It is tested if the
841        // remaining view cells are "better" than the old ones.
842        //
843        // repeat the merging test numPasses times. For example, it could be
844        // that a shuffle only makes sense if another pair was shuffled before.
845        // Therefore we keep two queues and shift the merge candidates between
846        // those two queues until numPasses is reached
847       
848        queue<MergeCandidate> queue1;
849        queue<MergeCandidate> queue2;
850
851        queue<MergeCandidate> *shuffleQueue = &queue1;
852        queue<MergeCandidate> *backQueue = &queue2;
853
854        while (!mMergeQueue.empty())
855        {
856                MergeCandidate mc = mMergeQueue.top();
857                shuffleQueue->push(mc);
858                mMergeQueue.pop();
859        }
860
861        const int numPasses = 5;
862        int pass = 0;
863        int passShuffled = 0;
864        int shuffled = 0;
865        int shuffledViewCells = 0;
866
867        ViewCell::NewMail();
868       
869        do
870        {
871                passShuffled = 0;
872                while (!shuffleQueue->empty())
873                {
874                        MergeCandidate mc = shuffleQueue->front();
875                        shuffleQueue->pop();
876
877                        // both view cells equal or already shuffled
878                        if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
879                                (GetSize(mc.GetLeftViewCell()) == 1) ||
880                                (GetSize(mc.GetRightViewCell()) == 1))
881                        {                       
882                                continue;
883                        }
884
885                        // candidate for shuffling
886                        const bool wasShuffled =
887                                ShuffleLeaves(mc.GetLeftViewCell(), mc.GetRightViewCell());
888               
889                        // shuffled or put into other queue for further refine
890                        if (wasShuffled)
891                        {
892                                ++ passShuffled;
893
894                                if (!mc.GetLeftViewCell()->Mailed())
895                                {
896                                        mc.GetLeftViewCell()->Mail();
897                                        ++ shuffledViewCells;
898                                }
899                                if (!mc.GetRightViewCell()->Mailed())
900                                {
901                                        mc.GetRightViewCell()->Mail();
902                                        ++ shuffledViewCells;
903                                }
904                        }
905                        else
906                        {
907                                backQueue->push(mc);
908                        }
909                }
910
911                // now the back queue is the current shuffle queue
912                swap(shuffleQueue, backQueue);
913                shuffled += passShuffled;
914                Debug << "shuffled in pass: " << passShuffled << endl;
915        }
916        while (((++ pass) < numPasses) && passShuffled);
917
918        while (!shuffleQueue->empty())
919        {
920                shuffleQueue->pop();
921        }
922
923        return shuffledViewCells;
924}
925
926
927
928
929inline int AddedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
930{
931        return pvs1.AddPvs(pvs2);
932}
933
934
935// recomputes pvs size minus pvs of leaf l
936#if 0
937inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
938{
939        ObjectPvs pvs;
940        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
941        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
942                if (*it != l)
943                        pvs.AddPvs(*(*it)->mPvs);
944        return pvs.GetSize();
945}
946#endif
947
948
949// computes pvs1 minus pvs2
950inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
951{
952        return pvs1.SubtractPvs(pvs2);
953}
954
955
956float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
957                                                                         ViewCell *vc1,
958                                                                         ViewCell *vc2) const
959{
960        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
961        const int pvs1 = SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
962        const int pvs2 = AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
963
964        const int lowerPvsLimit = mViewCellsManager->GetMinPvsSize();
965        const int upperPvsLimit = mViewCellsManager->GetMaxPvsSize();
966
967        const float pvsPenalty1 =
968                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
969
970        const float pvsPenalty2 =
971                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
972
973
974        // don't shuffle leaves with pvs > max
975        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
976        {
977                return 1e20f;
978        }
979
980        float p1, p2;
981
982    if (mUseAreaForPvs)
983        {
984                p1 = vc1->GetArea() - leaf->GetArea();
985                p2 = vc2->GetArea() + leaf->GetArea();
986        }
987        else
988        {
989                p1 = vc1->GetVolume() - leaf->GetVolume();
990                p2 = vc2->GetVolume() + leaf->GetVolume();
991        }
992
993        const float renderCost1 = pvsPenalty1 * p1;
994        const float renderCost2 = pvsPenalty2 * p2;
995
996        float dev1, dev2;
997
998        if (1)
999        {
1000                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1001                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1002        }
1003        else
1004        {
1005                dev1 = fabs(mExpectedCost - renderCost1);
1006                dev2 = fabs(mExpectedCost - renderCost2);
1007        }
1008       
1009        return mRenderCostWeight * (renderCost1 + renderCost2) +
1010                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumViewCells;
1011}
1012
1013
1014void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
1015                                                                ViewCell *vc1,
1016                                                                ViewCell *vc2) const
1017{
1018        // compute new pvs and area
1019        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1020        vc2->GetPvs().AddPvs(leaf->GetPvs());
1021       
1022        if (mUseAreaForPvs)
1023        {
1024                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1025                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1026        }
1027        else
1028        {
1029                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1030                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1031        }
1032
1033        // TODO
1034#if VC_HISTORY
1035        /// add to second view cell
1036        vc2->mLeaves.push_back(leaf);
1037
1038        // erase leaf from old view cell
1039        vector<BspLeaf *>::iterator it = vc1->mLeaves.begin();
1040
1041        for (; *it != leaf; ++ it);
1042        vc1->mLeaves.erase(it);
1043
1044        /*vc1->GetPvs().mEntries.clear();
1045        for (; it != vc1->mLeaves.end(); ++ it)
1046        {
1047                if (*it == leaf)
1048                        vc1->mLeaves.erase(it);
1049                else
1050                        vc1->GetPvs().AddPvs(*(*it)->mPvs);
1051        }*/
1052
1053        leaf->SetViewCell(vc2); // finally change view cell
1054#endif
1055}
1056
1057
1058bool ViewCellsTree::ShuffleLeaves(ViewCell *l, ViewCell *r) const
1059{
1060        float cost1, cost2;
1061
1062        //-- first test if shuffling would decrease cost
1063        cost1 = GetCostHeuristics(l);
1064        cost2 = GetCostHeuristics(r);
1065
1066        const float oldCost = cost1 + cost2;
1067       
1068        float shuffledCost1 = Limits::Infinity;
1069        float shuffledCost2 = Limits::Infinity;
1070
1071        // the view cell should not be empty after the shuffle
1072#if VC_HISTORY
1073        shuffledCost1 = EvalShuffleCost(l, vc1, vc2);
1074        /shuffledCost2 = EvalShuffleCost(r, vc2, vc1);
1075
1076        // if cost of shuffle is less than old cost => shuffle
1077        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1078                return false;
1079       
1080       
1081        if (shuffledCost1 < shuffledCost2)
1082        {
1083                ShuffleLeaf(leaf1, vc1, vc2);
1084                leaf1->Mail();
1085        }
1086        else
1087        {
1088                ShuffleLeaf(leaf2, vc2, vc1);
1089                leaf2->Mail();
1090        }
1091#endif
1092        return true;
1093}
1094
1095
1096float ViewCellsTree::GetVariance(ViewCell *vc) const
1097{
1098        const int upper = mViewCellsManager->GetMaxPvsSize();
1099        const int lower = mViewCellsManager->GetMinPvsSize();
1100
1101        if (1)
1102        {
1103                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1104                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) / (float)mNumViewCells;
1105        }
1106
1107    const float leafCost = GetRenderCost(vc);
1108        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1109}
1110
1111
1112float ViewCellsTree::GetDeviation(ViewCell *vc) const
1113{
1114        const int upper = mViewCellsManager->GetMaxPvsSize();
1115        const int lower = mViewCellsManager->GetMinPvsSize();
1116
1117        if (1)
1118        {
1119                const float penalty = EvalPvsPenalty(vc->GetPvs().GetSize(), lower, upper);
1120                return fabs(mAvgRenderCost - penalty) / (float)mNumViewCells;
1121        }
1122
1123    const float renderCost = GetRenderCost(vc);
1124        return fabs(mExpectedCost - renderCost);
1125}
1126
1127
1128
1129float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1130{
1131        if (mUseAreaForPvs)
1132                return vc->GetPvs().GetSize() * vc->GetArea();
1133
1134        return vc->GetPvs().GetSize() * vc->GetVolume();
1135}
1136
1137
1138float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1139{
1140        return GetRenderCost(vc) * mRenderCostWeight +
1141                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1142}
1143
1144
1145void ViewCellsTree::SetMergeCandidateValid(MergeCandidate &mc) const
1146{
1147        while (mc.mLeftViewCell->mParent)
1148        {
1149                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1150        }
1151
1152        while (mc.mRightViewCell->mParent)
1153        {
1154                mc.mRightViewCell = mc.mRightViewCell->mParent;
1155        }
1156
1157        EvalMergeCost(mc);
1158}
1159
1160
1161void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1162{
1163        //-- compute pvs difference
1164        const int newPvs =
1165                ComputeMergedPvsSize(mc.mLeftViewCell->GetPvs(),
1166                                                         mc.mRightViewCell->GetPvs());
1167                       
1168        const float newPenalty =
1169                EvalPvsPenalty(newPvs,
1170                                           mViewCellsManager->GetMinPvsSize(),
1171                                           mViewCellsManager->GetMaxPvsSize());
1172
1173        ViewCell *vc1 = mc.mLeftViewCell;
1174        ViewCell *vc2 = mc.mRightViewCell;
1175
1176        //-- compute ratio of old cost
1177        //   (i.e., added size of left and right view cell times pvs size)
1178        //   to new rendering cost (i.e, size of merged view cell times pvs size)
1179        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1180
1181    const float newCost = mUseAreaForPvs ?
1182                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1183                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1184
1185
1186        // strong penalty if pvs size too large
1187        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1188        {
1189                mc.mRenderCost = 1e20f;
1190        }
1191        else
1192        {
1193                mc.mRenderCost = (newCost - oldCost) /
1194                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1195        }       
1196       
1197
1198        //-- merge cost also takes deviation into account
1199        float newDev, oldDev;
1200
1201        if (1)
1202                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumViewCells;
1203        else
1204                newDev = fabs(mExpectedCost - newCost) / (float)mNumViewCells;
1205       
1206        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1207
1208        // compute deviation increase
1209        mc.mDeviationIncr = newDev - oldDev;
1210       
1211        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1212        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1213}
1214
1215
1216void ViewCellsTree::CompressViewCellsPvs()
1217{
1218        stack<ViewCell *> tstack;
1219
1220
1221}
1222
1223
1224void  ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells, const int numViewCells)
1225{
1226        TraversalQueue tqueue;
1227
1228        while (!tqueue.empty())
1229        {
1230                ViewCell *vc = tqueue.top();
1231
1232                tqueue.pop();
1233        }
1234}
1235
1236
1237/**************************************************************************/
1238/*                     MergeCandidate implementation                      */
1239/**************************************************************************/
1240
1241
1242MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
1243mRenderCost(0),
1244mDeviationIncr(0),
1245mLeftViewCell(l),
1246mRightViewCell(r)
1247{
1248        //EvalMergeCost();
1249}
1250
1251
1252void MergeCandidate::SetRightViewCell(ViewCell *v)
1253{
1254        mRightViewCell = v;
1255}
1256
1257
1258void MergeCandidate::SetLeftViewCell(ViewCell *v)
1259{
1260        mLeftViewCell = v;
1261}
1262
1263
1264ViewCell *MergeCandidate::GetRightViewCell() const
1265{
1266        return mRightViewCell;
1267}
1268
1269
1270ViewCell *MergeCandidate::GetLeftViewCell() const
1271{
1272        return mLeftViewCell;
1273}
1274
1275
1276ViewCell *MergeCandidate::GetInitialRightViewCell() const
1277{
1278        return mInitialRightViewCell;
1279}
1280
1281
1282ViewCell *MergeCandidate::GetInitialLeftViewCell() const
1283{
1284        return mInitialLeftViewCell;
1285}
1286
1287
1288bool MergeCandidate::IsValid() const
1289{
1290        return !(mLeftViewCell->mParent && mRightViewCell->mParent);
1291}
1292
1293
1294float MergeCandidate::GetRenderCost() const
1295{
1296        return mRenderCost;
1297}
1298
1299
1300float MergeCandidate::GetDeviationIncr() const
1301{
1302        return mDeviationIncr;
1303}
1304
1305
1306float MergeCandidate::GetMergeCost() const
1307{
1308        return mRenderCost * sRenderCostWeight +
1309                   mDeviationIncr * (1.0f - sRenderCostWeight);
1310}
1311
1312
1313/************************************************************************/
1314/*                    MergeStatistics implementation                    */
1315/************************************************************************/
1316
1317
1318void MergeStatistics::Print(ostream &app) const
1319{
1320        app << "===== Merge statistics ===============\n";
1321
1322        app << setprecision(4);
1323
1324        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
1325
1326        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
1327
1328        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
1329
1330        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
1331
1332        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
1333
1334        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
1335
1336        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
1337
1338        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
1339
1340        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
1341
1342        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
1343
1344        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
1345
1346        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
1347
1348        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
1349       
1350
1351        app << "===== END OF BspTree statistics ==========\n";
1352}
Note: See TracBrowser for help on using the repository browser.