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

Revision 2575, 64.4 KB checked in by bittner, 17 years ago (diff)

big merge: preparation for havran ray caster, check if everything works

RevLine 
[1010]1#include <time.h>
2#include <iomanip>
3#include <stack>
4
[2575]5#include "Material.h"
[235]6#include "ViewCell.h"
7#include "Mesh.h"
[308]8#include "Intersectable.h"
[1121]9#include "KdTree.h"
[235]10#include "Triangle3.h"
[580]11#include "common.h"
12#include "Environment.h"
13#include "ViewCellsManager.h"
14#include "Exporter.h"
[1614]15#include "BvHierarchy.h"
[2575]16
17#ifdef PERFTIMER 
[2544]18#include "Timer/PerfTimer.h"
[2575]19#endif
[580]20
[863]21namespace GtpVisibilityPreprocessor {
[580]22
23
[2539]24#define TYPE_INTERIOR -2
25#define TYPE_LEAF -3
[955]26
[2575]27#ifdef PERFTIMER 
[2544]28static PerfTimer sPvsTimer;
29static PerfTimer sSearchTimer;
[2575]30#endif
[2539]31
32static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
33{
34        return obj1->mId < obj2->mId;
35}
36
37
[580]38template <typename T> class myless
39{
40public:
41        bool operator() (T v1, T v2) const
42        {
[600]43                return (v1->GetMergeCost() < v2->GetMergeCost());
[580]44        }
45};
46
47
[1121]48typedef priority_queue<ViewCell *, vector<ViewCell *>,
[2575]49                       myless<vector<ViewCell *>::value_type> > TraversalQueue;
[580]50
[2575]51int Intersectable::sMailId = 10000;//2147483647;
52int Intersectable::sReservedMailboxes = 1;
[580]53
54float MergeCandidate::sRenderCostWeight = 0;
55
56
57// pvs penalty can be different from pvs size
[1709]58inline static float EvalPvsPenalty(const float pvs,
[2575]59                                   const float lower,
60                                   const float upper)
[580]61{
62        // clamp to minmax values
[728]63        if (pvs < lower)
[580]64                return (float)lower;
65        if (pvs > upper)
66                return (float)upper;
[752]67
[580]68        return (float)pvs;
69}
70
[1586]71/** Counts contribution of the view cell to the pvs.
72*/
73inline int CountPvsContribution(ViewCell *vc)
[585]74{
75        int count = 0;
76
[1742]77        ObjectPvsIterator pit = vc->GetPvs().GetIterator();
78
79        while (pit.HasMoreEntries())
[585]80        {
[2117]81                Intersectable *obj = pit.Next();
[1742]82
[2117]83                if (!obj->Mailed())
[585]84                {
[2117]85                        obj->Mail();
[585]86                        ++ count;
87                }
88        }
89
90        return count;
91}
92
[1233]93
[729]94/// Fast computation of merged pvs size
[1742]95static float ComputeMergedPvsCost(const ObjectPvs &pvs1,
96                                                                  const ObjectPvs &pvs2)
[580]97{
[729]98        // add first pvs
[1709]99        float pvs = (float)pvs1.GetSize();
[580]100
101        Intersectable::NewMail();
102
[729]103        // mail all objects in first pvs
[1742]104        ObjectPvsIterator pit = pvs1.GetIterator();
105
106        while (pit.HasMoreEntries())
[580]107        {
[2117]108                pit.Next()->Mail();
[580]109        }
110
[1742]111        pit = pvs2.GetIterator();
[580]112
[1742]113        while (pit.HasMoreEntries())
[580]114        {
[2117]115                if (!pit.Next()->Mailed())
[580]116                        ++ pvs;
117        }
118
119        return pvs;
120}
121
122
[478]123ViewCell::ViewCell():
124MeshInstance(NULL),
[551]125mArea(-1),
126mVolume(-1),
[580]127mValid(true),
128mParent(NULL),
[600]129mMergeCost(0),
[1709]130mPvsCost(0),
[1160]131mEntriesInPvs(0),
[1877]132mPvsSizeValid(false),
[2560]133mFilteredPvsSize(0),
134mNumPiercingRays(0)
[265]135{
[1570]136        mId = -100;
[265]137}
[235]138
[2539]139
[478]140ViewCell::ViewCell(Mesh *mesh):
141MeshInstance(mesh),
[551]142mArea(-1),
143mVolume(-1),
[580]144mValid(true),
145mParent(NULL),
[600]146mMergeCost(0),
[1709]147mPvsCost(0),
[1877]148mPvsSizeValid(false),
[2560]149mFilteredPvsSize(0),
150mNumPiercingRays(0)
[372]151{
[1570]152        mId = -100;
[372]153}
154
[503]155
[1551]156ViewCell::~ViewCell()
157{
158}
159
160
[469]161const ObjectPvs &ViewCell::GetPvs() const
[419]162{
[2569]163        return mPvs;
[419]164}
165
[752]166
[469]167ObjectPvs &ViewCell::GetPvs()
[372]168{
[2569]169        return mPvs;
[372]170}
171
[503]172
[2569]173ObjectPvs ViewCell::CopyPvs()
174{
175        return mPvs;
176}
177
178
[880]179void ViewCell::SetPvs(const ObjectPvs &pvs)
180{
181        mPvs = pvs;
182}
183
184
[235]185int ViewCell::Type() const
186{
[308]187        return VIEW_CELL;
[235]188}
189
[503]190
191void ViewCell::SetMesh(Mesh *mesh)
192{
193        mMesh = mesh;
194}
195
196
[752]197void ViewCell::SetColor(const RgbColor &color)
198{
199        mColor = color;
200}
201
202
203RgbColor ViewCell::GetColor() const
204{
205        return mColor;
206}
207
208
[547]209void ViewCell::SetValid(const bool valid)
210{
[564]211        mValid = valid;
[547]212}
213
214
215bool ViewCell::GetValid() const
216{
217        return mValid;
218}
219
220
[580]221void ViewCell::SetParent(ViewCellInterior *parent)
222{
223        mParent = parent;
224}
225
226
227bool ViewCell::IsRoot() const
228{
229        return !mParent;
230}
231
232
233ViewCellInterior *ViewCell::GetParent() const
234{
235        return mParent;
236}
237
238
[600]239void ViewCell::SetMergeCost(const float mergeCost)
[580]240{
[600]241        mMergeCost = mergeCost;
[580]242}
243
244
[728]245float ViewCell::GetRenderCost() const
246{
[1709]247        return mPvsCost * GetVolume();
[728]248}
249
250
[600]251float ViewCell::GetMergeCost() const
[580]252{
[600]253        return mMergeCost;
[580]254}
255
[1002]256
257bool ViewCell::AddPvsSample(Intersectable *sample,
258                                                        const float pdf,
259                                                        float &contribution)
[1772]260{
[2124]261        const bool result = mPvs.AddSample(sample, pdf);
[2210]262        // we have to recompute pvs size
[1586]263        mPvsSizeValid = false;
[1002]264
265        return result;
266}
267
268
[1133]269
[462]270/************************************************************************/
[580]271/*                class ViewCellInterior implementation                 */
272/************************************************************************/
273
274
275ViewCellInterior::ViewCellInterior()
276{
277}
278
279
280ViewCellInterior::~ViewCellInterior()
281{
282        ViewCellContainer::const_iterator it, it_end = mChildren.end();
283
284        for (it = mChildren.begin(); it != it_end; ++ it)
[1545]285        {
[580]286                delete (*it);
[1545]287        }
[580]288}
289
290
291ViewCellInterior::ViewCellInterior(Mesh *mesh):
292ViewCell(mesh)
293{
294}
295
296
297bool ViewCellInterior::IsLeaf() const
298{
299        return false;
300}
301
302
[650]303void ViewCellInterior::SetupChildLink(ViewCell *vc)
[580]304{
[650]305    mChildren.push_back(vc);
[1002]306    vc->SetParent(this);
[580]307}
308
309
[586]310void ViewCellInterior::RemoveChildLink(ViewCell *l)
311{
312        // erase leaf from old view cell
313        ViewCellContainer::iterator it = mChildren.begin();
[580]314
[586]315        for (; (*it) != l; ++ it);
316        if (it == mChildren.end())
317                Debug << "error" << endl;
318        else
319                mChildren.erase(it);
320}
321
[703]322
[1286]323void ViewCellInterior::ReplaceChildLink(ViewCell *prev, ViewCell *cur)
324{
325        // erase leaf from old view cell
326        ViewCellContainer::iterator it = mChildren.begin();
[2539]327        for (; (*it) != prev; ++ it);
[1286]328
329        if (it == mChildren.end())
330                Debug << "error: child link not found" << endl;
331        else
332                (*it) = cur;
333}
334
335
[1551]336
[580]337/************************************************************************/
[462]338/*                class ViewCellsStatistics implementation              */
339/************************************************************************/
340
[580]341
[463]342void ViewCellsStatistics::Print(ostream &app) const
343{
344        app << "=========== View Cells Statistics ===============\n";
345
346        app << setprecision(4);
347
348        //app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
349
[1709]350        app << "#N_OVERALLPVS ( cost of the PVS )\n" << pvsCost << endl;
[463]351
[1709]352        //app << "#N_PVSENTRIES ( entries in the PVS)\n" << pvsEntries << endl;
353
[463]354        app << "#N_PMAXPVS ( largest PVS )\n" << maxPvs << endl;
355
356        app << "#N_PMINPVS ( smallest PVS )\n" << minPvs << endl;
357
358        app << "#N_PAVGPVS ( average PVS )\n" << AvgPvs() << endl;
359
[485]360        app << "#N_PEMPTYPVS ( view cells with empty PVS )\n" << emptyPvs << endl;
[463]361
362        app << "#N_VIEWCELLS ( number of view cells)\n" << viewCells << endl;
363
364        app << "#N_AVGLEAVES (average number of leaves per view cell )\n" << AvgLeaves() << endl;
365
366        app << "#N_MAXLEAVES ( maximal number of leaves per view cell )\n" << maxLeaves << endl;
367       
[564]368        app << "#N_INVALID ( number of invalid view cells )\n" << invalid << endl;
369
[463]370        app << "========== End of View Cells Statistics ==========\n";
[580]371}
372
373
374/*************************************************************************/
375/*                    class ViewCellsTree implementation                 */
376/*************************************************************************/
377
378
[1004]379ViewCellsTree::ViewCellsTree(ViewCellsManager *vcm):
[580]380mRoot(NULL),
381mUseAreaForPvs(false),
[584]382mViewCellsManager(vcm),
[752]383#if 0
384mViewCellsStorage(PVS_IN_INTERIORS)
385#else
386mViewCellsStorage(PVS_IN_LEAVES)
387#endif
[580]388{
[1264]389        ReadEnvironment();
390        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
391}
392
393
394ViewCellsTree::ViewCellsTree():
395mRoot(NULL),
396mUseAreaForPvs(false),
397mViewCellsManager(NULL),
398#if 0
399mViewCellsStorage(PVS_IN_INTERIORS)
400#else
401mViewCellsStorage(PVS_IN_LEAVES)
402#endif
403{
404        ReadEnvironment();
405        MergeCandidate::sRenderCostWeight = mRenderCostWeight;
406}
407
408
409void ViewCellsTree::ReadEnvironment()
410{
[1004]411        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportMergedViewCells", mExportMergedViewCells);
412        Environment::GetSingleton()->GetFloatValue("ViewCells.maxStaticMemory", mMaxMemory);
[580]413
414        //-- merge options
[1004]415        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.renderCostWeight", mRenderCostWeight);
416        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.minViewCells", mMergeMinViewCells);
417        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.maxCostRatio", mMergeMaxCostRatio);
418        Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.refine", mRefineViewCells);   
[582]419
[1004]420        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", mMaxMergesPerPass);
421        Environment::GetSingleton()->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", mAvgCostMaxDeviation);
[586]422
[938]423        Debug << "============= view cell tree options ================\n";
[582]424        Debug << "minimum view cells: " << mMergeMinViewCells << endl;
425        Debug << "max cost ratio: " << mMergeMaxCostRatio << endl;
426        Debug << "max memory: " << mMaxMemory << endl;
[586]427        Debug << "refining view cells: " << mRefineViewCells << endl;
[1027]428        Debug << "=========== end view cell tree options ===============\n";
[580]429}
430
431
[582]432// return memory usage in MB
433float ViewCellsTree::GetMemUsage() const
434{
[752]435        // TODO
[582]436        return 0;
437                /*(sizeof(ViewCellsTree) +
438                 mBspStats.Leaves() * sizeof(BspLeaf) +
439                 mBspStats.Interior() * sizeof(BspInterior) +
440                 mBspStats.accumRays * sizeof(RayInfo)) / (1024.0f * 1024.0f);*/
441}
442
443
[736]444int ViewCellsTree::GetNumInitialViewCells(ViewCell *vc) const
[580]445{
446        int vcSize = 0;
447
448        stack<ViewCell *> tstack;
449        tstack.push(vc);
450
451        while (!tstack.empty())
452        {
453                ViewCell *vc = tstack.top();
454                tstack.pop();
455
456                if (vc->IsLeaf())
457                {
458                        ++ vcSize;
459                }
460                else
461                {
[2017]462                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[580]463                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1233]464                       
[580]465                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[1233]466                        {
[580]467                                tstack.push(*it);
[1233]468                        }
[580]469                }
470        }
471
472        return vcSize;
473}
474
475
476void ViewCellsTree::CollectLeaves(ViewCell *vc, ViewCellContainer &leaves) const
477{
478        stack<ViewCell *> tstack;
479
480        tstack.push(vc);
481
482        while (!tstack.empty())
483        {
484                ViewCell *vc = tstack.top();
485                tstack.pop();
486
487                if (vc->IsLeaf())
488                {
489                        leaves.push_back(vc);
490                }
491                else
492                {
[2017]493                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[580]494                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[664]495
[580]496                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[664]497                        {
[580]498                                tstack.push(*it);
[664]499                        }
[580]500                }
501        }
502}
503
504
505ViewCellsTree::~ViewCellsTree()
[2003]506{
[580]507        DEL_PTR(mRoot);
508}
509
510
511int ViewCellsTree::ConstructMergeTree(const VssRayContainer &rays,
512                                                                          const ObjectContainer &objects)
513{
[582]514        mNumActiveViewCells = (int)mViewCellsManager->GetViewCells().size();
[580]515
516        float variance = 0;
[1709]517        float totalPvs = 0;
[600]518        float totalRenderCost = 0;
[580]519
[1786]520        //////////////////
[580]521        //-- compute statistics values of initial view cells
[1786]522
[600]523        mViewCellsManager->EvaluateRenderStatistics(totalRenderCost,
[580]524                                                                                                mExpectedCost,
525                                                                                                mDeviation,
526                                                                                                variance,
527                                                                                                totalPvs,
528                                                                                                mAvgRenderCost);
529
[1786]530        /////////////
[580]531        //-- fill merge queue
[2210]532
[580]533        vector<MergeCandidate> candidates;
534
535        mViewCellsManager->CollectMergeCandidates(rays, candidates);
[703]536
[580]537        while(!candidates.empty())
538        {
539                MergeCandidate mc = candidates.back();
540                candidates.pop_back();
541                EvalMergeCost(mc);
542                mMergeQueue.push(mc);
543        }
544
[2210]545        Debug << "********************** merge ******************************" << endl; 
[580]546        Debug << "deviation: " << mDeviation << endl;
547        Debug << "avg render cost: " << mAvgRenderCost << endl;
[600]548        Debug << "expected cost: " << mExpectedCost << endl;
[580]549
550
551        ViewCellsManager::PvsStatistics pvsStats;
552        mViewCellsManager->GetPvsStatistics(pvsStats);
553
[605]554        //static float expectedValue = pvsStats.avgPvs;
[580]555       
[881]556        //-- the current view cells are kept in this container
557        //-- we start with the current view cells from the view cell manager.
558        //-- The active view cells will change with subsequent merges
[752]559       
[720]560        // todo: should rather take initial view cells
561    ViewCellContainer &activeViewCells = mViewCellsManager->GetViewCells();
562       
[752]563       
[580]564        ViewCell::NewMail();
565
566        MergeStatistics mergeStats;
567        mergeStats.Start();
568       
569        long startTime = GetTime();
570
571        mergeStats.collectTime = TimeDiff(startTime, GetTime());
572        mergeStats.candidates = (int)mMergeQueue.size();
573        startTime = GetTime();
574
575        // frequency stats are updated
[650]576        const int statsOut = 500;
[734]577       
[580]578        // passes are needed for statistics, because we don't want to record
579        // every merge
580        int pass = 0;
581        int mergedPerPass = 0;
582        float realExpectedCost = mExpectedCost;
583        float realAvgRenderCost = mAvgRenderCost;
[582]584        int realNumActiveViewCells = mNumActiveViewCells;
[580]585       
586        // maximal ratio of old expected render cost to expected render
587        // when the the render queue has to be reset.
[582]588        int numMergedViewCells = 0;
[938]589               
[580]590
591        cout << "actual merge starts now ... " << endl;
[604]592
[580]593        //-- use priority queue to merge leaf pairs
[612]594
[881]595        while (!mMergeQueue.empty())
[580]596        {
597                //-- reset merge queue if the ratio of current expected cost / real expected cost
598                //   too small or after a given number of merges
[938]599                if ((mergedPerPass > mMaxMergesPerPass) ||
600                        (mAvgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
[580]601                {
602                        Debug << "************ reset queue *****************\n"
[938]603                                  << "ratios: " << mAvgCostMaxDeviation
[580]604                                  << " real avg render cost " << realAvgRenderCost << " average render cost " << mAvgRenderCost
[938]605                                  << " merged per pass : " << mergedPerPass << " of maximal " << mMaxMergesPerPass << endl;
[580]606
607                        Debug << "Values before reset: " 
608                                  << " erc: " << mExpectedCost
609                                  << " avgrc: " << mAvgRenderCost
610                                  << " dev: " << mDeviation << endl;
611       
612                        // adjust render cost
613                        ++ pass;
614
615                        mergedPerPass = 0;
616                        mExpectedCost = realExpectedCost;
617                        mAvgRenderCost = realAvgRenderCost;
[582]618                        mNumActiveViewCells = realNumActiveViewCells;
[580]619                       
[582]620                        const int numMergedViewCells = UpdateActiveViewCells(activeViewCells);
621               
[1603]622                        /////////////////
623                        //-- reset / refine the view cells
[720]624                        //-- priorities are recomputed
625                        //-- the candidates are put back into merge queue
[1603]626
[586]627                        if (mRefineViewCells)
628                                RefineViewCells(rays, objects);
629                        else
630                                ResetMergeQueue();
[580]631
632                        Debug << "Values after reset: " 
633                                  << " erc: " << mExpectedCost
634                                  << " avg: " << mAvgRenderCost
635                                  << " dev: " << mDeviation << endl;
636
637                        if (mExportMergedViewCells)
638                        {
[582]639                                ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
[580]640                        }
641                }
642
643
644                MergeCandidate mc = mMergeQueue.top();
645                mMergeQueue.pop();
646       
[710]647                // both view cells equal because of previous merges
[582]648                // NOTE: do I really still need this? probably cannot happen!!
[580]649                if (mc.mLeftViewCell == mc.mRightViewCell)
650                        continue;
651
652                if (mc.IsValid())
653                {
654                        ViewCell::NewMail();
[600]655
656                        //-- update statistical values
[582]657                        -- realNumActiveViewCells;
[580]658                        ++ mergeStats.merged;
659                        ++ mergedPerPass;
660
[600]661                        const float renderCostIncr = mc.GetRenderCost();
662                        const float mergeCostIncr = mc.GetMergeCost();
[580]663
[600]664                        totalRenderCost += renderCostIncr;
[580]665                        mDeviation += mc.GetDeviationIncr();
[2210]666                       
667                        ///////////
668                        //-- merge the view cells of leaf1 and leaf2
[710]669
[1709]670                        float pvsDiff;
[580]671                        ViewCellInterior *mergedVc =
[1709]672                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);   
[580]673
[600]674                        // total render cost and deviation has changed
675                        // real expected cost will be larger than expected cost used for the
676                        // cost heuristics, but cannot recompute costs on each increase of the
677                        // expected cost
[580]678                        totalPvs += pvsDiff;
[600]679                        realExpectedCost = totalRenderCost / (float)realNumActiveViewCells;
680                        realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
681       
[801]682                        // set merge cost to this node for priority traversal
[837]683                        mergedVc->SetMergeCost(totalRenderCost);
684                       
685                        // check if "siblings (back and front node of the same parent)
[1706]686                        if (0) ++ mergeStats.siblings;
687
688                        // set the cost for rendering a view cell
[608]689                        mergedVc->SetCost(realExpectedCost);
[607]690
[650]691                        if ((mergeStats.merged % statsOut) == 0)
[580]692                                cout << "merged " << mergeStats.merged << " view cells" << endl;
693
694                }
695                else
696                {
697                        // merge candidate not valid, because one of the leaves was already
698                        // merged with another one => validate and reinsert into queue
[582]699                        if (ValidateMergeCandidate(mc))
700                        {
701                                EvalMergeCost(mc);
702                                mMergeQueue.push(mc);
703                        }
[580]704                }
[612]705               
[580]706        }
707
708        // adjust stats and reset queue one final time
709        mExpectedCost = realExpectedCost;
710        mAvgRenderCost = realAvgRenderCost;
[582]711        mNumActiveViewCells = realNumActiveViewCells;
[580]712
[582]713        UpdateActiveViewCells(activeViewCells);
[580]714
[586]715        // refine view cells and reset costs
716        if (mRefineViewCells)
717                RefineViewCells(rays, objects);
718        else
719                ResetMergeQueue();
720
[708]721
[580]722        // create a root node if the merge was not done till root level,
723        // else take the single node as new root
[582]724        if ((int)activeViewCells.size() > 1)
[580]725        {
[587]726                Debug << "creating root of view cell hierarchy for "
727                          << (int)activeViewCells.size() << " view cells" << endl;
[612]728               
[582]729                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
[710]730       
731                ViewCellContainer::const_iterator it, it_end = root->mChildren.end();
732
733                for (it = root->mChildren.begin(); it != it_end; ++ it)
734                        (*it)->SetParent(root);
735       
[600]736                root->SetMergeCost(totalRenderCost);
[608]737                // $$JB keep this 0 temporarilly
738                root->SetCost(0.0f);
[612]739
[580]740                mRoot = root;
741        }
[710]742        // normal case
743        else if (!activeViewCells.empty())
[580]744        {
[582]745                Debug << "setting root of the merge history" << endl;
746                mRoot = activeViewCells[0];
[580]747        }
[752]748        else
749        {
750                Debug << "big error, root is NULL" << endl;
751        }
[708]752       
[644]753        //-- empty merge queue just in case
[600]754        while (!mMergeQueue.empty())
755        {
756                mMergeQueue.pop();
757        }
[837]758
[1706]759        // test if computed volumes are correct
760        Debug << "volume of the root view cell: " << mRoot->GetVolume()
761                  << " " << mViewCellsManager->GetViewSpaceBox().GetVolume() << endl;
[837]762       
763        // TODO: delete because makes no sense here
[580]764        mergeStats.expectedRenderCost = realExpectedCost;
765        mergeStats.deviation = mDeviation;
766
767        // we want to optimize this heuristics
768        mergeStats.heuristics =
769                mDeviation * (1.0f - mRenderCostWeight) +
770                mExpectedCost * mRenderCostWeight;
771
772        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
773        mergeStats.Stop();
774        Debug << mergeStats << endl << endl;
775
[608]776        // assign colors for the view cells so that at least one is always consistent
777        AssignRandomColors();
[708]778
[580]779        //TODO: should return sample contributions?
780        return mergeStats.merged;
781}
782
783
[584]784ViewCell *ViewCellsTree::GetRoot() const
[581]785{
786        return mRoot;
787}
788
789
[580]790void ViewCellsTree::ResetMergeQueue()
791{
792        cout << "reset merge queue ... ";
793       
794        vector<MergeCandidate> buf;
795        buf.reserve(mMergeQueue.size());
796                       
797       
798        // store merge candidates in intermediate buffer
799        while (!mMergeQueue.empty())
800        {
801                MergeCandidate mc = mMergeQueue.top();
802                mMergeQueue.pop();
803               
804                // recalculate cost
[582]805                if (ValidateMergeCandidate(mc))
806                {
807                        EvalMergeCost(mc);
808                        buf.push_back(mc);                             
809                }
[580]810        }
811
812        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
813
814        // reinsert back into queue
815        for (bit = buf.begin(); bit != bit_end; ++ bit)
816        {     
817                mMergeQueue.push(*bit);
818        }
819
820        cout << "finished" << endl;
821}
822
823
[1002]824float ViewCellsTree::ComputeMergedPvsCost(const ObjectPvs &pvs1,
825                                                                                  const ObjectPvs &pvs2) const
826{
827        // computes render cost of merge
828        float renderCost = 0;
829
830        // compute new pvs size
831        Intersectable::NewMail();
832
[1742]833        ObjectPvsIterator pit = pvs1.GetIterator();
834
[1002]835        // first mail all objects in first pvs
[1742]836        while (pit.HasMoreEntries())
[1002]837        {
[2117]838                Intersectable *obj = pit.Next();
[1002]839
840                obj->Mail();
[2332]841                renderCost ++;
[1002]842        }
843
[1742]844        ObjectPvsIterator pit2 = pvs2.GetIterator();
[1002]845
[1742]846        while (pit2.HasMoreEntries())
[1002]847        {
[2117]848                Intersectable *obj = pit2.Next();
849               
[1002]850                // test if object already considered   
851                if (!obj->Mailed())
852                {
[2332]853                        renderCost ++;
[1002]854                }
855        }
856
857        return renderCost;
858}
859
860
[582]861int ViewCellsTree::UpdateActiveViewCells(ViewCellContainer &viewCells)
[580]862{
[582]863        int numMergedViewCells = 0;
[580]864
[584]865        Debug << "updating active vc: " << (int)viewCells.size() << endl;
[1141]866       
867        // find all already merged view cells and remove them from the
868        // container view cells
[582]869               
870        // sort out all view cells which are not active anymore, i.e., they
871        // were already part of a merge
[580]872        int i = 0;
873
[582]874        ViewCell::NewMail();
875
[580]876        while (1)
877        {
[582]878                // remove all merged view cells from end of the vector
879                while (!viewCells.empty() && (viewCells.back()->GetParent()))
[580]880                {
881                        viewCells.pop_back();
882                }
883
884                // all merged view cells have been found
[710]885                if (i >= (int)viewCells.size())
[580]886                        break;
887
[710]888                // already merged this view cell, put it to end of vector
[582]889                if (viewCells[i]->GetParent())
[580]890                        swap(viewCells[i], viewCells.back());
891               
[752]892                // mail view cell that it has not been merged
[710]893                viewCells[i]->Mail();
894
895                // increase loop counter
896                ++ i;
[580]897        }
898
[582]899
[580]900        // add new view cells to container only if they don't have been
901        // merged in the mean time
[582]902        ViewCellContainer::const_iterator ait, ait_end = mMergedViewCells.end();
[752]903
[582]904        for (ait = mMergedViewCells.begin(); ait != ait_end; ++ ait)
[580]905        {
[582]906                ViewCell *vc = mMergedViewCells.back();
907                if (!vc->GetParent() && !vc->Mailed())
[580]908                {
[582]909                        vc->Mail();
910                        viewCells.push_back(vc);
911                        ++ numMergedViewCells;
[580]912                }
913        }
914
[752]915        // dispose old merged view cells
[582]916        mMergedViewCells.clear();
917
[580]918        // update standard deviation
919        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
920       
921        mDeviation = 0;
922
923        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
924        {
[1709]925                const float lower = (float)mViewCellsManager->GetMinPvsSize();
926                const float upper = (float)mViewCellsManager->GetMaxPvsSize();
[752]927
[1707]928                const float penalty = EvalPvsPenalty((*vit)->GetPvs().EvalPvsCost(), lower, upper);
[580]929               
930                mDeviation += fabs(mAvgRenderCost - penalty);
931        }
932
933        mDeviation /= (float)viewCells.size();
[582]934       
935        return numMergedViewCells;
[580]936}
937
938
939void ViewCellsTree::ExportMergedViewCells(ViewCellContainer &viewCells,
940                                                                                  const ObjectContainer &objects,
[582]941                                                                                  const int numMergedViewCells)
[580]942{
943       
944
945        char s[64];
946
947        sprintf(s, "merged_viewcells%07d.x3d", (int)viewCells.size());
948        Exporter *exporter = Exporter::GetExporter(s);
949
950        if (exporter)
951        {
952                cout << "exporting " << (int)viewCells.size() << " merged view cells ... ";
953                exporter->ExportGeometry(objects);
954                //Debug << "vc size " << (int)viewCells.size() << " merge queue size: " << (int)mMergeQueue.size() << endl;
955                ViewCellContainer::const_iterator it, it_end = viewCells.end();
956
957                int i = 0;
958                for (it = viewCells.begin(); it != it_end; ++ it)
959                {
960                        Material m;
961                        // assign special material to new view cells
962                        // new view cells are on the back of container
[582]963                        if (i ++ >= (viewCells.size() - numMergedViewCells))
[580]964                        {
965                                //m = RandomMaterial();
966                                m.mDiffuseColor.r = RandomValue(0.5f, 1.0f);
967                                m.mDiffuseColor.g = RandomValue(0.5f, 1.0f);
968                                m.mDiffuseColor.b = RandomValue(0.5f, 1.0f);
969                        }
970                        else
971                        {
972                                float col = RandomValue(0.1f, 0.4f);
973                                m.mDiffuseColor.r = col;
974                                m.mDiffuseColor.g = col;
975                                m.mDiffuseColor.b = col;
976                        }
977
978                        exporter->SetForcedMaterial(m);
[1416]979                        mViewCellsManager->ExportViewCellGeometry(exporter, *it, NULL, NULL);
[580]980                }
[1416]981
[580]982                delete exporter;
983                cout << "finished" << endl;
984        }
985}
986
987
988// TODO: should be done in view cells manager
[1141]989ViewCellInterior *ViewCellsTree::MergeViewCells(ViewCell *left,
990                                                                                                ViewCell *right,
[1709]991                                                                                                float &pvsDiff) //const
[580]992{
[1141]993        // create merged view cell
994        ViewCellInterior *vc =
995                mViewCellsManager->MergeViewCells(left, right);
[580]996
997        // if merge was unsuccessful
998        if (!vc) return NULL;
999
[752]1000        // set to the new parent view cell
[1141]1001        left->SetParent(vc);
1002        right->SetParent(vc);
[710]1003
[1141]1004       
[580]1005        if (mUseAreaForPvs)
[710]1006        {
[1141]1007                // set new area of view cell
1008                // not not correct, but costly to compute real area!!
1009                vc->SetArea(left->GetArea() + right->GetArea());
[710]1010        }
[580]1011        else
[1141]1012        {       // set new volume of view cell
1013                vc->SetVolume(left->GetVolume() + right->GetVolume());
[602]1014        }
[710]1015
1016       
[580]1017        // important so other merge candidates sharing this view cell
1018        // are notified that the merge cost must be updated!!
1019        vc->Mail();
1020
[1707]1021        const float pvs1 = left->GetPvs().EvalPvsCost();
1022        const float pvs2 = right->GetPvs().EvalPvsCost();
[580]1023
1024
[1141]1025        // the new view cells are stored in this container
[582]1026        mMergedViewCells.push_back(vc);
[580]1027
[1707]1028        pvsDiff = vc->GetPvs().EvalPvsCost() - pvs1 - pvs2;
[580]1029
[752]1030
[1141]1031        // don't store pvs in interior cells, just a scalar
[752]1032        if (mViewCellsStorage == PVS_IN_LEAVES)
1033        {
[1168]1034                // set scalars
1035                mViewCellsManager->UpdateScalarPvsSize(left,
[1707]1036                                left->GetPvs().EvalPvsCost(),
[1586]1037                                left->GetPvs().GetSize());
[1168]1038                       
[1141]1039                // remove pvs, we don't store interior pvss
1040                if (!left->IsLeaf())
1041                {
1042                        left->GetPvs().Clear();
1043                }
1044
[1168]1045                // set scalars
1046                mViewCellsManager->UpdateScalarPvsSize(right,
[2210]1047                                                                                           right->GetPvs().EvalPvsCost(),
1048                                                                                           right->GetPvs().GetSize());
[1168]1049
[1141]1050                right->mPvsSizeValid = true;
[752]1051               
[1141]1052                // remove pvs, we don't store interior pvss
1053                if (!right->IsLeaf())
1054                {
1055                        right->GetPvs().Clear();
1056                }
1057        }
[752]1058
[580]1059        return vc;
1060}
1061
1062
[586]1063int ViewCellsTree::RefineViewCells(const VssRayContainer &rays,
1064                                                                   const ObjectContainer &objects)
[580]1065{
1066        Debug << "refining " << (int)mMergeQueue.size() << " candidates " << endl;
[586]1067
1068        // intermediate buffer for shuffled view cells
1069        vector<MergeCandidate> buf;
1070        buf.reserve(mMergeQueue.size());
1071                       
[580]1072        // Use priority queue of remaining leaf pairs
1073        // The candidates either share the same view cells or
1074        // are border leaves which share a boundary.
1075        // We test if they can be shuffled, i.e.,
1076        // either one leaf is made part of one view cell or the other
1077        // leaf is made part of the other view cell. It is tested if the
1078        // remaining view cells are "better" than the old ones.
1079       
[586]1080        const int numPasses = 3;
[580]1081        int pass = 0;
1082        int passShuffled = 0;
1083        int shuffled = 0;
1084        int shuffledViewCells = 0;
1085
1086        ViewCell::NewMail();
1087       
[586]1088        while (!mMergeQueue.empty())
[580]1089        {
[586]1090                MergeCandidate mc = mMergeQueue.top();
1091                mMergeQueue.pop();
[580]1092
[586]1093                // both view cells equal or already shuffled
1094                if ((mc.GetLeftViewCell() == mc.GetRightViewCell()) ||
1095                        mc.GetLeftViewCell()->IsLeaf() || mc.GetRightViewCell()->IsLeaf())
1096                {                       
1097                        continue;
1098                }
[580]1099
[586]1100                // candidate for shuffling
1101                const bool wasShuffled = ShuffleLeaves(mc);
[580]1102               
[586]1103                // shuffled or put into other queue for further refine
1104                if (wasShuffled)
1105                {
1106                        ++ passShuffled;
1107
1108                        if (!mc.GetLeftViewCell()->Mailed())
[580]1109                        {
[586]1110                                mc.GetLeftViewCell()->Mail();
1111                                ++ shuffledViewCells;
[580]1112                        }
[586]1113                        if (!mc.GetRightViewCell()->Mailed())
[580]1114                        {
[586]1115                                mc.GetRightViewCell()->Mail();
1116                                ++ shuffledViewCells;
[580]1117                        }
1118                }
1119
[586]1120                // put back into intermediate vector
1121                buf.push_back(mc);
[580]1122        }
1123
[586]1124
1125        //-- in the end, the candidates must be in the mergequeue again
1126        //   with the correct cost
1127
1128        cout << "reset merge queue ... ";
1129       
1130       
1131        vector<MergeCandidate>::const_iterator bit, bit_end = buf.end();
1132       
1133        for (bit = buf.begin(); bit != bit_end; ++ bit)
1134        {   
1135                MergeCandidate mc = *bit;
1136                // recalculate cost
1137                if (ValidateMergeCandidate(mc))
1138                {
1139                        EvalMergeCost(mc);
1140                        mMergeQueue.push(mc);   
1141                }
[580]1142        }
1143
[586]1144        cout << "finished" << endl;
1145
[580]1146        return shuffledViewCells;
1147}
1148
1149
[2100]1150inline int AddedPvsSize(const ObjectPvs &pvs1, const ObjectPvs &pvs2)
[580]1151{
[1740]1152        ObjectPvs interPvs;
1153        ObjectPvs::Merge(interPvs, pvs1, pvs2);
1154
1155        return (int)interPvs.GetSize();
[580]1156}
1157
1158
1159// recomputes pvs size minus pvs of leaf l
1160#if 0
1161inline int SubtractedPvsSize(BspViewCell *vc, BspLeaf *l, const ObjectPvs &pvs2)
1162{
1163        ObjectPvs pvs;
1164        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
1165        for (it = vc->mLeaves.begin(); it != vc->mLeaves.end(); ++ it)
1166                if (*it != l)
1167                        pvs.AddPvs(*(*it)->mPvs);
1168        return pvs.GetSize();
1169}
1170#endif
1171
1172
1173// computes pvs1 minus pvs2
1174inline int SubtractedPvsSize(ObjectPvs pvs1, const ObjectPvs &pvs2)
1175{
1176        return pvs1.SubtractPvs(pvs2);
1177}
1178
1179
1180float ViewCellsTree::EvalShuffleCost(ViewCell *leaf,
[586]1181                                                                         ViewCellInterior *vc1,
1182                                                                         ViewCellInterior *vc2) const
[580]1183{
1184        //const int pvs1 = SubtractedPvsSize(vc1, leaf, *leaf->mPvs);
[1709]1185        const float pvs1 = (float)SubtractedPvsSize(vc1->GetPvs(), leaf->GetPvs());
1186        const float pvs2 = (float)AddedPvsSize(vc2->GetPvs(), leaf->GetPvs());
[580]1187
[1709]1188        const float lowerPvsLimit = (float)mViewCellsManager->GetMinPvsSize();
1189        const float upperPvsLimit = (float)mViewCellsManager->GetMaxPvsSize();
[580]1190
1191        const float pvsPenalty1 =
1192                EvalPvsPenalty(pvs1, lowerPvsLimit, upperPvsLimit);
1193
1194        const float pvsPenalty2 =
1195                EvalPvsPenalty(pvs2, lowerPvsLimit, upperPvsLimit);
1196
1197
1198        // don't shuffle leaves with pvs > max
1199        if (0 && (pvs1 + pvs2 > mViewCellsManager->GetMaxPvsSize()))
1200        {
1201                return 1e20f;
1202        }
1203
1204        float p1, p2;
1205
1206    if (mUseAreaForPvs)
1207        {
1208                p1 = vc1->GetArea() - leaf->GetArea();
1209                p2 = vc2->GetArea() + leaf->GetArea();
1210        }
1211        else
1212        {
1213                p1 = vc1->GetVolume() - leaf->GetVolume();
1214                p2 = vc2->GetVolume() + leaf->GetVolume();
1215        }
1216
1217        const float renderCost1 = pvsPenalty1 * p1;
1218        const float renderCost2 = pvsPenalty2 * p2;
1219
1220        float dev1, dev2;
1221
1222        if (1)
1223        {
1224                dev1 = fabs(mAvgRenderCost - pvsPenalty1);
1225                dev2 = fabs(mAvgRenderCost - pvsPenalty2);
1226        }
1227        else
1228        {
1229                dev1 = fabs(mExpectedCost - renderCost1);
1230                dev2 = fabs(mExpectedCost - renderCost2);
1231        }
1232       
1233        return mRenderCostWeight * (renderCost1 + renderCost2) +
[582]1234                  (1.0f - mRenderCostWeight) * (dev1 + dev2) / (float)mNumActiveViewCells;
[580]1235}
1236
1237
1238void ViewCellsTree::ShuffleLeaf(ViewCell *leaf,
[586]1239                                                                ViewCellInterior *vc1,
1240                                                                ViewCellInterior *vc2) const
[580]1241{
1242        // compute new pvs and area
[586]1243        // TODO change
[580]1244        vc1->GetPvs().SubtractPvs(leaf->GetPvs());
1245       
[1740]1246        ObjectPvs interPvs;
1247        ObjectPvs::Merge(interPvs, vc2->GetPvs(), leaf->GetPvs());
1248        vc2->SetPvs(interPvs);
1249
[580]1250        if (mUseAreaForPvs)
1251        {
1252                vc1->SetArea(vc1->GetArea() - leaf->GetArea());
1253                vc2->SetArea(vc2->GetArea() + leaf->GetArea());
1254        }
1255        else
1256        {
1257                vc1->SetVolume(vc1->GetVolume() - leaf->GetVolume());
1258                vc2->SetVolume(vc2->GetVolume() + leaf->GetVolume());
1259        }
1260
[586]1261       
[2017]1262        ViewCellInterior *p = static_cast<ViewCellInterior *>(leaf->GetParent());
[580]1263
[586]1264        p->RemoveChildLink(leaf);
1265        vc2->SetupChildLink(leaf);
[580]1266}
1267
1268
[586]1269bool ViewCellsTree::ShuffleLeaves(MergeCandidate &mc) const
[580]1270{
1271        float cost1, cost2;
1272
[2017]1273        ViewCellInterior *vc1 = static_cast<ViewCellInterior *>(mc.GetLeftViewCell());
1274        ViewCellInterior *vc2 = static_cast<ViewCellInterior *>(mc.GetRightViewCell());
[586]1275
1276        ViewCell *leaf1 = mc.GetInitialLeftViewCell();
1277        ViewCell *leaf2 = mc.GetInitialRightViewCell();
1278
[580]1279        //-- first test if shuffling would decrease cost
[586]1280        cost1 = GetCostHeuristics(vc1);
1281        cost2 = GetCostHeuristics(vc2);
[580]1282
1283        const float oldCost = cost1 + cost2;
1284       
1285        float shuffledCost1 = Limits::Infinity;
1286        float shuffledCost2 = Limits::Infinity;
1287
[586]1288        if (leaf1)
1289                shuffledCost1 = EvalShuffleCost(leaf1, vc1, vc2);       
1290        if (leaf2)
1291                shuffledCost2 = EvalShuffleCost(leaf2, vc2, vc1);
[580]1292
1293        // if cost of shuffle is less than old cost => shuffle
1294        if ((oldCost <= shuffledCost1) && (oldCost <= shuffledCost2))
1295                return false;
1296       
1297        if (shuffledCost1 < shuffledCost2)
1298        {
[586]1299                if (leaf1)
1300                        ShuffleLeaf(leaf1, vc1, vc2);
1301                mc.mInitialLeftViewCell = NULL;
[580]1302        }
1303        else
1304        {
[586]1305                if (leaf2)
1306                        ShuffleLeaf(leaf2, vc2, vc1);
1307                mc.mInitialRightViewCell = NULL;
[580]1308        }
[586]1309
[580]1310        return true;
1311}
1312
1313
1314float ViewCellsTree::GetVariance(ViewCell *vc) const
1315{
[1709]1316        const float upper = (float)mViewCellsManager->GetMaxPvsSize();
1317        const float lower = (float)mViewCellsManager->GetMinPvsSize();
[580]1318
1319        if (1)
1320        {
[752]1321                const float penalty =
[2342]1322                        EvalPvsPenalty(GetTrianglesInPvs(vc), lower, upper);
[1141]1323
[752]1324                return (mAvgRenderCost - penalty) * (mAvgRenderCost - penalty) /
1325                        (float)mNumActiveViewCells;
[580]1326        }
1327
1328    const float leafCost = GetRenderCost(vc);
1329        return (mExpectedCost - leafCost) * (mExpectedCost - leafCost);
1330}
1331
1332
1333float ViewCellsTree::GetDeviation(ViewCell *vc) const
1334{
[1709]1335        const float upper = (float)mViewCellsManager->GetMaxPvsSize();
1336        const float lower = (float)mViewCellsManager->GetMinPvsSize();
[580]1337
1338        if (1)
1339        {
[2342]1340                const float penalty = EvalPvsPenalty(GetTrianglesInPvs(vc), lower, upper);
[582]1341                return fabs(mAvgRenderCost - penalty) / (float)mNumActiveViewCells;
[580]1342        }
1343
1344    const float renderCost = GetRenderCost(vc);
1345        return fabs(mExpectedCost - renderCost);
1346}
1347
1348
1349float ViewCellsTree::GetRenderCost(ViewCell *vc) const
1350{
1351        if (mUseAreaForPvs)
[1141]1352        {
[1707]1353                return vc->GetPvs().EvalPvsCost() * vc->GetArea();
[1141]1354        }
[580]1355
[1707]1356        return vc->GetPvs().EvalPvsCost() * vc->GetVolume();
[580]1357}
1358
1359
1360float ViewCellsTree::GetCostHeuristics(ViewCell *vc) const
1361{
1362        return GetRenderCost(vc) * mRenderCostWeight +
1363                   GetDeviation(vc) * (1.0f - mRenderCostWeight);
1364}
1365
1366
[582]1367bool ViewCellsTree::ValidateMergeCandidate(MergeCandidate &mc) const
[580]1368{
[752]1369        // propagate up so we have only the active view cells
[580]1370        while (mc.mLeftViewCell->mParent)
1371        {
1372                mc.mLeftViewCell = mc.mLeftViewCell->mParent;
1373        }
1374
1375        while (mc.mRightViewCell->mParent)
1376        {
1377                mc.mRightViewCell = mc.mRightViewCell->mParent;
1378        }
1379
[752]1380        // this view cell was already merged
1381        //return mc.mLeftViewCell && (mc.mLeftViewCell != mc.mRightViewCell);
[582]1382        return mc.mLeftViewCell != mc.mRightViewCell;
[580]1383}
1384
1385
1386void ViewCellsTree::EvalMergeCost(MergeCandidate &mc) const
1387{
[1586]1388        ///////////////////
[580]1389        //-- compute pvs difference
[1586]1390
[1709]1391        float newPvs;
[1586]1392       
[1709]1393        // not valid if not using const cost per object!!
1394        newPvs = ComputeMergedPvsCost(mc.mLeftViewCell->GetPvs(), mc.mRightViewCell->GetPvs());
[580]1395
[1709]1396
[1141]1397        const float newPenalty = EvalPvsPenalty(newPvs,
[1709]1398                                                                                        (float)mViewCellsManager->GetMinPvsSize(),
1399                                                                                        (float)mViewCellsManager->GetMaxPvsSize());
[729]1400
[580]1401        ViewCell *vc1 = mc.mLeftViewCell;
1402        ViewCell *vc2 = mc.mRightViewCell;
1403
1404        //-- compute ratio of old cost
[1586]1405        //-- (i.e., added size of left and right view cell times pvs size)
1406        //-- to new rendering cost (i.e, size of merged view cell times pvs size)
[580]1407        const float oldCost = GetRenderCost(vc1) + GetRenderCost(vc2);
1408
1409    const float newCost = mUseAreaForPvs ?
1410                (float)newPenalty * (vc1->GetArea() + vc2->GetArea()) :
1411                (float)newPenalty * (vc1->GetVolume() + vc2->GetVolume());
1412
1413
1414        // strong penalty if pvs size too large
1415        if (0 && (newPvs > mViewCellsManager->GetMaxPvsSize()))
1416        {
1417                mc.mRenderCost = 1e20f;
1418        }
1419        else
1420        {
1421                mc.mRenderCost = (newCost - oldCost) /
1422                        mViewCellsManager->GetViewSpaceBox().GetVolume();
1423        }       
1424       
[1586]1425        ///////////////////////////
1426        //-- merge cost also takes deviation into account
[580]1427
1428        float newDev, oldDev;
1429
1430        if (1)
[582]1431                newDev = fabs(mAvgRenderCost - newPenalty) / (float)mNumActiveViewCells;
[580]1432        else
[582]1433                newDev = fabs(mExpectedCost - newCost) / (float)mNumActiveViewCells;
[580]1434       
1435        oldDev = GetDeviation(vc1) + GetDeviation(vc2);
1436
1437        // compute deviation increase
1438        mc.mDeviationIncr = newDev - oldDev;
1439       
1440        //Debug << "render cost: " << mc.mRenderCost * mRenderCostWeight << endl;
1441        //Debug << "standard deviation: " << mc.mDeviationIncr * mRenderCostWeight << endl;
1442}
1443
[752]1444
1445void ViewCellsTree::SetViewCellsStorage(int stype)
[580]1446{
[752]1447        if (mViewCellsStorage == stype)
1448                return;
1449
1450        // TODO
1451        switch (stype)
[581]1452        {
[752]1453        case COMPRESSED:
[584]1454                CompressViewCellsPvs(mRoot);
[752]1455                break;
1456        default:
1457                break;
[584]1458        }
[752]1459
1460        mViewCellsStorage = stype;
[584]1461}
[580]1462
[752]1463
[584]1464void ViewCellsTree::CompressViewCellsPvs(ViewCell *root)
1465{
1466        if (!root->IsLeaf())
1467        {
[2017]1468                ViewCellInterior *interior = static_cast<ViewCellInterior *>(root);
[584]1469
1470        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[585]1471               
[584]1472                // compress child sets first
1473                for (it = interior->mChildren.begin(); it != it_end; ++ it)
[581]1474                {
[584]1475                        CompressViewCellsPvs(*it);
[581]1476                }
[584]1477
[1842]1478                /*cout << "***************\nbefore pulling up:\n";
1479                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1480                {
1481                        cout << "vc:\n" << (*it)->GetPvs() << endl;
1482                }*/
1483
[585]1484                // compress root node
[610]1485                PullUpVisibility(interior);
[1842]1486
1487                /*cout << "after pulling up:\n";
1488                cout << "interior:\n" << interior->GetPvs() << endl;
1489
1490                for (it = interior->mChildren.begin(); it != it_end; ++ it)
1491                {
1492                        cout << "vc:\n" << (*it)->GetPvs() << endl;
1493                }*/
[581]1494        }
[580]1495}
1496
1497
[1166]1498void ViewCellsTree::UpdateStats(ofstream &stats,
[1709]1499                                                                const ViewCellsTreeStats &vcStats)
[1166]1500{
[1709]1501         stats << "#Pass\n" << vcStats.mPass << endl
1502                   << "#Splits\n" << vcStats.mNumViewCells << endl
1503                   << "#RenderCostDecrease\n" << vcStats.mRenderCostDecrease << endl // TODO
1504                   << "#TotalRenderCost\n" << vcStats.mTotalRenderCost << endl
1505                   << "#CurrentPvs\n" << vcStats.mCurrentPvsCost << endl
1506                   << "#ExpectedCost\n" << vcStats.mExpectedCost << endl
1507                   << "#AvgRenderCost\n" << vcStats.mAvgRenderCost << endl
1508                   << "#Deviation\n" << vcStats.mDeviation << endl
1509                   << "#TotalPvs\n" << vcStats.mTotalPvsCost << endl
1510                   << "#TotalEntriesInPvs\n" << vcStats.mEntriesInPvs << endl
1511                   << "#Memory\n" << vcStats.mMemoryCost << endl
1512                   << "#PvsSizeDecrease\n" << vcStats.mPvsSizeDecr << endl
1513                   << "#Volume\n" << vcStats.mVolume << endl
[1653]1514                   << endl;
[1166]1515}
1516
[1489]1517
[660]1518void ViewCellsTree::ExportStats(const string &mergeStats)
[650]1519{
1520        TraversalQueue tqueue;
1521        tqueue.push(mRoot);
[1666]1522
[1709]1523        ViewCellsTreeStats vcStats;
1524        vcStats.Reset();
1525
[1695]1526        //cout << "exporting stats ... " << endl;
[1709]1527        vcStats.mNumViewCells = 1;
[650]1528       
1529        const AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1530        const float vol = box.GetVolume();
1531
[2342]1532        const float rootPvs = GetTrianglesInPvs(mRoot);
[1161]1533        const int rootEntries = GetPvsEntries(mRoot);
[1709]1534       
1535        vcStats.mTotalPvsCost = rootPvs;
1536        vcStats.mTotalRenderCost = rootPvs;
1537        vcStats.mAvgRenderCost = rootPvs;
1538        vcStats.mExpectedCost = rootPvs;
1539       
1540        vcStats.mEntriesInPvs = rootEntries;
[650]1541
1542        ofstream stats;
[660]1543        stats.open(mergeStats.c_str());
[650]1544
[1709]1545        vcStats.mMemoryCost = (float)vcStats.mEntriesInPvs * ObjectPvs::GetEntrySize();
[1653]1546
[1603]1547        /////////////
[752]1548        //-- first view cell
[1603]1549
[1709]1550        UpdateStats(stats, vcStats);
1551                               
[1166]1552               
[1161]1553        //-- go through tree in the order of render cost decrease
1554        //-- which is the same order as the view cells were merged
1555        //-- or the reverse order of subdivision for subdivision-only
1556        //-- view cell hierarchies.
[650]1557
1558        while (!tqueue.empty())
1559        {
1560                ViewCell *vc = tqueue.top();
1561                tqueue.pop();
1562
1563                if (!vc->IsLeaf())
1564                {       
[2017]1565                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1166]1566
[2342]1567                        const float parentCost = GetTrianglesInPvs(interior);
[1166]1568                        const int parentPvsEntries = GetPvsEntries(interior);
[1709]1569            const float parentExpCost = (float)parentCost * interior->GetVolume();
[1166]1570
[1709]1571                        float childExpCost = 0;
[650]1572                        float childCost = 0;
[1166]1573                        int childPvsEntries = 0;
[650]1574
[1709]1575                        -- vcStats.mNumViewCells;
[650]1576
1577                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1179]1578
[650]1579                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1580                        {
[1166]1581                                ViewCell *vc = *it;
[1168]1582
[2342]1583                                const float pvsCost = GetTrianglesInPvs(vc);
[1166]1584                                const int pvsEntries = GetPvsEntries(vc);
1585
[1709]1586                                childExpCost += childCost * vc->GetVolume();
1587                                childCost += pvsCost;
[1166]1588                                childPvsEntries += pvsEntries;
[650]1589
[1166]1590                                tqueue.push(vc);
[1709]1591                                ++ vcStats.mNumViewCells;
[650]1592                        }
1593
[1603]1594                        // update stats for this view cell
[1709]1595                        const float costDecr = (parentExpCost - childExpCost) / vol;
[650]1596
[1709]1597                        vcStats.mTotalRenderCost -= costDecr;
1598                        vcStats.mTotalPvsCost += childCost - parentCost;
1599                        vcStats.mEntriesInPvs += childPvsEntries - parentPvsEntries;
[1166]1600
[1709]1601                        vcStats.mExpectedCost = vcStats.mTotalRenderCost / (float)vcStats.mNumViewCells;
1602                        vcStats.mAvgRenderCost = vcStats.mTotalPvsCost / (float)vcStats.mNumViewCells;
[650]1603
[1709]1604                        vcStats.mMemoryCost = vcStats.mEntriesInPvs * ObjectPvs::GetEntrySize();
[1653]1605
[1709]1606                        UpdateStats(stats, vcStats);
[650]1607                }
1608        }
1609
1610        stats.close();
1611}
1612
1613
1614void ViewCellsTree::SetRoot(ViewCell *root)
1615{
1616        mRoot = root;
1617}
1618
[660]1619
[581]1620void ViewCellsTree::CollectBestViewCellSet(ViewCellContainer &viewCells,
1621                                                                                   const int numViewCells)
[580]1622{
1623        TraversalQueue tqueue;
[581]1624        tqueue.push(mRoot);
[582]1625       
[580]1626        while (!tqueue.empty())
1627        {
1628                ViewCell *vc = tqueue.top();
[650]1629                tqueue.pop();
1630
[582]1631                // save the view cells if it is a leaf or if enough view cells have already been traversed
1632                // because of the priority queue, this will be the optimal set of v
[650]1633                if (vc->IsLeaf() || ((viewCells.size() + tqueue.size() + 1) >= numViewCells))
[581]1634                {
1635                        viewCells.push_back(vc);
1636                }
[582]1637                else
1638                {       
[2017]1639                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[580]1640
[581]1641                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1642
1643                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1644                        {
1645                                tqueue.push(*it);
1646                        }
1647                }
[580]1648        }
1649}
1650
[1742]1651
[610]1652void ViewCellsTree::PullUpVisibility(ViewCellInterior *interior)
[581]1653{
[1842]1654        const int mail = (int)interior->mChildren.size();
1655        Intersectable::NewMail(mail);
[580]1656
[581]1657        ViewCellContainer::const_iterator cit, cit_end = interior->mChildren.end();
1658
[1842]1659    // mail all objects in the leaf sets
[584]1660        // we are interested in the objects which are present in all leaves
1661        // => count how often an object is part of a child set
[581]1662        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1663        {
1664                ViewCell *vc = *cit;
[1842]1665                ObjectPvsIterator pit = vc->GetPvs().GetIterator();
[581]1666
[1842]1667                while (pit.HasMoreEntries())
1668                {               
[2117]1669                        pit.Next()->Mail();
[1842]1670                }
1671        }
1672
1673        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1674        {
1675                ViewCell *vc = *cit;
1676
[1742]1677                ObjectPvsIterator pit = vc->GetPvs().GetIterator();
[581]1678
[1742]1679                while (pit.HasMoreEntries())
1680                {               
[2117]1681                        pit.Next()->IncMail();
[581]1682                }
1683        }
1684
[1842]1685        // reset pvs
1686    interior->GetPvs().Clear(false);
[1742]1687               
[2117]1688        PvsData pvsData;
1689
[581]1690        // only the objects which are present in all leaf pvs
1691        // should remain in the parent pvs
[584]1692        // these are the objects which have been mailed in all children
[581]1693        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1694        {
1695                ViewCell *vc = *cit;
[1742]1696               
1697                ObjectPvsIterator pit = vc->GetPvs().GetIterator();
[581]1698
[1742]1699                while (pit.HasMoreEntries())
1700                {               
[2117]1701                        Intersectable *obj = pit.Next(pvsData);
[581]1702
[2117]1703                        if (obj->Mailed(mail))
[581]1704                        {       
[2117]1705                                interior->GetPvs().AddSample(obj, pvsData.mSumPdf);
[581]1706                        }
1707                }
1708        }
1709
[1842]1710        // delete entries which are pulled up
1711        // note: could be inefficent, rather gather unmailed pvs and reassign
1712        for (cit = interior->mChildren.begin(); cit != cit_end; ++ cit)
1713        {
1714                ViewCell *vc = *cit;
1715                ObjectPvsIterator pit = vc->GetPvs().GetIterator();
[581]1716
[1842]1717                ObjectPvs newPvs;
[2117]1718               
[1842]1719                while (pit.HasMoreEntries())
1720                {               
[2117]1721                        Intersectable *obj = pit.Next(pvsData);
[1842]1722
1723                        if (!obj->Mailed(mail))
1724                        {
[2117]1725                                newPvs.AddSampleDirty(obj, pvsData.mSumPdf);
[1189]1726                        }
[581]1727                }
[1842]1728
1729                vc->SetPvs(newPvs);
[581]1730        }
1731}
1732
[1168]1733
[1166]1734// TODO matt: implement this function for different storing methods
[584]1735void ViewCellsTree::GetPvs(ViewCell *vc, ObjectPvs &pvs) const
1736{
[1161]1737        // pvs is stored in each cell => just return pvs
[752]1738        if (mViewCellsStorage == PVS_IN_INTERIORS)
[801]1739        {
[585]1740                pvs = vc->GetPvs();
[801]1741                return;
1742        }
[585]1743
[1713]1744        ////////////////
[1161]1745        //-- pvs is not stored with the interiors => reconstruct
[585]1746        ViewCell *root = vc;
1747       
[883]1748        // add pvs from this view cell to root
[585]1749        while (root->GetParent())
[584]1750        {
[585]1751                root = root->GetParent();
[1740]1752                pvs.MergeInPlace(root->GetPvs());
[585]1753        }
[584]1754
[883]1755        // add pvs from leaves
[585]1756        stack<ViewCell *> tstack;
1757        tstack.push(vc);
[584]1758
[585]1759        while (!tstack.empty())
1760        {
1761                vc = tstack.top();
1762                tstack.pop();
[1742]1763       
[1161]1764                // add newly found pvs to merged pvs
[1740]1765                pvs.MergeInPlace(vc->GetPvs());
[1750]1766               
[1161]1767                if (!vc->IsLeaf()) // interior cells: go down to leaf level
[584]1768                {
[2017]1769                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[584]1770                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1771
1772                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1773                        {
[585]1774                                tstack.push(*it);
1775                        }               
[584]1776                }
1777        }
1778}
1779
1780
[1709]1781float ViewCellsTree::GetPvsCostForLeafStorage(ViewCell *vc) const
[584]1782{
[2227]1783        // pvs is already stored in the leaves
[1166]1784        if (vc->IsLeaf())
1785        {
[1707]1786                return vc->GetPvs().EvalPvsCost();
[1166]1787        }
[1168]1788       
[2227]1789        /////////////////////////////////
1790
[1707]1791        // interior nodes: pvs is either stored as a
1792        // scalar or has to be reconstructed from the leaves
[1168]1793        // the stored pvs size is the valid pvs size => just return scalar
1794        if (vc->mPvsSizeValid)
[1166]1795        {
[1709]1796                return vc->mPvsCost;
[1168]1797        }
1798       
1799        // if no valid pvs size stored as a scalar =>
1800        // compute current pvs size of interior from it's leaf nodes
1801        ViewCellContainer leaves;
1802        CollectLeaves(vc, leaves);
[1121]1803
[1168]1804        ViewCellContainer::const_iterator it, it_end = leaves.end();
[1166]1805
[1168]1806        ObjectPvs newPvs;
[1166]1807
[1586]1808        // sum up uniquely found intersectables
[1168]1809        for (it = leaves.begin(); it != it_end; ++ it)
1810        {
[1763]1811                newPvs.MergeInPlace((*it)->GetPvs());
[1166]1812        }
1813
[1707]1814        return newPvs.EvalPvsCost();
[1166]1815}
1816
1817
1818int ViewCellsTree::GetEntriesInPvsForLeafStorage(ViewCell *vc) const
1819{
1820        // pvs is always stored directly in leaves
1821        if (vc->IsLeaf())
[752]1822        {
[1168]1823                return vc->GetPvs().GetSize();
[1166]1824        }
[1168]1825
1826        // interior nodes: pvs is either stored as a scalar or
1827        // has to be reconstructed from the leaves
1828
1829        // the stored pvs size is the valid pvs size => just return scalar
1830        if (vc->mPvsSizeValid)
[1166]1831        {
[1168]1832                return vc->mEntriesInPvs;
1833        }
1834       
1835        int pvsSize = 0;
[1161]1836
[1168]1837        // if no valid pvs size stored as a scalar =>
1838        // compute current pvs size of interior from it's leaf nodes
1839        ViewCellContainer leaves;
1840        CollectLeaves(vc, leaves);
[1161]1841
[1168]1842        ViewCellContainer::const_iterator it, it_end = leaves.end();
1843        Intersectable::NewMail();
[1161]1844
[1168]1845        // sum different intersectables
1846        for (it = leaves.begin(); it != it_end; ++ it)
1847        {
[1742]1848                ObjectPvsIterator oit = (*it)->GetPvs().GetIterator();
[1161]1849
[1742]1850                while (oit.HasMoreEntries())
[1166]1851                {
[2117]1852                        Intersectable *intersect = oit.Next();
[1168]1853
1854                        if (!intersect->Mailed())
1855                        {
1856                                intersect->Mail();
1857                                ++ pvsSize;
1858                        }
[1166]1859                }
1860        }
[1161]1861
[1166]1862        return pvsSize;
1863}
[1161]1864
1865
[1709]1866float ViewCellsTree::GetPvsCostForCompressedStorage(ViewCell *vc) const
[1166]1867{
[1709]1868        float pvsCost = 0;
[1166]1869
[1545]1870        /////////////
[1166]1871        //-- compressed pvs
1872
1873        // the stored pvs size is the valid pvs size => just return scalar
1874        if (vc->mPvsSizeValid)
1875        {
[1709]1876                pvsCost = vc->mPvsCost;
[1166]1877        }
1878
1879        // if no pvs size stored, compute new one
1880        ViewCell *root = vc;
1881       
1882        // also add pvs from this view cell to root
1883        while (root->GetParent())
1884        {
1885                root = root->GetParent();
1886       
1887                // matt: bug! must evaluate kd pvss also
[1709]1888                pvsCost += CountPvsContribution(root);
[1166]1889        }
1890
1891        stack<ViewCell *> tstack;
1892        tstack.push(vc);
1893
1894        while (!tstack.empty())
1895        {
1896                vc = tstack.top();
1897                tstack.pop();
[1709]1898
[1166]1899                // matt: bug! must evaluate kd pvss also
[1709]1900                pvsCost += CountPvsContribution(vc);
[1166]1901
1902                if (!vc->IsLeaf())
[1161]1903                {
[2017]1904                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1166]1905                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
1906
1907                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
[752]1908                        {
[1166]1909                                tstack.push(*it);
1910                        }               
1911                }
1912        }
[1161]1913
[1709]1914        return pvsCost;
[1166]1915}
1916
1917
1918int ViewCellsTree::GetEntriesInPvsForCompressedStorage(ViewCell *vc) const
1919{
1920        int pvsSize = 0;
1921
[1586]1922        /////////////////
[1166]1923        //-- compressed pvs
1924
1925        // the stored pvs size is the valid pvs size => just return scalar
1926        if (vc->mPvsSizeValid)
1927        {
1928                pvsSize = vc->mEntriesInPvs;
1929        }
1930
1931        // if no pvs size stored, compute new one
1932        ViewCell *root = vc;
[752]1933       
[1166]1934        // also add pvs from this view cell to root
1935        while (root->GetParent())
1936        {
1937                root = root->GetParent();
1938                // count the pvs entries different from the already found ones 
[1586]1939                pvsSize += CountPvsContribution(root);
[1166]1940        }
[585]1941
[1166]1942        stack<ViewCell *> tstack;
1943        tstack.push(vc);
[719]1944
[1166]1945        while (!tstack.empty())
1946        {
1947                vc = tstack.top();
1948                tstack.pop();
[1161]1949       
[1166]1950                // count the pvs entries different from the already found ones 
[1586]1951                pvsSize += CountPvsContribution(vc);
[752]1952
[1166]1953                if (!vc->IsLeaf())
1954                {
[2017]1955                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1161]1956
[1166]1957                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[1161]1958
[1166]1959                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
1960                        {
1961                                tstack.push(*it);
1962                        }               
1963                }
1964        }
1965
1966        return pvsSize;
1967}
1968
1969
[2342]1970float ViewCellsTree::GetTrianglesInPvs(ViewCell *vc) const
[1166]1971{
[1709]1972        float pvsCost = 0;
[1166]1973        Intersectable::NewMail();
1974
1975        ////////////////////////////////////////////////
[2205]1976        //-- for interiors, pvs can be stored using different methods
[1166]1977
1978        switch (mViewCellsStorage)
1979        {
[1707]1980        case PVS_IN_LEAVES:
1981                // pvs is stored only in leaves
[1709]1982                pvsCost = GetPvsCostForLeafStorage(vc);                 
[1311]1983                break;
[1166]1984        case COMPRESSED:
[1709]1985                pvsCost = GetPvsCostForCompressedStorage(vc);
[1311]1986                break;
[1161]1987        case PVS_IN_INTERIORS:
1988        default:
[1742]1989                // pvs is stored consistently in the tree up
[2164]1990                // to the root just return pvs size
[1709]1991                pvsCost = vc->GetPvs().EvalPvsCost();   
[1161]1992                break;
1993        }
1994
[1709]1995        return pvsCost; 
[1161]1996}
1997
1998
1999int ViewCellsTree::GetPvsEntries(ViewCell *vc) const
2000{
2001        int pvsSize = 0;
2002
2003        Intersectable::NewMail();
2004
[2210]2005        /////////////////////////
2006        //-- different storage methods for interiors
[1161]2007       
2008        switch (mViewCellsStorage)
2009        {
[1622]2010        case PVS_IN_LEAVES:
2011                {
2012                        //-- store pvs only in leaves
[1166]2013                        pvsSize = GetEntriesInPvsForLeafStorage(vc);
2014                        break;
[752]2015                }
2016        case COMPRESSED:
2017                {
[1166]2018                        pvsSize = GetEntriesInPvsForCompressedStorage(vc);
[752]2019                        break;
2020                }
2021        case PVS_IN_INTERIORS:
[997]2022        default:
[1161]2023                // pvs is stored consistently in the tree up to the root
2024                // just return pvs size
2025                pvsSize = vc->GetPvs().GetSize();       
2026                break;
[752]2027        }
[584]2028
2029        return pvsSize; 
2030}
2031
2032
2033float ViewCellsTree::GetMemoryCost(ViewCell *vc) const
2034{
[1667]2035        return (float)CountStoredPvsEntries(vc) * ObjectPvs::GetEntrySize();
[584]2036}
2037
[2539]2038
[1586]2039int ViewCellsTree::CountStoredPvsEntries(ViewCell *root) const
[584]2040{
[1161]2041        int pvsSize = root->GetPvs().GetSize();
[584]2042
[1161]2043        // recursivly count leaves
2044        if (!root->IsLeaf())
[584]2045        {
[2017]2046                ViewCellInterior *interior = static_cast<ViewCellInterior *>(root);
[584]2047                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2048
2049                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2050                {
[1586]2051                        pvsSize += CountStoredPvsEntries(*it);
[584]2052                }
2053        }
2054
2055        return pvsSize;         
2056}
2057
[2539]2058
[752]2059int ViewCellsTree::ViewCellsStorage() const
[584]2060{
[752]2061        return mViewCellsStorage;
[584]2062}
2063
2064
[881]2065ViewCell *ViewCellsTree::GetActiveViewCell(ViewCellLeaf *vc) const
[590]2066{
[881]2067        return vc->GetActiveViewCell();
[590]2068}
2069
2070
[1740]2071void ViewCellsTree::PropagatePvs(ViewCell *root)
[664]2072{       
[1740]2073        ViewCell *viewCell = root;
[664]2074
[660]2075        // propagate pvs up
[664]2076        while (viewCell->GetParent())
[610]2077        {
[1740]2078                ObjectPvs mergedPvs;
2079                viewCell->GetParent()->GetPvs().MergeInPlace(root->GetPvs());
2080
[664]2081                viewCell = viewCell->GetParent();
[610]2082        }
[651]2083
[1740]2084        if (root->IsLeaf())
[651]2085                return;
2086
[660]2087        // propagate pvs to the leaves
[651]2088        stack<ViewCell *> tstack;
[1740]2089        tstack.push(root);
[651]2090
2091        while (!tstack.empty())
2092        {
2093                ViewCell *viewCell = tstack.top();
2094                tstack.pop();
2095
[1740]2096                if (viewCell != root)
[651]2097                {
[1740]2098                        viewCell->GetPvs().MergeInPlace(root->GetPvs());
[651]2099                }
2100
2101                if (!viewCell->IsLeaf())
2102                {
[2017]2103                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(viewCell);
[664]2104
[651]2105                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2106
2107                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2108                        {
2109                                tstack.push(*it);
2110                        }
2111                }
2112        }
[610]2113}
[605]2114
[610]2115
[650]2116void ViewCellsTree::AssignRandomColors()
[608]2117{
[675]2118        TraversalQueue tqueue;
2119        tqueue.push(mRoot);
[708]2120       
[675]2121        mRoot->SetColor(RandomColor(0.3f, 1.0f));
2122       
2123        while (!tqueue.empty())
[608]2124        {
[675]2125                ViewCell *vc = tqueue.top();
2126                tqueue.pop();
[650]2127
[1740]2128                // save the view cells if it is a leaf or if enough view cells
2129                // have already been traversed because of the priority queue,
2130                // this will be the optimal set of v
[675]2131                if (!vc->IsLeaf())
2132                {       
[2017]2133                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[675]2134                 
2135                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2136                 
2137                        float maxProbability = -1.0f;
2138                 
2139                        ViewCell *maxViewCell = NULL;
2140                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2141                        {
2142                                ViewCell *v = *it;
2143                         
2144                                // set random color
2145                                v->SetColor(RandomColor(0.3f, 1.0f));
2146                         
2147                                if (v->GetVolume() > maxProbability)
2148                                {
2149                                        maxProbability = v->GetVolume();
2150                                        maxViewCell = v;
2151                                }
2152
2153                                if (maxViewCell)
[708]2154                                {
[675]2155                                        maxViewCell->SetColor(vc->GetColor());
[708]2156                                }
[675]2157                               
2158                                tqueue.push(v);
2159                        }
2160                }       
[608]2161        }
2162}
2163
[675]2164
[1161]2165/** Get costs resulting from each merge step.
2166*/
[1603]2167void ViewCellsTree::GetCostFunction(vector<float> &costFunction)
[608]2168{
[1603]2169        TraversalQueue tqueue;
2170        tqueue.push(mRoot);
2171
2172        int numViewCells = 1;
2173
2174        const float vol = mViewCellsManager->GetViewSpaceBox().GetVolume();
[2342]2175        const float rootPvs = GetTrianglesInPvs(mRoot);
[1603]2176       
2177        float totalRenderCost;
2178
[1709]2179        float totalPvsCost = rootPvs;
[1603]2180        totalRenderCost = (float)rootPvs;
2181
2182        costFunction.push_back(totalRenderCost);
2183
2184        //-- go through tree in the order of render cost decrease
2185        //-- which is the same order as the view cells were merged
2186        //-- or the reverse order of subdivision for subdivision-only
2187        //-- view cell hierarchies.
2188
2189        while (!tqueue.empty())
[1161]2190        {
[1603]2191                ViewCell *vc = tqueue.top();
2192                tqueue.pop();
2193
2194                if (!vc->IsLeaf())
2195                {       
[2017]2196                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1603]2197
[2342]2198                        const float parentCost = GetTrianglesInPvs(interior);
[1709]2199                        const float parentExpCost = parentCost * interior->GetVolume();
[1603]2200
2201                        -- numViewCells;
2202
[1709]2203                        float childExpCost = 0;
[1603]2204                        float childCost = 0;
2205                       
2206                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2207
2208                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2209                        {
2210                                ViewCell *vc = *it;
2211
[2342]2212                                const float pvsCost = GetTrianglesInPvs(vc);
[1603]2213                               
[1709]2214                                childExpCost += (float) pvsCost * vc->GetVolume();
2215                                childCost += pvsCost;
[1603]2216                               
2217                                tqueue.push(vc);
2218                                ++ numViewCells;
2219                        }
2220
2221                        // update stats for this view cell
[1709]2222                        const float costDecr = (parentExpCost - childExpCost) / vol;
[1603]2223                        totalRenderCost -= costDecr;
[1709]2224                       
2225                        costFunction.push_back(totalRenderCost);
[1161]2226                }
[608]2227        }
2228}
2229
2230
[1603]2231/** Get storage costs resulting from each merge step.
2232*/
2233void ViewCellsTree::GetStorageFunction(vector<int> &storageFunction)
2234{
2235        TraversalQueue tqueue;
2236        tqueue.push(mRoot);
2237
2238        int numViewCells = 1;
2239
2240        const float vol = mViewCellsManager->GetViewSpaceBox().GetVolume();
2241        const int rootEntries = GetPvsEntries(mRoot);
2242
2243        int entriesInPvs = rootEntries;
[2100]2244        // one entry into the pvs
2245    const int entryStorage = sizeof(PvsData) + sizeof(int);
[1603]2246
2247        storageFunction.push_back(rootEntries);
2248
2249        ////////////
2250        //-- go through tree in the order of render cost decrease
2251        //-- which is the same order as the view cells were merged
2252        //-- or the reverse order of subdivision for subdivision-only
2253        //-- view cell hierarchies.
2254
2255        while (!tqueue.empty())
2256        {
2257                ViewCell *vc = tqueue.top();
2258                tqueue.pop();
2259
2260                if (!vc->IsLeaf())
2261                {       
[2017]2262                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1603]2263
[2342]2264                        const float parentPvsCost = GetTrianglesInPvs(interior);
[1603]2265                        const int parentPvsEntries = GetPvsEntries(interior);
[1709]2266            const float parentExpCost = (float)parentPvsCost * interior->GetVolume();
[1603]2267
[1709]2268                        float childExpCost = 0;
[1603]2269                        int childPvs = 0;
2270                        int childPvsEntries = 0;
2271
2272                        -- numViewCells;
2273
2274                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2275
2276                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2277                        {
2278                                ViewCell *vc = *it;
2279
2280                                const int pvsEntries = GetPvsEntries(vc);
2281                                childPvsEntries += pvsEntries;
2282
2283                                tqueue.push(vc);
2284                                ++ numViewCells;
2285                        }
2286
2287                        // update stats for this view cell
[1709]2288                        const float costDecr = (parentExpCost - childExpCost) / vol;
[1603]2289
2290                        entriesInPvs += childPvsEntries - parentPvsEntries;
2291
2292                        const int storageCost = entriesInPvs * entryStorage;
2293                        storageFunction.push_back(storageCost);
2294                }
2295        }
2296}
2297
2298
[1161]2299void ViewCellsTree::UpdateViewCellsStats(ViewCell *vc,
2300                                                                                 ViewCellsStatistics &vcStat)
[605]2301{
2302        ++ vcStat.viewCells;
2303               
[2342]2304        const float pvsCost = GetTrianglesInPvs(vc);
[605]2305
[1709]2306        vcStat.pvsCost += pvsCost;
[605]2307
[1709]2308        if (pvsCost < Limits::Small)
[605]2309                ++ vcStat.emptyPvs;
2310
[1709]2311        if (pvsCost > vcStat.maxPvs)
2312                vcStat.maxPvs = pvsCost;
[605]2313
[1709]2314        if (pvsCost < vcStat.minPvs)
2315                vcStat.minPvs = pvsCost;
[605]2316
2317        if (!vc->GetValid())
2318                ++ vcStat.invalid;
2319}
2320
[1161]2321
[1201]2322bool ViewCellsTree::Export(OUT_STREAM &stream, const bool exportPvs)
[610]2323{
[840]2324        // export recursivly all view cells from the root
[844]2325        ExportViewCell(mRoot, stream, exportPvs);
[605]2326
[610]2327        return true;
2328}
2329
2330
[651]2331void ViewCellsTree::CreateUniqueViewCellsIds()
[610]2332{
[651]2333        stack<ViewCell *> tstack;
[610]2334
[651]2335        int currentId = 0;
2336
2337        tstack.push(mRoot);
2338
2339        while (!tstack.empty())
[610]2340        {
[651]2341                ViewCell *vc = tstack.top();
2342                tstack.pop();
2343
[1551]2344                if (vc->GetId() != -1) // out of bounds
2345                        vc->SetId(currentId ++);
[651]2346
2347                if (!vc->IsLeaf())
2348                {
[2017]2349                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[1161]2350                       
[651]2351                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2352                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2353                        {
2354                                tstack.push(*it);
2355                        }
2356                }
[610]2357        }
[651]2358}
[610]2359
[1201]2360
2361void ViewCellsTree::ExportPvs(ViewCell *viewCell, OUT_STREAM &stream)
[651]2362{
[1742]2363        ObjectPvsIterator it = viewCell->GetPvs().GetIterator();
[651]2364
[1742]2365        while (it.HasMoreEntries())
[837]2366        {
[2117]2367                Intersectable *obj = it.Next();
[1742]2368
[2124]2369                // hack: just output all the "elementary" objects
[1843]2370                if (0 && (obj->Type() == Intersectable::BVH_INTERSECTABLE))
[1614]2371                {
2372                        ObjectContainer objects;
[2017]2373                        BvhNode *node = static_cast<BvhNode *>(obj);
[1614]2374                        node->CollectObjects(objects);
2375               
2376                        ObjectContainer::const_iterator oit, oit_end = objects.end();
2377                        for (oit = objects.begin(); oit != oit_end; ++ oit)
2378                        {
2379                                stream << (*oit)->GetId() << " ";
2380                        }
2381                }
2382                else
2383                {
[2117]2384                        stream << obj->GetId() << " ";
[1614]2385                }
[837]2386        }
2387}
2388
[1201]2389
2390void ViewCellsTree::ExportViewCell(ViewCell *viewCell,
2391                                                                   OUT_STREAM &stream,
2392                                                                   const bool exportPvs)
[837]2393{
[610]2394        if (viewCell->IsLeaf())
2395        {
2396                stream << "<Leaf ";
2397                stream << "id=\"" << viewCell->GetId() << "\" ";
[2017]2398                stream << "active=\"" << static_cast<ViewCellLeaf *>(viewCell)->GetActiveViewCell()->GetId() << "\" ";
[610]2399                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
2400                stream << "pvs=\"";
[837]2401               
[1551]2402                //-- export pvs, i.e., the ids of the objects in the pvs
[844]2403                if (exportPvs)
[955]2404                {
[840]2405                        ExportPvs(viewCell, stream);
[955]2406                }
[651]2407                stream << "\" />" << endl;
[610]2408        }
2409        else
2410        {
[2017]2411                ViewCellInterior *interior = static_cast<ViewCellInterior *>(viewCell);
[610]2412       
2413                stream << "<Interior ";
2414                stream << "id=\"" << viewCell->GetId() << "\" ";
2415                stream << "mergecost=\"" << viewCell->GetMergeCost() << "\" ";
[870]2416                stream << "pvs=\"";
2417
[1551]2418                // NOTE: do not export pvss for interior view cells because
[870]2419                // they can be completely reconstructed from the leaf pvss
[1551]2420                // on the other hand: we could store a tag with the compression scheme,
2421        // then some scheme were pvs is in the interiors could be used
[1890]2422                if (exportPvs)
2423                {
2424                        ExportPvs(viewCell, stream);
2425                }
2426
[651]2427                stream << "\" >" << endl;
2428
[837]2429                //-- recursivly export child view cells
[610]2430                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2431
2432                for (it = interior->mChildren.begin(); it != it_end; ++ it)
2433                {
[844]2434                        ExportViewCell(*it, stream, exportPvs);
[610]2435                }
2436
2437                stream << "</Interior>" << endl;
2438        }
2439}
2440
2441
[660]2442void ViewCellsTree::ResetPvs()
2443{
2444        stack<ViewCell *> tstack;
[610]2445
[660]2446        tstack.push(mRoot);
2447
2448        while (!tstack.empty())
2449        {
2450                ViewCell *vc = tstack.top();
2451                tstack.pop();
2452
[1189]2453                vc->GetPvs().Clear();
[666]2454               
[660]2455                if (!vc->IsLeaf())
2456                {
[2017]2457                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(vc);
[660]2458                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
[666]2459
[660]2460                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2461                        {
2462                                tstack.push(*it);
2463                        }
2464                }
2465        }
2466}
2467
2468
[1551]2469void ViewCellsTree::SetViewCellsManager(ViewCellsManager *vcm)
2470{
2471        mViewCellsManager = vcm;
2472}
2473
2474
[660]2475void ViewCellsTree::SetActiveSetToLeaves()
2476{
[752]2477        // todo
[660]2478}
2479
[1603]2480
[1842]2481
[580]2482/**************************************************************************/
2483/*                     MergeCandidate implementation                      */
2484/**************************************************************************/
2485
2486
2487MergeCandidate::MergeCandidate(ViewCell *l, ViewCell *r):
2488mRenderCost(0),
2489mDeviationIncr(0),
2490mLeftViewCell(l),
[586]2491mRightViewCell(r),
2492mInitialLeftViewCell(l),
2493mInitialRightViewCell(r)
[580]2494{
2495        //EvalMergeCost();
2496}
2497
2498
2499void MergeCandidate::SetRightViewCell(ViewCell *v)
2500{
2501        mRightViewCell = v;
2502}
2503
2504
2505void MergeCandidate::SetLeftViewCell(ViewCell *v)
2506{
2507        mLeftViewCell = v;
2508}
2509
2510
2511ViewCell *MergeCandidate::GetRightViewCell() const
2512{
2513        return mRightViewCell;
2514}
2515
2516
2517ViewCell *MergeCandidate::GetLeftViewCell() const
2518{
2519        return mLeftViewCell;
2520}
2521
2522
2523ViewCell *MergeCandidate::GetInitialRightViewCell() const
2524{
2525        return mInitialRightViewCell;
2526}
2527
2528
2529ViewCell *MergeCandidate::GetInitialLeftViewCell() const
2530{
2531        return mInitialLeftViewCell;
2532}
2533
2534
2535bool MergeCandidate::IsValid() const
2536{
[752]2537        // if one has a parent, it was already merged
[1002]2538        return !(mLeftViewCell->GetParent() || mRightViewCell->GetParent());
[580]2539}
2540
2541
2542float MergeCandidate::GetRenderCost() const
2543{
2544        return mRenderCost;
2545}
2546
2547
2548float MergeCandidate::GetDeviationIncr() const
2549{
2550        return mDeviationIncr;
2551}
2552
2553
2554float MergeCandidate::GetMergeCost() const
2555{
2556        return mRenderCost * sRenderCostWeight +
2557                   mDeviationIncr * (1.0f - sRenderCostWeight);
2558}
2559
2560
[605]2561
[580]2562/************************************************************************/
2563/*                    MergeStatistics implementation                    */
2564/************************************************************************/
2565
2566
2567void MergeStatistics::Print(ostream &app) const
2568{
2569        app << "===== Merge statistics ===============\n";
2570
2571        app << setprecision(4);
2572
2573        app << "#N_CTIME ( Overall time [s] )\n" << Time() << " \n";
2574
2575        app << "#N_CCTIME ( Collect candidates time [s] )\n" << collectTime * 1e-3f << " \n";
2576
2577        app << "#N_MTIME ( Merge time [s] )\n" << mergeTime * 1e-3f << " \n";
2578
2579        app << "#N_NODES ( Number of nodes before merge )\n" << nodes << "\n";
2580
2581        app << "#N_CANDIDATES ( Number of merge candidates )\n" << candidates << "\n";
2582
2583        app << "#N_MERGEDSIBLINGS ( Number of merged siblings )\n" << siblings << "\n";
2584
2585        app << "#OVERALLCOST ( overall merge cost )\n" << overallCost << "\n";
2586
2587        app << "#N_MERGEDNODES ( Number of merged nodes )\n" << merged << "\n";
2588
2589        app << "#MAX_TREEDIST ( Maximal distance in tree of merged leaves )\n" << maxTreeDist << "\n";
2590
2591        app << "#AVG_TREEDIST ( Average distance in tree of merged leaves )\n" << AvgTreeDist() << "\n";
2592
2593        app << "#EXPECTEDCOST ( expected render cost )\n" << expectedRenderCost << "\n";
2594
2595        app << "#DEVIATION ( deviation )\n" << deviation << "\n";
2596
2597        app << "#HEURISTICS ( heuristics )\n" << heuristics << "\n";
2598       
2599
2600        app << "===== END OF BspTree statistics ==========\n";
[608]2601}
[860]2602
[1742]2603
[2539]2604///////////////////
[2543]2605//-- binary export functions
[2539]2606
2607void ViewCellsTree::ExportBinInterior(OUT_STREAM &stream, ViewCellInterior *interior)
2608{
[2543]2609        int type = TYPE_INTERIOR;
2610        stream.write(reinterpret_cast<char *>(&type), sizeof(int));
[1199]2611}
[2539]2612
2613
2614void ViewCellsTree::ExportBinLeaf(OUT_STREAM &stream, ViewCell *leaf)
2615{
2616        int type = TYPE_LEAF;
2617
2618        stream.write(reinterpret_cast<char *>(&type), sizeof(int));
2619
[2542]2620        int pvsSize = leaf->GetPvs().GetSize();
[2539]2621        stream.write(reinterpret_cast<char *>(&pvsSize), sizeof(int));
2622
[2542]2623        ObjectPvsIterator pit = leaf->GetPvs().GetIterator();
[2539]2624
[2542]2625        // write pvs
[2539]2626        while (pit.HasMoreEntries())
2627        {
[2543]2628                Intersectable *obj = pit.Next();
2629               
2630                int objId = obj->GetId();
2631        stream.write(reinterpret_cast<char *>(&objId), sizeof(int));
[2539]2632        }
2633}
2634
2635
2636bool ViewCellsTree::ExportBinary(OUT_STREAM &stream)
2637{
2638        // export binary version of mesh
2639        queue<ViewCell *> tStack;
2640        tStack.push(mRoot);
2641
2642        while(!tStack.empty())
2643        {
2644                ViewCell *node = tStack.front();
2645                tStack.pop();
2646               
2647                if (node->IsLeaf())
2648                {
2649                        ExportBinLeaf(stream, static_cast<ViewCellLeaf *>(node));
2650                }
2651                else
2652                {
[2542]2653                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(node);
[2539]2654
[2542]2655                        // export current interior
[2539]2656                        ExportBinInterior(stream, interior);
2657                       
[2542]2658                        // push children
2659                        ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2660
2661                        for (it = interior->mChildren.begin(); it != it_end; ++ it)
2662                        {
2663                                tStack.push(*it);
2664                        }
[2539]2665                }
2666        }
[2542]2667
[2539]2668        return true;
2669}
2670
2671
2672//////////////////
[2543]2673//-- binary import methods
[2539]2674
2675ViewCellInterior *ViewCellsTree::ImportBinInterior(IN_STREAM  &stream, ViewCellInterior *parent)
2676{
2677        ViewCellInterior *interior = new ViewCellInterior();
2678        return interior;
2679}
2680
2681
2682ViewCellLeaf *ViewCellsTree::ImportBinLeaf(IN_STREAM &stream,
2683                                                                                   ViewCellInterior *parent,
2684                                                                                   const ObjectContainer &pvsObjects)
2685{
[2544]2686        VspViewCell *leaf = new VspViewCell();
2687
2688        Intersectable *obj;
2689
[2575]2690#ifdef PERFTIMER 
[2544]2691        sPvsTimer.Entry();
[2575]2692#endif
[2543]2693        int pvsSize;
2694        stream.read(reinterpret_cast<char *>(&pvsSize), sizeof(int));
[2544]2695        stream.read(reinterpret_cast<char *>(mPvsIds), sizeof(int) * pvsSize);
[2539]2696
[2544]2697        // just add pvs dirty, there won't be any duplicates
2698        ObjectPvs &pvs = leaf->GetPvs();
2699        pvs.Reserve(pvsSize);
[2543]2700
[2539]2701        // read object ids
[2543]2702        for (int i = 0; i < pvsSize; ++ i)
[2539]2703        {       
[2544]2704                obj = pvsObjects[mPvsIds[i]];
2705                if (obj) pvs.AddSampleDirty(obj, 0);
2706        }
[2543]2707
[2575]2708#ifdef PERFTIMER
[2544]2709        sPvsTimer.Exit();
[2575]2710#endif 
[2539]2711
2712        return leaf;
2713}
2714
2715
2716ViewCell *ViewCellsTree::ImportNextNode(IN_STREAM &stream,
2717                                                                                ViewCellInterior *parent,
2718                                                                                const ObjectContainer &objects)
2719{
2720        int nodeType;
2721        stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int));
2722
2723        if (nodeType == TYPE_LEAF)
[2543]2724        {
2725                //cerr << "l";
[2539]2726                return ImportBinLeaf(stream, static_cast<ViewCellInterior *>(parent), objects);
[2543]2727        }
[2539]2728
2729        if (nodeType == TYPE_INTERIOR)
[2543]2730        {       
2731                //cerr << "i";
[2539]2732                return ImportBinInterior(stream, static_cast<ViewCellInterior *>(parent));
[2543]2733        }
[2539]2734
[2543]2735        cerr << "error! loading view cell failed!" << endl;
[2539]2736        return NULL;
2737}
2738
2739
2740bool ViewCellsTree::ImportBinary(IN_STREAM &stream, const ObjectContainer &pvsObjects)
2741{
[2543]2742        // export view cells in binary mode
[2539]2743        queue<ViewCell *> tStack;
2744
[2575]2745#ifdef PERFTIMER 
[2544]2746        sPvsTimer.Start();
[2575]2747#endif
2748       
[2544]2749        mPvsIds = new int[pvsObjects.size()];
2750
[2539]2751        // hack: we make a new root
2752        DEL_PTR(mRoot);
[2543]2753        // import root 
[2539]2754        mRoot = ImportNextNode(stream, NULL, pvsObjects);
2755
[2544]2756        //cerr << "root: " << mRoot << endl;
[2539]2757        tStack.push(mRoot);
2758
2759        while(!tStack.empty())
2760        {
2761                ViewCell *viewCell = tStack.front();
2762                tStack.pop();
2763
2764                if (!viewCell->IsLeaf())
2765                {
2766                        ViewCellInterior *interior = static_cast<ViewCellInterior *>(viewCell);
2767
2768            ViewCell *front = ImportNextNode(stream, interior, pvsObjects);
2769                        ViewCell *back = ImportNextNode(stream, interior, pvsObjects);
2770       
2771                        interior->mChildren.push_back(front);
2772                        interior->mChildren.push_back(back);
2773
2774                        tStack.push(front);                     
2775                        tStack.push(back);
2776                }
2777                else
2778                {
2779                        //cout << "l";
2780                }
2781        }
2782
[2575]2783#ifdef PERFTIMER 
[2544]2784        Debug << "needed " << sPvsTimer.TotalTime() << " secs for pvs loading" << endl;
[2575]2785#endif
2786       
[2544]2787        delete mPvsIds;
2788
[2539]2789        return true;
2790}
2791
2792
2793
2794}
Note: See TracBrowser for help on using the repository browser.