source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp @ 955

Revision 955, 123.1 KB checked in by mattausch, 18 years ago (diff)
RevLine 
[440]1#include "ViewCellsManager.h"
2#include "RenderSimulator.h"
3#include "Mesh.h"
4#include "Triangle3.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "X3dParser.h"
8#include "ViewCellBsp.h"
9#include "KdTree.h"
10#include "VspKdTree.h"
11#include "Exporter.h"
[442]12#include "VspBspTree.h"
[508]13#include "ViewCellsParser.h"
[532]14#include "Beam.h"
[540]15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
[931]17#include "BoundingBoxConverter.h"
[440]18
[931]19
[955]20
21
[863]22namespace GtpVisibilityPreprocessor {
[860]23
24
[712]25// HACK
26const static bool SAMPLE_AFTER_SUBDIVISION = true;
27const static bool TEST_EMPTY_VIEW_CELLS = false;
[517]28
[697]29
30
31template <typename T> class myless
32{
33public:
34        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
35        bool operator() (T v1, T v2) const
36        {
37                return (v1->GetMergeCost() < v2->GetMergeCost());
38        }
39};
40
[706]41//typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > FilterQueue;
[697]42
43
44
[938]45ViewCellsManager::ViewCellsManager(Environment *env):
[480]46mRenderer(NULL),
[574]47mInitialSamples(0),
[440]48mConstructionSamples(0),
49mPostProcessSamples(0),
[470]50mVisualizationSamples(0),
51mTotalAreaValid(false),
[517]52mTotalArea(0.0f),
[547]53mViewCellsFinished(false),
[562]54mMaxPvsSize(9999999),
[564]55mMinPvsSize(0), // one means only empty view cells are invalid
[719]56mMaxPvsRatio(1.0),
57mViewCellPvsIsUpdated(false)
[938]58,mEnvironment(env)
[440]59{
[542]60        mViewSpaceBox.Initialize();
[482]61        ParseEnvironment();
[580]62
[938]63        mViewCellsTree = new ViewCellsTree(this, env);
[440]64}
65
[517]66
[482]67void ViewCellsManager::ParseEnvironment()
68{
[503]69        // visualization stuff
[938]70        mEnvironment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
71        mEnvironment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
72        mEnvironment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[664]73       
[938]74        mEnvironment->GetBoolValue("ViewCells.pruneEmptyViewCells", mPruneEmptyViewCells);
[664]75
[710]76        // HACK
77        if (0)
78                mMinPvsSize = mPruneEmptyViewCells ? 1 : 0;
79        else
80                mMinPvsSize = 0;
81
[938]82        mEnvironment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]83
[938]84        mEnvironment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
85        mEnvironment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
86        mEnvironment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
[595]87
[938]88        mEnvironment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
[574]89
[938]90        mEnvironment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
91        mEnvironment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
[581]92       
[938]93        mEnvironment->GetIntValue("ViewCells.active", mNumActiveViewCells);
94        mEnvironment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
95        mEnvironment->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
96        mEnvironment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
97        mEnvironment->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
98        mEnvironment->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
99        mEnvironment->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
100        mEnvironment->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
101        mEnvironment->GetIntValue("ViewCells.renderCostEvaluationType", mRenderCostEvaluationType);
[710]102
[938]103        mEnvironment->GetBoolValue("ViewCells.exportBboxesForPvs", mExportBboxesForPvs);
104        mEnvironment->GetBoolValue("ViewCells.exportPvs", mExportPvs);
[837]105
[664]106        char buf[100];
[938]107        mEnvironment->GetStringValue("ViewCells.samplingType", buf);
[664]108
[660]109       
[664]110        if (strcmp(buf, "box") == 0)
[722]111        {
[660]112                mSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[722]113        }
[664]114        else if (strcmp(buf, "directional") == 0)
[722]115        {
[660]116                mSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
[722]117        }
[666]118        else
119        {
120                Debug << "error! wrong sampling type" << endl;
121                exit(0);
122        }
[660]123
[938]124        mEnvironment->GetStringValue("ViewCells.Evaluation.samplingType", buf);
[722]125       
126        if (strcmp(buf, "box") == 0)
127        {
128                mEvaluationSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
129        }
130        else if (strcmp(buf, "directional") == 0)
131        {
132                mEvaluationSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
133        }
134        else
135        {
136                Debug << "error! wrong sampling type" << endl;
137                exit(0);
138        }
[503]139
[938]140        mEnvironment->GetStringValue("ViewCells.renderCostEvaluationType", buf);
[728]141       
[734]142        if (strcmp(buf, "perobject") == 0)
[728]143        {
144                mRenderCostEvaluationType = ViewCellsManager::PER_OBJECT;
145        }
146        else if (strcmp(buf, "directional") == 0)
147        {
148                mRenderCostEvaluationType = ViewCellsManager::PER_TRIANGLE;
149        }
150        else
151        {
152                Debug << "error! wrong sampling type" << endl;
153                exit(0);
154        }
155
[938]156    mEnvironment->GetStringValue("ViewCells.Visualization.colorCode", buf);
[722]157
[482]158        if (strcmp(buf, "PVS") == 0)
159                mColorCode = 1;
160        else if (strcmp(buf, "MergedLeaves") == 0)
161                mColorCode = 2;
162        else if (strcmp(buf, "MergedTreeDiff") == 0)
163                mColorCode = 3;
164        else
165                mColorCode = 0;
166
[664]167
[710]168
[664]169        Debug << "***********View Cells options ****************" << endl;
170        Debug << "color code: " << mColorCode << endl;
171
172        Debug << "export rays: " << mExportRays << endl;
173        Debug << "export geometry: " << mExportGeometry << endl;
174        Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
175       
[710]176        Debug << "prune empty view cells: " << mPruneEmptyViewCells << endl;
[664]177       
178        Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
179        Debug << "construction samples: " << mConstructionSamples << endl;
180        Debug << "post process samples: " << mPostProcessSamples << endl;
181        Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
182        Debug << "visualization samples: " << mVisualizationSamples << endl;
183        Debug << "construction samples per pass: " << mSamplesPerPass << endl;
184        Debug << "export to file: " << mExportViewCells << endl;
185       
[801]186        Debug << "active view cells: " << mNumActiveViewCells << endl;
[664]187        Debug << "post process compress: " << mCompressViewCells << endl;
188        Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
189        Debug << "post process merge: " << mMergeViewCells << endl;
190        Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
191        Debug << "sampling type: " << mSamplingType << endl;
[801]192        Debug << "render cost evaluation type: " << mRenderCostEvaluationType << endl;
[728]193        Debug << "evaluation sampling type: " << mEvaluationSamplingType << endl;
[666]194        Debug << "show visualization: " << mShowVisualization << endl;
[697]195        Debug << "filter width: " << mFilterWidth << endl;
[710]196        Debug << "sample after subdivision: " << SAMPLE_AFTER_SUBDIVISION << endl;
[850]197
198        Debug << "export bounding boxes: " << mExportBboxesForPvs << endl;
199        Debug << "export pvs for view cells: " << mExportPvs << endl;
200
[664]201        Debug << endl;
[440]202}
203
[485]204
[440]205ViewCellsManager::~ViewCellsManager()
206{
[480]207        DEL_PTR(mRenderer);
[580]208
[598]209        if (!ViewCellsTreeConstructed())
210                CLEAR_CONTAINER(mViewCells);
211        else
212                DEL_PTR(mViewCellsTree);
213
[503]214        CLEAR_CONTAINER(mMeshContainer);
[440]215}
216
[859]217AxisAlignedBox3
218ViewCellsManager::GetViewCellBox(ViewCell *vc)
219{
220  Mesh *m = vc->GetMesh();
221 
222  if (m) {
223        m->ComputeBoundingBox();
224        return m->mBox;
225  }
[485]226
[859]227  AxisAlignedBox3 box;
228 
229  box.Initialize();
230 
231  if (!vc->IsLeaf()) {
232        ViewCellInterior *vci = (ViewCellInterior *) vc;
233       
234        ViewCellContainer::iterator it = vci->mChildren.begin();
235        for (; it != vci->mChildren.end(); ++it) {
236          box.Include(GetViewCellBox(*it));
237        }
238  }
239 
240  return box;
241}
242
[693]243void ViewCellsManager::CollectEmptyViewCells()
244{
245        mEmptyViewCells.clear();
246        ViewCellContainer leaves;
247        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
248
249        ViewCellContainer::const_iterator it, it_end = leaves.end();
250
251        cout << "collecting empty view cells" << endl;
[694]252       
[693]253        for (it = leaves.begin(); it != it_end; ++ it)
254        {
255                if ((*it)->GetPvs().Empty())
256                {
257                        mEmptyViewCells.push_back(*it);
258                }
259        }
[694]260        Debug << "empty view cells found: " << (int)mEmptyViewCells.size() << endl;
[693]261}
262
263
[694]264void ViewCellsManager::TestEmptyViewCells(const ObjectContainer &obj)
[693]265{
266        ViewCellContainer::const_iterator it, it_end = mEmptyViewCells.end();
267
268        char buf[50];
269        int i = 0;
270        for (it = mEmptyViewCells.begin(); it != it_end; ++ it)
271        {
272                if (!(*it)->GetPvs().Empty())
273                {
[694]274                        sprintf(buf, "empty-viewcells-%09d.x3d", i/*(*it)->GetId()*/);
[693]275                        Exporter *exporter = Exporter::GetExporter(buf);
276                       
277                        if (exporter && i < 20)
278                        {
[694]279                                Ray *pray = (*it)->mPiercingRays[0];
[728]280                                Debug << "view cell " << (*it)->GetId() << " not empty, pvs: "
281                                          << (*it)->GetPvs().GetSize() << " " << (int)pray->intersections.size() << endl;
[694]282
283                                exporter->ExportRays((*it)->mPiercingRays);
284                                                       
285                                exporter->SetFilled();
286                                exporter->SetForcedMaterial(RgbColor(0,0,1));
287
288                                for (int j = 0; j < (int)pray->intersections.size(); ++ j)
289                                {
290                                        if (pray->intersections[j].mObject)
291                                                exporter->ExportIntersectable(pray->intersections[j].mObject);
292                                }
293
294                                //exporter->SetWireframe();
295                                exporter->SetForcedMaterial(RgbColor(0,1,0));
296                                exporter->ExportGeometry(obj);
297
298                                exporter->SetFilled();
299
300                                exporter->SetForcedMaterial(RgbColor(1,0,0));
[693]301                                ExportViewCellGeometry(exporter, *it);
[694]302
303                                delete exporter;               
[693]304                        }
305
[694]306               
[693]307                        ++ i;
308                }
309        }
[694]310        Debug << "\nSampled " << i << " new view cells (" << " of " << (int)mEmptyViewCells.size() << ")" << endl << endl;
[693]311}
312
313
[574]314int ViewCellsManager::CastPassSamples(const int samplesPerPass,
315                                                                          const int sampleType,
316                                                                          VssRayContainer &passSamples) const
[527]317{
[570]318        SimpleRayContainer simpleRays;
[540]319
[573]320        preprocessor->GenerateRays(samplesPerPass,
321                                                           sampleType,
[570]322                                                           simpleRays);
[564]323
[573]324        // shoot simple ray and add it to importance samples
325        preprocessor->CastRays(simpleRays, passSamples);
[570]326
[574]327        return (int)passSamples.size();
328}
[570]329
[574]330
[607]331
[574]332/// helper function which destroys rays or copies them into the output ray container
[639]333inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
[574]334{
335        cout << "disposing samples ... ";
[582]336        long startTime = GetTime();
337        int n = (int)rays.size();
338
[573]339        if (outRays)
[542]340        {
[574]341                VssRayContainer::const_iterator it, it_end = rays.end();
342
343                for (it = rays.begin(); it != it_end; ++ it)
344                {
345                        outRays->push_back(*it);
346                }
[573]347        }
348        else
349        {
[639]350                VssRayContainer::const_iterator it, it_end = rays.end();
351
352                for (it = rays.begin(); it != it_end; ++ it)
353                {
354                        //(*it)->Unref();
355                        if (!(*it)->IsActive())
356                                delete (*it);
357                }
[573]358        }
[639]359
[574]360        cout << "finished" << endl;
[582]361        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[573]362}
[570]363
364
[573]365int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
366{
367        int numSamples = 0;
368        SimpleRayContainer simpleRays;
369       
[574]370        VssRayContainer initialSamples;
[540]371
[574]372        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
[712]373
[752]374        long startTime = GetTime();
375
[573]376        //-- construction rays => we use uniform samples for this
[574]377        CastPassSamples(mInitialSamples,
[660]378                                        mSamplingType,
[574]379                                        initialSamples);
[573]380       
[574]381        cout << "finished" << endl;
382
[660]383       
[573]384        // construct view cells
[752]385        ConstructSubdivision(preprocessor->mObjects, initialSamples);
[540]386
[727]387        // initial samples count for overall samples ...
[752]388        numSamples += mInitialSamples;
[542]389
[574]390        // rays can be passed or deleted
[639]391        disposeRays(initialSamples, outRays);
[752]392
393        cout << "time needed for initial construction: "
394                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
395
396        Debug << "time needed for initial construction: "
397                  << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
398
399
400        // take post processing time
401        startTime = GetTime();
402
403
[720]404        // testing the view cell filter functionality   
405        if (0) TestFilter(preprocessor->mObjects);
[570]406
[660]407        // -- stats after contruction
408        ResetViewCells();
409
[667]410        Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
411
[683]412        if (1) // export initial view cells
[660]413        {
[712]414                const char filename[] = "view_cells.wrl";
415                Exporter *exporter = Exporter::GetExporter(filename);
[660]416
[712]417       
[660]418                if (exporter)
419                {
[712]420                        cout << "exporting initial view cells (=leaves) to " << filename << " ... ";
[660]421                        if (mExportGeometry)
[712]422                        {
[660]423                                exporter->ExportGeometry(preprocessor->mObjects);
[712]424                        }
[660]425
[750]426                        exporter->SetWireframe();
[660]427                        ExportViewCellsForViz(exporter);
428
429                        delete exporter;
[712]430                        cout << "finished" << endl;
[660]431                }
432        }
433
[573]434        //-- guided rays are used for further sampling
[574]435        const int n = mConstructionSamples; //+initialSamples;
[570]436
[666]437        // should we use directional samples?
[694]438        bool dirSamples = (mSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
[573]439
[712]440        // -- the main loop
[573]441        while (numSamples < n)
442        {
[596]443                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
[727]444                Debug << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
445
[574]446                VssRayContainer constructionSamples;
447
[694]448                const int samplingType = mSamplingType;
449                        /*dirSamples ?
[574]450                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
[694]451                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;*/
[667]452
[720]453                if (0) dirSamples = !dirSamples; // toggle sampling method
[667]454
[727]455                // cast new samples
[574]456                numSamples += CastPassSamples(mSamplesPerPass,
[666]457                                                                          samplingType,
[574]458                                                                          constructionSamples);
459
460                cout << "finished" << endl;
461
462                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
463
[727]464                // computes sample contribution of cast rays TODO: leak?
465                if (SAMPLE_AFTER_SUBDIVISION)
[605]466                        ComputeSampleContributions(constructionSamples, true, false);
[712]467
[574]468                cout << "finished" << endl;
469
470
[639]471                disposeRays(constructionSamples, outRays);
[574]472
473                cout << "total samples: " << numSamples << endl;
[542]474        }
[752]475
[573]476       
[570]477
[573]478        //-- post processing
479        VssRayContainer postProcessSamples;
[570]480
[694]481        //-- construction rays
[574]482        CastPassSamples(mPostProcessSamples,
[694]483                                        mSamplingType,
[574]484                                        postProcessSamples);
[660]485
486
487        // stats before post processing (i.e., merge)
488        EvaluateViewCellsStats();
489        Debug << "\noriginal view cell partition before post process:\n" << mCurrentViewCellsStats << endl;
490
491        mRenderer->RenderScene();
492        SimulationStatistics ss;
493        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
494
495    Debug << ss << endl;
496
497
498
[574]499        cout << "starting post processing and visualization" << endl;
500
[660]501
[666]502        // store view cells for postprocessing
[574]503        const bool storeViewCells = true;
[605]504
[660]505
[605]506        if (SAMPLE_AFTER_SUBDIVISION)
507                ComputeSampleContributions(postProcessSamples, true, storeViewCells);
[663]508
[720]509        //-- post processing (e.g.,merging) of the view cells
[573]510        PostProcess(preprocessor->mObjects, postProcessSamples);
[570]511
[955]512        cout << "time needed for post processing (merge) step: "
[752]513                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
514
[955]515        Debug << "time needed for post processing (merge) step: "
[752]516                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
517
[720]518        // only for debugging purpose
[694]519        if (TEST_EMPTY_VIEW_CELLS)
520                CollectEmptyViewCells();
[801]521       
522        // evaluation of the paritition, i.e., a number of new samples are cast
523        if (mEvaluateViewCells)
524        {
525                EvalViewCellPartition(preprocessor);
526        }
527       
[574]528        //-- visualization
[666]529        if (mShowVisualization)
530        {
531                VssRayContainer visualizationSamples;
[574]532
[666]533                //-- construction rays => we use uniform samples for this
534                CastPassSamples(mVisualizationSamples,
535                                            Preprocessor::DIRECTION_BASED_DISTRIBUTION,
536                                                visualizationSamples);
[574]537
[666]538                if (SAMPLE_AFTER_SUBDIVISION)
539                        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
[574]540
[666]541                // different visualizations
542                Visualize(preprocessor->mObjects, visualizationSamples);
[574]543
[666]544                disposeRays(visualizationSamples, outRays);
545        }
[574]546
[573]547        return numSamples;
[527]548}
549
[547]550
[752]551void ViewCellsManager::EvalViewCellHistogram(const string filename,
552                                                                                         const int nViewCells)
[728]553{
554        std::ofstream outstream;
555        outstream.open(filename.c_str());
556
557        ViewCellContainer viewCells;
[735]558        mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
[728]559
560        float maxRenderCost, minRenderCost;
[734]561
562        // sort by render cost
563        sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerRenderCost);
564
565        minRenderCost = viewCells.front()->GetRenderCost();
566        maxRenderCost = viewCells.back()->GetRenderCost();
567
[736]568        Debug << "histogram minrc: " << minRenderCost << " maxrc: " << maxRenderCost << endl;
569
[752]570        const int intervals = min(50, (int)viewCells.size());
[735]571
[728]572        const float range = maxRenderCost - minRenderCost;
[735]573        const float stepSize = range / (float)intervals;
[728]574
[735]575        float currentRenderCost = minRenderCost;//(int)ceil(minRenderCost);
576
577        const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
578        const float totalVol = GetViewSpaceBox().GetVolume();
[736]579        //const float totalVol = mViewCellsTree->GetRoot()->GetVolume();
[735]580
[736]581        //float vol = 0;
582        //int smallerCost = 0;
583        int j = 0;
[735]584        int i = 0;
585       
[734]586        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();             
587
[744]588        // count for integral
589        float volSum = 0;
590        int smallerCostSum = 0;
[735]591       
[734]592        // note can skip computations for view cells already evaluated and delete them from vector ...
593    while (1)
594        {
[744]595                // count for histogram value
596                float volDif = 0;
597                int smallerCostDif = 0;
[736]598
[734]599                while ((i < (int)viewCells.size()) && (viewCells[i]->GetRenderCost() < currentRenderCost))
600                {
[744]601                        volSum += viewCells[i]->GetVolume();
602                        volDif += viewCells[i]->GetVolume();
603
[734]604                        ++ i;
[744]605                        ++ smallerCostSum;
606                        ++ smallerCostDif;
[734]607                }
[736]608               
[744]609                if ((i >= (int)viewCells.size()) || (currentRenderCost >= maxRenderCost))
[735]610                        break;
[736]611               
[744]612                const float rcRatio = currentRenderCost / maxRenderCost;
613                const float volRatioSum = volSum / totalVol;
614                const float volRatioDif = volDif / totalVol;
[735]615
[736]616                outstream << "#Pass\n" << j << endl;
617                outstream << "#RenderCostRatio\n" << rcRatio << endl;
618                outstream << "#WeightedCost\n" << currentRenderCost / totalVol << endl;
[744]619                outstream << "#ViewCellsDif\n" << smallerCostDif << endl;
620                outstream << "#ViewCellsSum\n" << smallerCostSum << endl;       
621                outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
622                outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
[735]623
624                // increase current render cost
[734]625                currentRenderCost += stepSize;
[736]626                ++ j;
[734]627        }
[735]628
[734]629        outstream.close();
630}
631
[735]632
633void ViewCellsManager::EvalViewCellHistogramForPvsSize(const string filename,
634                                                                                                           const int nViewCells)
[734]635{
636        std::ofstream outstream;
637        outstream.open(filename.c_str());
638
639        ViewCellContainer viewCells;
[735]640        mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
[734]641
[735]642        int maxPvsSize, minPvsSize;
[734]643
[735]644        // sort by render cost
645        sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerPvs);
646
647        minPvsSize = viewCells.front()->GetPvs().GetSize();
648        maxPvsSize = viewCells.back()->GetPvs().GetSize();
[752]649        minPvsSize = 0;
650        maxPvsSize = 1200;
[811]651        minPvsSize = 0;
652        maxPvsSize = 1200;
[752]653
[736]654        Debug << "histogram minpvssize: " << minPvsSize << " maxpvssize: " << maxPvsSize << endl;
[735]655
[752]656        const int intervals = min(20, (int)viewCells.size());
[735]657        const int range = maxPvsSize - minPvsSize;
658        int stepSize = range / intervals;
659
[752]660       
[735]661        if (!stepSize) stepSize = 1;
[752]662Debug << "stepsize: " << stepSize << endl;
663        cout << "stepsize: " << stepSize << endl;
[735]664
665        const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
666        const float totalVol = GetViewSpaceBox().GetVolume();
667
668        int currentPvsSize = minPvsSize;//(int)ceil(minRenderCost);
669
[736]670        //float vol = 0;
[735]671        int i = 0;
672        int j = 0;
[734]673
[744]674        float volSum = 0;
675        int smallerSum = 0;
676
[735]677        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();             
678       
[736]679        while (1)
[728]680        {
[744]681                float volDif = 0;
682                int smallerDif = 0;
[736]683
[735]684                while ((i < (int)viewCells.size()) && (viewCells[i]->GetPvs().GetSize() < currentPvsSize))
685                {
[744]686                        volDif += viewCells[i]->GetVolume();
687                        volSum += viewCells[i]->GetVolume();
[735]688                        ++ i;
[744]689                        ++ smallerDif;
690                        ++ smallerSum;
[735]691                }
[736]692               
[744]693                //if (i < (int)viewCells.size())
694                //      Debug << "new pvs size increase: " << viewCells[i]->GetPvs().GetSize() << " " << currentPvsSize << endl;
[728]695
[735]696                if ((i >= (int)viewCells.size()) || (currentPvsSize >= maxPvsSize))
697                        break;
[728]698
[744]699                const float volRatioDif = volDif / totalVol;
700                const float volRatioSum = volSum / totalVol;
[728]701
[735]702                outstream << "#Pass\n" << j ++ << endl;
703                outstream << "#Pvs\n" << currentPvsSize << endl;
[744]704                outstream << "#ViewCellsDif\n" << smallerDif << endl;
705                outstream << "#ViewCellsSum\n" << smallerSum << endl;   
706                outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
707                outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
[729]708
[735]709                // increase current pvs size
710                currentPvsSize += stepSize;
[728]711        }
[735]712        outstream.close();
[728]713}
714
[735]715
[664]716void ViewCellsManager::EvalViewCellPartition(Preprocessor *preprocessor)
[660]717{
718        int samplesPerPass;
719        int numSamples;
720        int castSamples = 0;
721
[664]722        char s[64];
723
[938]724        mEnvironment->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
725        mEnvironment->GetIntValue("ViewCells.Evaluation.samples", numSamples);
[660]726
[664]727        char statsPrefix[100];
[938]728        mEnvironment->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
[663]729
[664]730        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
731        Debug << "view cell evaluation samples: " << numSamples << endl;
732        Debug << "view cell stats prefix: " << statsPrefix << endl;
733
734        //VssRayContainer outRays;
[666]735        // should directional sampling be used?
[722]736        bool dirSamples = (mEvaluationSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
[664]737
738
[801]739/*ViewCellContainer leaves;
740mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
741*/     
742        cout << "reseting pvs ... ";
743               
744
[666]745        bool startFromZero = true;
746
747        // reset pvs and start over from zero
748        if (startFromZero)
749        {
750                mViewCellsTree->ResetPvs();
751        }
752        else // statistics without addidtional samples
753        {
754                cout << "compute new statistics ... ";
755                sprintf(s, "-%09d-eval.log", castSamples);
756                string fName = string(statsPrefix) + string(s);
757
758                mViewCellsTree->ExportStats(fName);
759                cout << "finished" << endl;
760        }
761       
[744]762        cout << "finished" << endl;
763
764        cout << "Evaluating view cell partition" << endl;
765
[660]766        while (castSamples < numSamples)
767        {
[664]768                VssRayContainer evaluationSamples;
[663]769
[722]770                const int samplingType = mEvaluationSamplingType;
[666]771                /*      dirSamples ?
[664]772                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
773                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[666]774                */
[664]775                //-- construction rays => we use uniform samples for this
[744]776                cout << "casting " << samplesPerPass << " samples " << endl;
[664]777                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
778               
779                castSamples += samplesPerPass;
780
[752]781                cout << "computing sample contributions of " << (int)evaluationSamples.size()
782                         << " samples " << endl;
[664]783
784                ComputeSampleContributions(evaluationSamples, true, false);
785
786                cout << "compute new statistics ... ";
787
[801]788/*Debug << "*******+" << endl;
789float overall = 0;
790stable_sort(leaves.begin(), leaves.end(), ViewCell::SmallerPvs);
791        for (int i = 0; i < leaves.size(); ++ i)
792        {
793                overall += leaves[i]->GetPvs().GetSize();
794                Debug << "i " << i << " !size: " << leaves[i]->GetPvs().GetSize() << " vol: " << leaves[i]->GetVolume() << " overall " << overall << endl;
795               
796        }
797*/
798
799                //-- propagate pvs or pvs size information
[752]800                ObjectPvs pvs;
801                UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
[664]802
803
[801]804                //-- output stats
[667]805                sprintf(s, "-%09d-eval.log", castSamples);
[664]806                string fileName = string(statsPrefix) + string(s);
807
808                mViewCellsTree->ExportStats(fileName);
809
810                cout << "finished" << endl;
811       
812                disposeRays(evaluationSamples, NULL);
[660]813        }
[728]814       
[735]815        bool useHisto;
816        int histoPasses;
[693]817
[938]818        mEnvironment->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
819        mEnvironment->GetIntValue("ViewCells.Evaluation.histoPasses", histoPasses);
[728]820
[744]821        const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
[736]822
[822]823        //Debug << "number of leaves: " << numLeaves << endl;
824        //cout << "number of leaves: " << numLeaves << endl;
[736]825
[735]826        if (useHisto)
[734]827        {
[735]828                // evaluate view cells in a histogram           
829                char s[64];
[744]830#if 0
[735]831                for (int passes = 1; passes <= histoPasses; ++ passes)
832                {
[736]833                        int n = numLeaves * passes / histoPasses;
[734]834               
[735]835                        cout << "computing histogram for " << n << " view cells" << endl;
836
837                        //-- evaluate histogram for render cost
838                        sprintf(s, "-%09d-histo.log", n);
839                        string filename = string(statsPrefix) + string(s);
840
841                        EvalViewCellHistogram(filename, n);
842
843                        //////////////////////////////////////////
844            // --evaluate histogram for pvs size
845
846                        cout << "computing pvs histogram for " << n << " view cells" << endl;
847
848                        sprintf(s, "-%09d-histo-pvs.log", n);
849                        filename = string(statsPrefix) + string(s);
850
851                        EvalViewCellHistogramForPvsSize(filename, n);
852                }
[744]853#else
[752]854                for (int pass = histoPasses; pass <= numLeaves; pass += histoPasses)
[744]855                {
856                        cout << "computing histogram for " << pass << " view cells" << endl;
857
858                        //-- evaluate histogram for render cost
859                        sprintf(s, "-%09d-histo.log", pass);
860                        string filename = string(statsPrefix) + string(s);
861
862                        EvalViewCellHistogram(filename, pass);
863
864                        //////////////////////////////////////////
[752]865            //-- evaluate histogram for pvs size
[744]866
867                        cout << "computing pvs histogram for " << pass << " view cells" << endl;
868
869                        sprintf(s, "-%09d-histo-pvs.log", pass);
870                        filename = string(statsPrefix) + string(s);
871
872                        EvalViewCellHistogramForPvsSize(filename, pass);
873                }
874#endif
[734]875        }
876
[693]877        // find empty view cells bug
[694]878        if (TEST_EMPTY_VIEW_CELLS)
[719]879        {
[694]880                TestEmptyViewCells(preprocessor->mObjects);
[719]881        }
[660]882}
883
[704]884
885inline float EvalMergeCost(ViewCell *root, ViewCell *candidate)
[703]886{
[704]887        return root->GetPvs().GetPvsHomogenity(candidate->GetPvs());
888}
[660]889
[703]890
[728]891// Returns index of the best view cells of the neighborhood
[704]892int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
893{
[705]894        int bestViewCellIdx = 0;
[703]895
[704]896        float mergeCost = Limits::Infinity;
897        int i = 0;
[703]898
[734]899        ViewCellContainer::const_iterator vit, vit_end = neighborhood.end();
[703]900
[734]901        for (vit = neighborhood.begin(); vit != vit_end; ++ vit, ++ i)
[703]902        {
[734]903                const float mc = EvalMergeCost(root, *vit);
[705]904               
905                if (mc < mergeCost)
[704]906                {
907                        mergeCost = mc;
908                        bestViewCellIdx = i;
[703]909                }
[704]910        }
[703]911
[704]912        return bestViewCellIdx;
913}
[703]914
915
[728]916void ViewCellsManager::SetMaxFilterSize(const int size)
917{
918        mMaxFilterSize = size;
919}
920
921
922float ViewCellsManager::EvalRenderCost(Intersectable *obj) const
923{
924        switch (mRenderCostEvaluationType)
925        {
926        case PER_OBJECT:
[752]927                //cout << "perobject" << endl;
928                return 1.0f;
[728]929       
930        case PER_TRIANGLE:
[735]931                {cout << "pertriangle" << endl;
[728]932                        // HACK
933                        MeshInstance *mi = dynamic_cast<MeshInstance *>(obj);
934
935                        // HACK: assume meshes are triangles
936                        if (mi->GetMesh())
937                        {
938                                return mi->GetMesh()->mFaces.size();
939                        }
940                }
941        default:
[752]942                cout << "default" << endl;
943                return 1.0f;
[728]944        }
945
946        // should not come here
[752]947        return 0.0f;
[728]948}
949
950
[704]951ViewCell *ViewCellsManager::ConstructLocalMergeTree(ViewCell *currentViewCell,
952                                                                                                        const ViewCellContainer &viewCells)
953{
954        ViewCell *root = currentViewCell;
955        ViewCellContainer neighborhood = viewCells;
[703]956
[704]957        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
[703]958
[704]959        const int n = min(mMaxFilterSize, (int)neighborhood.size());
960        //-- use priority queue to merge leaf pairs
[703]961
[705]962        //cout << "neighborhood: " << neighborhood.size() << endl;
[704]963        //const float maxAvgCost = 350;
964        for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
[703]965        {
[704]966                const int bestViewCellIdx = GetBestViewCellIdx(root, neighborhood);
[703]967               
[704]968                ViewCell *bestViewCell = neighborhood[bestViewCellIdx];
[706]969       
[704]970                // remove from vector
971                swap(neighborhood[bestViewCellIdx], neighborhood.back());
972                neighborhood.pop_back();
[705]973       
[713]974                //              cout << "vc idx: " << bestViewCellIdx << endl;
[704]975                if (!bestViewCell || !root)
976                        cout << "warning!!" << endl;
[705]977               
[704]978                // create new root of the hierarchy
979                root = MergeViewCells(root, bestViewCell);
[703]980        }
981
[704]982        return root;   
[703]983}
984
[704]985
[713]986struct SortableViewCellEntry {
987
988  SortableViewCellEntry() {}
989  SortableViewCellEntry(const float v, ViewCell *cell):mValue(v), mViewCell(cell) {}
990 
991  float mValue;
992  ViewCell *mViewCell;
993
994  friend bool operator<(const SortableViewCellEntry &a, const SortableViewCellEntry &b) {
995        return a.mValue < b.mValue;
996  }
997};
998
999ViewCell *
1000ViewCellsManager::ConstructLocalMergeTree2(ViewCell *currentViewCell,
1001                                                                                   const ViewCellContainer &viewCells)
1002{
1003 
1004  vector<SortableViewCellEntry> neighborhood(viewCells.size());
1005  int i, j;
1006  for (i = 0, j = 0; i < viewCells.size(); i++) {
1007        if (viewCells[i] != currentViewCell)
1008          neighborhood[j++] = SortableViewCellEntry(
1009                                                                                                EvalMergeCost(currentViewCell, viewCells[i]),
1010                                                                                                viewCells[i]);
1011  }
1012  neighborhood.resize(j);
1013 
1014  sort(neighborhood.begin(), neighborhood.end());
1015 
1016  ViewCell *root = currentViewCell;
1017 
1018  vector<SortableViewCellEntry>::const_iterator it, it_end = neighborhood.end();
1019 
1020  const int n = min(mMaxFilterSize, (int)neighborhood.size());
1021  //-- use priority queue to merge leaf pairs
1022 
1023  //cout << "neighborhood: " << neighborhood.size() << endl;
1024  for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
[728]1025  {
[713]1026          ViewCell *bestViewCell = neighborhood[nMergedViewCells].mViewCell;
1027          //cout <<nMergedViewCells<<":"<<"homogenity=" <<neighborhood[nMergedViewCells].mValue<<endl;
1028          // create new root of the hierarchy
1029          root = MergeViewCells(root, bestViewCell);
1030          // set negative cost so that this view cell gets deleted
1031          root->SetMergeCost(-1.0f);
[728]1032  }
[713]1033 
1034  return root; 
1035}
1036
1037void
1038ViewCellsManager::DeleteLocalMergeTree(ViewCell *vc
1039                                                                           ) const
1040{
1041  if (!vc->IsLeaf() && vc->GetMergeCost() < 0.0f) {
1042        ViewCellInterior *vci = (ViewCellInterior *) vc;
1043        ViewCellContainer::const_iterator it, it_end = vci->mChildren.end();
1044       
1045        for (it = vci->mChildren.begin(); it != it_end; ++ it)
1046          DeleteLocalMergeTree(*it);
1047        vci->mChildren.clear();
1048        delete vci;
1049  }
1050}
1051
[564]1052bool ViewCellsManager::CheckValidity(ViewCell *vc,
1053                                                                         int minPvsSize,
[562]1054                                                                         int maxPvsSize) const
[547]1055{
[569]1056
[710]1057        if ((vc->GetPvs().GetSize() > maxPvsSize) ||
1058                (vc->GetPvs().GetSize() < minPvsSize))
[564]1059        {
[710]1060                return false;
[561]1061        }
[570]1062
[710]1063        return true;
[547]1064}
1065
1066
[710]1067bool ViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
1068{
1069        return false;
1070}
1071
1072int ViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
1073                                                                                          ViewCellContainer &viewCells) const
1074{
1075        return 0;
1076};
1077
[697]1078AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
1079                                                                                                const float width) const
1080{
[746]1081  float w = Magnitude(mViewSpaceBox.Size())*width;
1082  Vector3 min = viewPoint - w * 0.5f;
1083  Vector3 max = viewPoint + w * 0.5f;
1084 
1085  return AxisAlignedBox3(min, max);
[697]1086}
1087
1088
[904]1089void ViewCellsManager::GetPrVS(const Vector3 &viewPoint,
1090                                                           PrVs &prvs,
1091                                                           const float filterWidth)
[697]1092{
[904]1093  const AxisAlignedBox3 box = GetFilterBBox(viewPoint, filterWidth);
[746]1094       
1095  ViewCell *currentViewCell = GetViewCell(viewPoint);
[697]1096
[746]1097  if (currentViewCell) {
[697]1098        ViewCellContainer viewCells;
1099        ComputeBoxIntersections(box, viewCells);
[746]1100       
[713]1101        ViewCell *root = ConstructLocalMergeTree2(currentViewCell, viewCells);
[704]1102        prvs.mViewCell = root;
[746]1103  } else
1104        prvs.mViewCell = NULL;
1105  //prvs.mPvs = root->GetPvs();
[697]1106}
1107
1108
[581]1109bool ViewCellsManager::ViewCellsTreeConstructed() const
1110{
1111        return mViewCellsTree->GetRoot();
1112}
1113
1114
[564]1115void ViewCellsManager::SetValidity(ViewCell *vc,
1116                                                                   int minPvs,
[562]1117                                                                   int maxPvs) const
1118{
1119        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
1120}
1121
[577]1122
[569]1123void
1124ViewCellsManager::SetValidity(
[570]1125                                                          int minPvsSize,
[569]1126                                                          int maxPvsSize) const
1127{
1128  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[570]1129
[569]1130  for (it = mViewCells.begin(); it != it_end; ++ it) {
1131        SetValidity(*it, minPvsSize, maxPvsSize);
1132  }
1133}
[562]1134
[569]1135void
1136ViewCellsManager::SetValidityPercentage(
1137                                                                                const float minValid,
1138                                                                                const float maxValid
1139                                                                                )
1140{
1141  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[570]1142
[569]1143  int start = mViewCells.size()*minValid;
1144  int end = mViewCells.size()*maxValid;
[570]1145
[569]1146  for (int i=0; i < mViewCells.size(); i++)
1147        mViewCells[i]->SetValid(i >= start && i <= end);
1148}
1149
1150int
1151ViewCellsManager::CountValidViewcells() const
1152{
1153  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1154  int valid = 0;
1155  for (it = mViewCells.begin(); it != it_end; ++ it) {
1156        if ((*it)->GetValid())
[706]1157          valid ++;
[569]1158  }
1159  return valid;
1160}
1161
[577]1162
1163bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
[440]1164{
1165        X3dParser parser;
[503]1166
[938]1167        mEnvironment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]1168
[440]1169        bool success = parser.ParseFile(filename, *this);
1170        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
1171
1172        return success;
1173}
1174
[485]1175
[487]1176bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
1177{
[542]1178        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]1179
1180        return true;
1181}
1182
1183
[557]1184float ViewCellsManager::GetViewSpaceVolume()
1185{
[610]1186        return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
[557]1187}
1188
1189
[490]1190bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
1191{
[569]1192  if (!ViewCellsConstructed())
[837]1193          return mViewSpaceBox.IsInside(viewPoint);
1194  else
1195  {
1196          if (!mViewSpaceBox.IsInside(viewPoint))
1197                  return false;
1198         
1199          ViewCell *viewcell = GetViewCell(viewPoint);
1200         
1201          if (!viewcell || !viewcell->GetValid())
1202                  return false;
[569]1203  }
[837]1204
[569]1205  return true;
[490]1206}
1207
[501]1208
[563]1209float
1210ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
[574]1211                                                                                         const bool addRays,
1212                                                                                         const bool storeViewCells
[563]1213                                                                                         )
[440]1214{
[563]1215  // view cells not yet constructed
1216  if (!ViewCellsConstructed())
1217        return 0.0f;
[564]1218
[563]1219  VssRayContainer::const_iterator it, it_end = rays.end();
[503]1220
[563]1221  float sum = 0.0f;
[664]1222  for (it = rays.begin(); it != it_end; ++ it)
1223  {
1224          sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
1225          //ComputeSampleContributions(*(*it), addRays);
1226          //    sum += (*it)->mPvsContribution;
[563]1227  }
[664]1228
[563]1229  return sum;
[440]1230}
1231
[485]1232
[479]1233void ViewCellsManager::EvaluateViewCellsStats()
1234{
[660]1235        mCurrentViewCellsStats.Reset();
[479]1236
1237        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1238
1239        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]1240        {
[660]1241                mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
[487]1242        }
[479]1243}
1244
[485]1245
[580]1246void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
[579]1247                                                                                                float &expectedRenderCost,
[580]1248                                                                                                float &deviation,
1249                                                                                                float &variance,
1250                                                                                                int &totalPvs,
1251                                                                                                float &avgRenderCost)
[579]1252{
1253        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1254
[580]1255
[579]1256        //-- compute expected value
1257
1258        totalRenderCost = 0;
[580]1259        totalPvs = 0;
[579]1260
1261        for (it = mViewCells.begin(); it != it_end; ++ it)
1262        {
1263                ViewCell *vc = *it;
1264                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
[580]1265                totalPvs += (int)vc->GetPvs().GetSize();
[579]1266        }
1267
[580]1268        // normalize with view space box
1269        totalRenderCost /= mViewSpaceBox.GetVolume();
[579]1270        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
[580]1271        avgRenderCost = totalPvs / (float)mViewCells.size();
[579]1272
1273
[580]1274        //-- compute standard defiation
[579]1275        variance = 0;
[580]1276        deviation = 0;
[579]1277
1278        for (it = mViewCells.begin(); it != it_end; ++ it)
1279        {
1280                ViewCell *vc = *it;
1281
1282                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
[580]1283                float dev;
[579]1284
[580]1285                if (1)
1286                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
1287                else
1288                        dev = fabs(expectedRenderCost - renderCost);
[579]1289
[580]1290                deviation += dev;
1291                variance += dev * dev;
[579]1292        }
[580]1293
[579]1294        variance /= (float)mViewCells.size();
[580]1295        deviation /= (float)mViewCells.size();
[579]1296}
1297
1298
1299
[440]1300void ViewCellsManager::AddViewCell(ViewCell *viewCell)
1301{
1302        mViewCells.push_back(viewCell);
1303}
1304
[485]1305
[478]1306float ViewCellsManager::GetArea(ViewCell *viewCell) const
1307{
1308        return viewCell->GetArea();
1309}
1310
1311
1312float ViewCellsManager::GetVolume(ViewCell *viewCell) const
1313{
1314        return viewCell->GetVolume();
1315}
1316
[485]1317
[503]1318void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
1319                                                                           ViewCellContainer &viewCells,
[440]1320                                                                           const int maxViewCells) const
1321{
1322        // maximal max viewcells
[503]1323        int limit = maxViewCells > 0 ?
[440]1324                Min((int)objects.size(), maxViewCells) : (int)objects.size();
1325
1326        for (int i = 0; i < limit; ++ i)
1327        {
1328                Intersectable *object = objects[i];
[503]1329
[440]1330                // extract the mesh instances
1331                if (object->Type() == Intersectable::MESH_INSTANCE)
1332                {
1333                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
1334
1335                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
1336                        viewCells.push_back(viewCell);
1337                }
1338                //TODO: transformed meshes
1339        }
1340}
1341
[485]1342
[503]1343ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]1344                                                                                        const float height) const
1345{
1346        // one mesh per view cell
1347        Mesh *mesh = new Mesh();
[503]1348
[440]1349        //-- construct prism
1350
[503]1351        // bottom
[440]1352        mesh->mFaces.push_back(new Face(2,1,0));
1353        // top
1354    mesh->mFaces.push_back(new Face(3,4,5));
1355        // sides
1356        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
1357        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
1358        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
1359
1360        //--- extrude new vertices for top of prism
1361        Vector3 triNorm = baseTri.GetNormal();
1362
[503]1363        Triangle3 topTri;
[440]1364
1365        // add base vertices and calculate top vertices
1366        for (int i = 0; i < 3; ++ i)
1367                mesh->mVertices.push_back(baseTri.mVertices[i]);
[503]1368
1369        // add top vertices
[440]1370        for (int i = 0; i < 3; ++ i)
1371                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]1372
[440]1373        mesh->Preprocess();
1374
1375        return GenerateViewCell(mesh);
1376}
1377
[485]1378
[551]1379void ViewCellsManager::FinalizeViewCells(const bool createMesh)
1380{
1381        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[693]1382
1383        // volume and area of the view cells are recomputed and a view cell mesh is created
[551]1384        for (it = mViewCells.begin(); it != it_end; ++ it)
1385        {
1386                Finalize(*it, createMesh);
1387        }
[555]1388
1389        mTotalAreaValid = false;
[551]1390}
1391
1392
1393void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
1394{
1395        // implemented in subclasses
1396}
1397
[752]1398// fast way of merging 2 view cells
[582]1399ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
[440]1400{
[580]1401        // generate parent view cell
[752]1402        ViewCellInterior *vc = new ViewCellInterior();
[710]1403
[752]1404        vc->GetPvs().Clear();
[610]1405        vc->GetPvs() = left->GetPvs();
[752]1406
1407        // merge pvs of right cell
[610]1408        vc->GetPvs().Merge(right->GetPvs());
[440]1409
[462]1410        //-- merge ray sets
[564]1411        if (0)
1412        {
[582]1413                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
1414                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
[440]1415
[582]1416                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
1417                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
[564]1418                                   vc->mPiercingRays.begin());
1419        }
[440]1420
[710]1421        // set only links to child (not from child to parent, maybe not wished!!)
1422        vc->mChildren.push_back(left);
1423        vc->mChildren.push_back(right);
1424
[752]1425        // update pvs size
1426        vc->mPvsSize = vc->GetPvs().GetSize();
1427        vc->mPvsSizeValid = true;
1428
[440]1429        return vc;
1430}
1431
[485]1432
[582]1433ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
1434{
[752]1435        ViewCellInterior *vc = new ViewCellInterior();
[582]1436
1437        ViewCellContainer::const_iterator it, it_end = children.end();
1438
1439        for (it = children.begin(); it != it_end; ++ it)
1440        {
1441                // merge pvs
[610]1442                vc->GetPvs().Merge((*it)->GetPvs());
[710]1443                vc->mChildren.push_back(*it);
[582]1444        }
1445
1446        return vc;
1447}
1448
1449
[480]1450void ViewCellsManager::SetRenderer(Renderer *renderer)
1451{
1452        mRenderer = renderer;
1453}
[441]1454
[485]1455
[580]1456ViewCellsTree *ViewCellsManager::GetViewCellsTree()
[440]1457{
[580]1458        return mViewCellsTree;
[440]1459}
1460
1461
1462void ViewCellsManager::SetVisualizationSamples(const int visSamples)
1463{
[444]1464        mVisualizationSamples = visSamples;
[440]1465}
1466
[485]1467
[440]1468void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
1469{
1470        mConstructionSamples = constructionSamples;
1471}
1472
[485]1473
[574]1474void ViewCellsManager::SetInitialSamples(const int initialSamples)
1475{
1476        mInitialSamples = initialSamples;
1477}
1478
1479
[440]1480void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
1481{
1482        mPostProcessSamples = postProcessSamples;
1483}
1484
[485]1485
[440]1486int ViewCellsManager::GetVisualizationSamples() const
1487{
1488        return mVisualizationSamples;
1489}
1490
[485]1491
[440]1492int ViewCellsManager::GetConstructionSamples() const
1493{
1494        return mConstructionSamples;
1495}
1496
[485]1497
[440]1498int ViewCellsManager::GetPostProcessSamples() const
1499{
1500        return mPostProcessSamples;
1501}
1502
[485]1503
[719]1504void ViewCellsManager::UpdatePvs()
1505{
[720]1506        if (mViewCellPvsIsUpdated || !ViewCellsTreeConstructed())
[719]1507                return;
1508
1509        mViewCellPvsIsUpdated = true;
1510
1511        ViewCellContainer leaves;
1512        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
1513
1514        ViewCellContainer::const_iterator it, it_end = leaves.end();
1515
1516        for (it = leaves.begin(); it != it_end; ++ it)
1517        {
1518                mViewCellsTree->PropagatePvs(*it);
1519        }
1520}
1521
1522
[485]1523void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]1524{
[719]1525        // update pvs of view cells tree if necessary
1526        UpdatePvs();
[467]1527
[719]1528        ViewCellContainer::const_iterator it = mViewCells.begin();
1529
1530        stat.viewcells = 0;
1531        stat.minPvs = 100000000;
1532        stat.maxPvs = 0;
1533        stat.avgPvs = 0.0f;
1534
1535        for (; it != mViewCells.end(); ++ it)
1536        {
1537                ViewCell *viewcell = *it;
1538               
1539                const int pvsSize = mViewCellsTree->GetPvsSize(viewcell);
1540               
1541                if (pvsSize < stat.minPvs)
1542                        stat.minPvs = pvsSize;
1543                if (pvsSize > stat.maxPvs)
1544                        stat.maxPvs = pvsSize;
1545                stat.avgPvs += pvsSize;
1546               
1547                ++ stat.viewcells;
1548        }
1549
1550        if (stat.viewcells)
1551                stat.avgPvs/=stat.viewcells;
[467]1552}
1553
[485]1554
[480]1555void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]1556{
1557  s<<"############# Viewcell PVS STAT ##################\n";
1558  PvsStatistics pvsStat;
1559  GetPvsStatistics(pvsStat);
1560  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
1561  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
1562  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
1563}
1564
[485]1565
[532]1566int ViewCellsManager::CastBeam(Beam &beam)
1567{
1568        return 0;
1569}
1570
[547]1571
[468]1572ViewCellContainer &ViewCellsManager::GetViewCells()
1573{
1574        return mViewCells;
1575}
1576
[485]1577
[487]1578void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
1579{
[542]1580        mViewSpaceBox = box;
[591]1581
[660]1582        CreateClipPlane();
[591]1583       
[577]1584        mTotalAreaValid = false;
[487]1585}
1586
1587
[660]1588void ViewCellsManager::CreateClipPlane()
[591]1589{
1590        int axis = 0;
[667]1591        float pos;
[591]1592
[938]1593        mEnvironment->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
[591]1594
[667]1595        Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
1596
[660]1597        if (mUseClipPlaneForViz)
[938]1598        mEnvironment->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
[591]1599
1600        Vector3 normal(0,0,0);
1601        normal[axis] = 1;
1602
[660]1603        mClipPlane = Plane3(normal, point);
[591]1604}
1605
1606
[519]1607AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
1608{
[542]1609        return mViewSpaceBox;
[519]1610}
1611
1612
[480]1613void ViewCellsManager::ResetViewCells()
1614{
[720]1615        // recollect view cells
[480]1616        mViewCells.clear();
1617        CollectViewCells();
[590]1618       
[720]1619       
1620        // stats are computed once more
[660]1621        mCurrentViewCellsStats.Reset();
[480]1622        EvaluateViewCellsStats();
[590]1623
[520]1624        // has to be recomputed
[480]1625        mTotalAreaValid = false;
1626}
1627
[485]1628
[547]1629int ViewCellsManager::GetMaxPvsSize() const
1630{
1631        return mMaxPvsSize;
1632}
1633
[590]1634
[563]1635void
1636ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
1637{
1638  if (!ViewCellsConstructed())
1639        return;
[564]1640
[563]1641  VssRayContainer::const_iterator it, it_end = rays.end();
[564]1642
[563]1643  for (it = rays.begin(); it != it_end; ++ it) {
1644        AddSampleContributions(*(*it));
1645  }
1646}
[547]1647
[581]1648
[562]1649int ViewCellsManager::GetMinPvsSize() const
1650{
1651        return mMinPvsSize;
1652}
1653
1654
1655
[561]1656float ViewCellsManager::GetMaxPvsRatio() const
1657{
1658        return mMaxPvsRatio;
1659}
1660
1661
[563]1662void
1663ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]1664{
[563]1665  // assumes viewcells have been stored...
1666  ViewCellContainer *viewcells = &ray.mViewCells;
1667  ViewCellContainer::const_iterator it;
1668  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
1669        ViewCell *viewcell = *it;
[569]1670        if (viewcell->GetValid()) {
1671          // if ray not outside of view space
1672          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1673        }
[563]1674  }
1675}
[503]1676
[574]1677
[570]1678float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
[574]1679                                                                                                   const bool addRays,
1680                                                                                                   const bool storeViewCells)
[563]1681{
[570]1682        ViewCellContainer viewcells;
[564]1683
[570]1684        ray.mPvsContribution = 0;
1685        ray.mRelativePvsContribution = 0.0f;
[485]1686
[570]1687        static Ray hray;
[564]1688        hray.Init(ray);
1689        //hray.mFlags |= Ray::CULL_BACKFACES;
1690        //Ray hray(ray);
1691
1692        float tmin = 0, tmax = 1.0;
1693
1694        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
[565]1695                return 0;
[564]1696
1697        Vector3 origin = hray.Extrap(tmin);
1698        Vector3 termination = hray.Extrap(tmax);
1699
1700        CastLineSegment(origin, termination, viewcells);
[664]1701
[570]1702        // copy viewcells memory efficiently
[574]1703        //const bool storeViewcells = !addRays;
[564]1704
[574]1705        if (storeViewCells)
[570]1706        {
1707                ray.mViewCells.reserve(viewcells.size());
1708                ray.mViewCells = viewcells;
1709        }
[564]1710
[570]1711        ViewCellContainer::const_iterator it = viewcells.begin();
[564]1712
[664]1713        for (; it != viewcells.end(); ++ it)
1714        {
1715                ViewCell *viewcell = *it;
[694]1716
[708]1717                if (viewcell->GetValid())
[664]1718                {
1719                        // if ray not outside of view space
1720                        float contribution;
[666]1721                        if (ray.mTerminationObject &&
1722                                viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
[664]1723                                                                                                                 ray.mPdf,
1724                                                                                                                 contribution))
1725                        {
1726                                ++ ray.mPvsContribution;
1727                                ray.mRelativePvsContribution += contribution;
1728                        }
[718]1729
[840]1730                        // for directional sampling it is important to count only contributions
[718]1731                        // made in one direction!!!
1732                        // the other contributions of this sample will be counted for the oposite ray!
1733#if 0
[666]1734                        if (ray.mOriginObject &&
1735                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
1736                                                                                                                 ray.mPdf,
1737                                                                                                                 contribution))
1738                        {
1739                                ++ ray.mPvsContribution;
1740                                ray.mRelativePvsContribution += contribution;
1741                        }
[718]1742#endif
[664]1743                }
[569]1744        }
[564]1745
[664]1746       
1747        if (addRays)
1748        {
1749                for (it = viewcells.begin(); it != viewcells.end(); ++ it)
1750                {
1751                        ViewCell *viewcell = *it;
1752           
[706]1753                        if (viewcell->GetValid())
[664]1754                        {
1755                                // if ray not outside of view space
[666]1756                                 if (ray.mTerminationObject)
1757                                         viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
[718]1758
1759#if 0
[666]1760                                 if (ray.mOriginObject)
1761                                         viewcell->GetPvs().AddSample(ray.mOriginObject, ray.mPdf);
[718]1762#endif
[664]1763                        }
1764                }
[563]1765        }
[570]1766
1767        return ray.mRelativePvsContribution;
[468]1768}
1769
1770
[469]1771void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]1772                                                                  const int maxSize,
[503]1773                                                                  VssRayContainer &usedRays,
[485]1774                                                                  VssRayContainer *savedRays) const
[469]1775{
[485]1776        const int limit = min(maxSize, (int)sourceRays.size());
[473]1777        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]1778
[485]1779        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]1780        for (it = sourceRays.begin(); it != it_end; ++ it)
1781        {
[473]1782                if (Random(1.0f) < prop)
[485]1783                        usedRays.push_back(*it);
1784                else if (savedRays)
1785                        savedRays->push_back(*it);
[469]1786        }
1787}
1788
[477]1789
[728]1790float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
[605]1791{
[728]1792        return mViewCellsTree->GetPvsSize(viewCell);
[605]1793}
1794
1795
[477]1796float ViewCellsManager::GetAccVcArea()
[470]1797{
1798        // if already computed
1799        if (mTotalAreaValid)
[728]1800        {
[470]1801                return mTotalArea;
[728]1802        }
[470]1803
1804        mTotalArea = 0;
1805        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1806
1807        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]1808        {
1809                //Debug << "area: " << GetArea(*it);
[470]1810        mTotalArea += GetArea(*it);
[480]1811        }
1812
[470]1813        mTotalAreaValid = true;
1814
1815        return mTotalArea;
1816}
1817
[482]1818
[475]1819void ViewCellsManager::PrintStatistics(ostream &s) const
1820{
[660]1821        s << mCurrentViewCellsStats << endl;
[475]1822}
1823
[477]1824
[508]1825void ViewCellsManager::CreateUniqueViewCellIds()
[482]1826{
[651]1827        if (ViewCellsTreeConstructed())
1828                mViewCellsTree->CreateUniqueViewCellsIds();
1829        else
1830                for (int i = 0; i < (int)mViewCells.size(); ++ i)
1831                        mViewCells[i]->SetId(i);
[508]1832}
1833
1834
1835void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
1836{
[482]1837        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1838
1839        for (it = mViewCells.begin(); it != it_end; ++ it)
1840        {
[574]1841                if (!mOnlyValidViewCells || (*it)->GetValid())
1842                {
[801]1843                        ExportColor(exporter, *it);     
1844
[591]1845                        ExportViewCellGeometry(exporter, *it,
[660]1846                                mUseClipPlaneForViz ? &mClipPlane : NULL);
[574]1847                }
[482]1848        }
1849}
1850
1851
[517]1852void ViewCellsManager::CreateViewCellMeshes()
[503]1853{
1854        // convert to meshes
1855        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1856
1857        for (it = mViewCells.begin(); it != it_end; ++ it)
1858        {
[517]1859                if (!(*it)->GetMesh())
1860                        CreateMesh(*it);
[503]1861        }
1862}
1863
[508]1864
[944]1865bool ViewCellsManager::ExportViewCells(const string filename,
1866                                                                           const bool exportPvs,
1867                                                                           const ObjectContainer &objects)
[564]1868{
[508]1869        return false;
1870}
1871
1872
[610]1873void ViewCellsManager::CollectViewCells(const int n)
[508]1874{
[610]1875        mNumActiveViewCells = n;
1876        mViewCells.clear();
1877        CollectViewCells();
1878}
[508]1879
1880
[660]1881void ViewCellsManager::SetViewCellsActive()
1882{
[882]1883        // collect leaf view cells and set the pointers to the currently
1884        // active view cells
[660]1885        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[944]1886
[660]1887        for (it = mViewCells.begin(); it != it_end; ++ it)
1888        {
[881]1889                ViewCellContainer leaves;
1890                mViewCellsTree->CollectLeaves(*it, leaves);
1891
1892                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
1893                for (lit = mViewCells.begin(); lit != lit_end; ++ lit)
1894                {
1895                        dynamic_cast<ViewCellLeaf *>(*lit)->SetActiveViewCell(*it);
1896                }
[660]1897        }
1898}
[508]1899
[840]1900
1901int ViewCellsManager::GetMaxFilterSize() const
1902{
1903        return mMaxFilterSize; 
1904}
1905
1906static const bool USE_ASCII = true;
1907
1908bool ViewCellsManager::ExportBoundingBoxes(const string filename,
1909                                                                                   const ObjectContainer &objects) const
1910{
1911        ObjectContainer::const_iterator it, it_end = objects.end();
1912       
1913        if (USE_ASCII)
1914        {
1915                ofstream boxesOut(filename.c_str());
1916                if (!boxesOut.is_open())
1917                        return false;
1918
1919                for (it = objects.begin(); it != it_end; ++ it)
1920                {
1921                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
1922                        const AxisAlignedBox3 box = mi->GetBox();
1923
1924                        boxesOut << mi->GetId() << " "
1925                                         << box.Min().x << " "
1926                                         << box.Min().y << " "
1927                                         << box.Min().z << " "
1928                                         << box.Max().x << " "
1929                                         << box.Max().y << " "
1930                     << box.Max().z << endl;   
1931                }
1932
1933                boxesOut.close();
1934        }
1935        else
1936        {
1937                ofstream boxesOut(filename.c_str(), ios::binary);
1938
1939                if (!boxesOut.is_open())
1940                        return false;
1941
1942                for (it = objects.begin(); it != it_end; ++ it)
1943                {       
1944                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
1945                        const AxisAlignedBox3 box = mi->GetBox();
1946                        Vector3 bmin = box.Min();
1947                        Vector3 bmax = box.Max();
[850]1948                        int id = mi->GetId();
[840]1949
[850]1950                        boxesOut.write(reinterpret_cast<char *>(&id), sizeof(int));
[840]1951                        boxesOut.write(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
1952                        boxesOut.write(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
1953                }
1954               
1955                boxesOut.close();
1956        }
1957
1958
1959        return true;
1960}
1961
1962
[850]1963bool ViewCellsManager::LoadBoundingBoxes(const string filename,
1964                                                                                 IndexedBoundingBoxContainer &boxes) const
[840]1965{
[850]1966        Vector3 bmin, bmax;
1967        int id;
[840]1968
[850]1969        if (USE_ASCII)
[840]1970        {
[850]1971                ifstream boxesIn(filename.c_str());
[840]1972               
[850]1973                if (!boxesIn.is_open())
[840]1974                {
[850]1975                        cout << "failed to open file " << filename << endl;
1976                        return false;
[840]1977                }
[850]1978
1979                string buf;
1980                while (!(getline(boxesIn, buf)).eof())
[840]1981                {
[850]1982                        sscanf(buf.c_str(), "%d %f %f %f %f %f %f",
1983                                   &id, &bmin.x, &bmin.y, &bmin.z,
1984                                   &bmax.x, &bmax.y, &bmax.z);
1985               
1986                        AxisAlignedBox3 box(bmin, bmax);
1987                        //      MeshInstance *mi = new MeshInstance();
1988                        // HACK: set bounding box to new box
1989                        //mi->mBox = box;
1990
1991                        boxes.push_back(IndexedBoundingBox(id, box));
[840]1992                }
1993
[850]1994                boxesIn.close();
[840]1995        }
[850]1996        else
[840]1997        {
[850]1998                ifstream boxesIn(filename.c_str(), ios::binary);
[840]1999
[850]2000                if (!boxesIn.is_open())
2001                        return false;
2002
2003                while (1)
[840]2004                {
[850]2005                        boxesIn.read(reinterpret_cast<char *>(&id), sizeof(Vector3));
2006                        boxesIn.read(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
2007                        boxesIn.read(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
2008                       
2009                        if (boxesIn.eof())
2010                                break;
2011
2012                       
2013                        AxisAlignedBox3 box(bmin, bmax);
2014                        MeshInstance *mi = new MeshInstance(NULL);
2015
2016                        // HACK: set bounding box to new box
2017                        //mi->mBox = box;
2018                        //boxes.push_back(mi);
2019                        boxes.push_back(IndexedBoundingBox(id, box));
[840]2020                }
2021
[850]2022                boxesIn.close();
[840]2023        }
2024
2025        return true;
[850]2026}
[840]2027
[931]2028
2029float ViewCellsManager::GetFilterWidth()
2030{
2031        return mFilterWidth;
2032}
2033
2034
2035float ViewCellsManager::GetAbsFilterWidth()
2036{
2037        return Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
2038}
2039
2040
[440]2041/**********************************************************************/
[931]2042/*                 BspViewCellsManager implementation                 */
[440]2043/**********************************************************************/
2044
[482]2045
[938]2046BspViewCellsManager::BspViewCellsManager(BspTree *bspTree, Environment *env):
2047ViewCellsManager(env), mBspTree(bspTree)
[440]2048{
[938]2049        mEnvironment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
[587]2050        mBspTree->SetViewCellsManager(this);
[590]2051        mBspTree->mViewCellsTree = mViewCellsTree;
[440]2052}
2053
[462]2054
[440]2055bool BspViewCellsManager::ViewCellsConstructed() const
2056{
2057        return mBspTree->GetRoot() != NULL;
2058}
2059
[480]2060
[440]2061ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2062{
2063        return new BspViewCell(mesh);
2064}
2065
[480]2066
[574]2067int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2068                                                                                          const VssRayContainer &rays)
[440]2069{
[441]2070        // if view cells were already constructed
[440]2071        if (ViewCellsConstructed())
2072                return 0;
2073
2074        int sampleContributions = 0;
[503]2075
[469]2076        // construct view cells using the collected samples
2077        RayContainer constructionRays;
2078        VssRayContainer savedRays;
[440]2079
[574]2080        const int limit = min(mInitialSamples, (int)rays.size());
[440]2081
[469]2082        VssRayContainer::const_iterator it, it_end = rays.end();
[448]2083
[473]2084        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
2085
[469]2086        for (it = rays.begin(); it != it_end; ++ it)
2087        {
[473]2088                if (Random(1.0f) < prop)
[469]2089                        constructionRays.push_back(new Ray(*(*it)));
2090                else
2091                        savedRays.push_back(*it);
2092        }
[440]2093
[503]2094    if (mViewCells.empty())
2095        {
2096                // no view cells loaded
[587]2097                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
[469]2098                // collect final view cells
2099                mBspTree->CollectViewCells(mViewCells);
[503]2100        }
[469]2101        else
2102        {
2103                mBspTree->Construct(mViewCells);
2104        }
2105
2106        // destroy rays created only for construction
2107        CLEAR_CONTAINER(constructionRays);
2108
[440]2109        Debug << mBspTree->GetStatistics() << endl;
[503]2110
2111        //EvaluateViewCellsStats();
[660]2112        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[480]2113
[469]2114        // recast rest of the rays
[649]2115        if (SAMPLE_AFTER_SUBDIVISION)
2116                ComputeSampleContributions(savedRays, true, false);
[469]2117
[719]2118        // real meshes are contructed at this stage
2119        if (0)
2120        {
2121                cout << "finalizing view cells ... ";
2122                FinalizeViewCells(true);
2123                cout << "finished" << endl;     
2124        }
2125
[440]2126        return sampleContributions;
2127}
2128
[503]2129
[480]2130void BspViewCellsManager::CollectViewCells()
2131{
[587]2132        // view cells tree constructed
2133        if (!ViewCellsTreeConstructed())
[591]2134        {               
[587]2135                mBspTree->CollectViewCells(mViewCells);
2136        }
2137        else
2138        {
2139                // we can use the view cells tree hierarchy to get the right set
[591]2140                mViewCellsTree->CollectBestViewCellSet(mViewCells,
[600]2141                                                                                           mNumActiveViewCells);
[587]2142        }
[480]2143}
[468]2144
[503]2145
[471]2146float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]2147{
[471]2148        // compute view cell area as subsititute for probability
[591]2149        if (1)
2150                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
2151        else
2152                return GetArea(viewCell) / GetAccVcArea();
[466]2153}
[440]2154
[503]2155
[440]2156
[468]2157int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
2158                                                                                 const Vector3 &termination,
2159                                                                                 ViewCellContainer &viewcells)
[440]2160{
[468]2161        return mBspTree->CastLineSegment(origin, termination, viewcells);
2162}
2163
2164
[503]2165int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]2166                                                                         const VssRayContainer &rays)
2167{
[469]2168        if (!ViewCellsConstructed())
[441]2169        {
2170                Debug << "view cells not constructed" << endl;
2171                return 0;
2172        }
[590]2173       
2174        // view cells already finished before post processing step (i.e. because they were loaded)
2175        if (mViewCellsFinished)
2176        {
2177                FinalizeViewCells(true);
2178                EvaluateViewCellsStats();
2179
2180                return 0;
2181        }
2182
[440]2183        //-- post processing of bsp view cells
[600]2184
[440]2185    int vcSize = 0;
2186        int pvsSize = 0;
2187
[591]2188        //-- merge view cells
[649]2189        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
2190        long startTime = GetTime();
2191       
2192        VssRayContainer postProcessRays;
2193        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2194
[592]2195        if (mMergeViewCells)
[591]2196        {
[660]2197                cout << "constructing visibility based merge tree" << endl;
[650]2198                mViewCellsTree->ConstructMergeTree(rays, objects);
[649]2199        }
2200        else
2201        {
[660]2202                cout << "constructing spatial merge tree" << endl;
[752]2203
[649]2204                // create spatial merge hierarchy
[752]2205                ViewCell *root = ConstructSpatialMergeTree(mBspTree->GetRoot());
2206                mViewCellsTree->SetRoot(root);
2207
2208                // compute pvs
2209                ObjectPvs pvs;
2210                UpdatePvsForEvaluation(root, pvs);
[649]2211        }
[440]2212
[660]2213        // export statistics after merge
[666]2214        if (1)
2215        {
2216                char mstats[100];
[938]2217                mEnvironment->GetStringValue("ViewCells.mergeStats", mstats);
[666]2218                mViewCellsTree->ExportStats(mstats);
2219        }
[650]2220
[649]2221        //-- stats and visualizations
2222        cout << "finished" << endl;
[650]2223        cout << "merged view cells in "
[752]2224                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[440]2225
[650]2226        Debug << "Postprocessing: Merged view cells in "
[752]2227                << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
[649]2228       
[503]2229
[660]2230        //-- visualization and statistics
[600]2231    // reset view cells and stats
[480]2232        ResetViewCells();
[660]2233        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
[600]2234
[660]2235
[600]2236        int savedColorCode  = mColorCode;
[605]2237       
[600]2238        //BspLeaf::NewMail();
2239        if (1) // export merged view cells
2240        {
2241                mColorCode = 0;
[605]2242               
[744]2243                Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
[605]2244               
[600]2245
2246                cout << "exporting view cells after merge ... ";
2247
2248                if (exporter)
2249                {
2250                        if (mExportGeometry)
2251                                exporter->ExportGeometry(objects);
2252
2253                        //exporter->SetWireframe();
2254                        exporter->SetFilled();
2255                        ExportViewCellsForViz(exporter);
2256
2257
2258                        delete exporter;
2259                }
2260                cout << "finished" << endl;
2261        }
2262
[752]2263        if (1) // export merged view cells using pvs color coding
[600]2264        {
2265                mColorCode = 1;
2266
[744]2267                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
[600]2268       
2269                cout << "exporting view cells after merge (pvs size) ... ";     
2270
2271                if (exporter)
2272                {
2273                        //exporter->SetWireframe();
[752]2274                        //exporter->SetForcedMaterial(RandomMaterial());
2275
[600]2276                        if (mExportGeometry)
2277                                exporter->ExportGeometry(objects);
2278
2279                        //exporter->SetWireframe();
2280                        exporter->SetFilled();
2281                        ExportViewCellsForViz(exporter);
2282
2283                        delete exporter;
2284                }
2285                cout << "finished" << endl;
2286        }
2287
[693]2288       
2289        // only for testing
2290        TestSubdivision();
2291
[600]2292        mColorCode = savedColorCode;
2293
[719]2294        // compute final meshes and volume / area
2295        if (1) FinalizeViewCells(true);
2296
[587]2297        // write view cells to disc
2298        if (mExportViewCells)
2299        {
[840]2300                char filename[100];
[938]2301                mEnvironment->GetStringValue("ViewCells.filename", filename);
[931]2302                ExportViewCells(filename, mExportPvs, objects);
[587]2303        }
[840]2304       
2305        // export bounding boxes
[931]2306        if (0 && mExportBboxesForPvs)
[840]2307        {
2308                char filename[100];
[938]2309                mEnvironment->GetStringValue("ViewCells.boxesFilename", filename);
[840]2310                ExportBoundingBoxes(filename, objects);
2311        }
[587]2312
[840]2313
[650]2314        return 0;
[440]2315}
2316
[477]2317
2318BspViewCellsManager::~BspViewCellsManager()
2319{
2320}
2321
2322
[440]2323int BspViewCellsManager::GetType() const
2324{
2325        return BSP;
2326}
2327
2328
2329void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2330                                                                        const VssRayContainer &sampleRays)
[440]2331{
[469]2332        if (!ViewCellsConstructed())
2333                return;
[574]2334       
[600]2335        int savedColorCode = mColorCode;
2336
2337       
2338       
2339        if (1) // export final view cells
[440]2340        {
[600]2341                mColorCode = 1;
[587]2342
[822]2343                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[600]2344       
2345                cout << "exporting view cells after merge (pvs size) ... ";     
[587]2346
[469]2347                if (exporter)
[440]2348                {
[600]2349                        //exporter->SetWireframe();
2350                       
2351                        if (mExportGeometry)
2352                                exporter->ExportGeometry(objects);
[590]2353
[600]2354                        //exporter->SetWireframe();
[801]2355                        //exporter->SetFilled();
2356                        bool b = mUseClipPlaneForViz;
2357                        mUseClipPlaneForViz = false;
[508]2358                        ExportViewCellsForViz(exporter);
[801]2359                        mUseClipPlaneForViz = b;
[469]2360                        delete exporter;
[440]2361                }
[469]2362                cout << "finished" << endl;
[503]2363        }
[477]2364
[600]2365        mColorCode = savedColorCode;
2366
[469]2367        //-- visualization of the BSP splits
2368        bool exportSplits = false;
[938]2369        mEnvironment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]2370
[469]2371        if (exportSplits)
[440]2372        {
[469]2373                cout << "exporting splits ... ";
[477]2374                ExportSplits(objects);
[469]2375                cout << "finished" << endl;
[440]2376        }
[477]2377
[600]2378        // export single view cells
[477]2379        ExportBspPvs(objects);
[440]2380}
2381
2382
[477]2383void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]2384{
2385        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2386
[503]2387        if (exporter)
2388        {
[598]2389                //exporter->SetFilled();
2390
2391                if (mExportGeometry)
2392                        exporter->ExportGeometry(objects);
2393
[503]2394                Material m;
[440]2395                m.mDiffuseColor = RgbColor(1, 0, 0);
2396                exporter->SetForcedMaterial(m);
2397                exporter->SetWireframe();
[503]2398
[440]2399                exporter->ExportBspSplits(*mBspTree, true);
2400
[482]2401                //NOTE: take forced material, else big scenes cannot be viewed
[440]2402                m.mDiffuseColor = RgbColor(0, 1, 0);
2403                exporter->SetForcedMaterial(m);
[482]2404                //exporter->ResetForcedMaterial();
2405
[440]2406                delete exporter;
2407        }
2408}
2409
[477]2410
2411void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]2412{
[477]2413        const int leafOut = 10;
[503]2414
[477]2415        ViewCell::NewMail();
[440]2416
[477]2417        //-- some rays for output
2418        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]2419
[477]2420        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2421        Debug << "\nOutput view cells: " << endl;
[503]2422
[478]2423        // sort view cells to get largest view cells
[587]2424        if (0)
[801]2425                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[587]2426
[503]2427        int limit = min(leafOut, (int)mViewCells.size());
2428
[478]2429        for (int i = 0; i < limit; ++ i)
[477]2430        {
[478]2431                cout << "creating output for view cell " << i << " ... ";
2432                VssRayContainer vcRays;
2433                Intersectable::NewMail();
[582]2434                ViewCell *vc;
2435
2436                if (0)
2437                        vc = mViewCells[i];
2438                else
2439                        vc = mViewCells[Random((int)mViewCells.size())];
2440
[478]2441                cout << "creating output for view cell " << i << " ... ";
[469]2442
[587]2443                if(0)
[477]2444                {
[587]2445                        // check whether we can add the current ray to the output rays
2446                        for (int k = 0; k < raysOut; ++ k)
[477]2447                        {
[587]2448                                BspRay *ray = mBspRays[k];
2449                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
2450                                {
2451                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
2452                                        if (vc == leaf->GetViewCell())
2453                                                vcRays.push_back(ray->vssRay);
2454                                }
[477]2455                        }
2456                }
[587]2457
[478]2458                //bspLeaves[j]->Mail();
2459                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]2460
[478]2461                Exporter *exporter = Exporter::GetExporter(s);
[503]2462
[478]2463                exporter->SetWireframe();
[477]2464
[478]2465                Material m;//= RandomMaterial();
2466                m.mDiffuseColor = RgbColor(0, 1, 0);
2467                exporter->SetForcedMaterial(m);
[477]2468
[587]2469                ExportViewCellGeometry(exporter, vc);
2470               
[478]2471                // export rays piercing this view cell
2472                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
[580]2473
[478]2474                m.mDiffuseColor = RgbColor(1, 0, 0);
2475                exporter->SetForcedMaterial(m);
[440]2476
[478]2477                ObjectPvsMap::const_iterator it,
2478                        it_end = vc->GetPvs().mEntries.end();
[440]2479
[478]2480                exporter->SetFilled();
[469]2481
[478]2482                // output PVS of view cell
[503]2483                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]2484                {
2485                        Intersectable *intersect = (*it).first;
[469]2486
[478]2487                        if (!intersect->Mailed())
2488                        {
2489                                Material m = RandomMaterial();
2490                                exporter->SetForcedMaterial(m);
2491
2492                                exporter->ExportIntersectable(intersect);
2493                                intersect->Mail();
[503]2494                        }
[477]2495                }
[503]2496
[478]2497                DEL_PTR(exporter);
2498                cout << "finished" << endl;
[477]2499        }
2500
2501        Debug << endl;
[440]2502}
2503
[441]2504
[503]2505void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]2506                                                                          ViewCell *vc) const
2507{
[600]2508        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[482]2509
2510        float importance = 0;
[598]2511        static Material m;
[482]2512
2513        switch (mColorCode)
2514        {
[598]2515        case 0: // Random
2516                {
2517                        if (vcValid)
2518                        {
2519                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
2520                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
[600]2521                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
[598]2522                        }
2523                        else
2524                        {
2525                                m.mDiffuseColor.r = 0.0f;
2526                                m.mDiffuseColor.g = 1.0f;
2527                                m.mDiffuseColor.b = 0.0f;
2528                        }
2529
2530                        exporter->SetForcedMaterial(m);
2531                        return;
2532                }
2533               
[482]2534        case 1: // pvs
2535                {
[503]2536                        importance = (float)vc->GetPvs().GetSize() /
[660]2537                                (float)mCurrentViewCellsStats.maxPvs;
[598]2538
[482]2539                }
2540                break;
2541        case 2: // merges
2542                {
[736]2543            int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
[660]2544                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]2545                }
[598]2546                //break;
[482]2547        case 3: // merge tree differene
2548                {
2549                        // TODO
[598]2550                        //importance = (float)GetMaxTreeDiff(vc) /
2551                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2552
[482]2553                }
2554                break;
2555        default:
2556                break;
2557        }
2558
[598]2559        // special color code for invalid view cells
[482]2560        m.mDiffuseColor.r = importance;
2561        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[598]2562        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[503]2563
[598]2564        //Debug << "importance: " << importance << endl;
[482]2565        exporter->SetForcedMaterial(m);
2566}
2567
[587]2568
[693]2569void BspViewCellsManager::TestSubdivision()
2570{
2571        ViewCellContainer leaves;
2572        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
2573
2574        ViewCellContainer::const_iterator it, it_end = leaves.end();
2575
2576        const float vol = mViewSpaceBox.GetVolume();
2577        float subdivVol = 0;
2578        float newVol = 0;
2579
2580        for (it = leaves.begin(); it != it_end; ++ it)
2581        {
2582                BspNodeGeometry geom;
2583                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2584                mBspTree->ConstructGeometry(leaf, geom);
2585
2586                const float lVol = geom.GetVolume();
2587               
2588                newVol += lVol;
2589                subdivVol += (*it)->GetVolume();
[694]2590
[704]2591                float thres = 0.9f;
[694]2592                if ((lVol < ((*it)->GetVolume() * thres)) ||
2593                        (lVol * thres > ((*it)->GetVolume())))
2594                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]2595        }
2596       
2597        Debug << "exact volume: " << vol << endl;
2598        Debug << "subdivision volume: " << subdivVol << endl;
2599        Debug << "new volume: " << newVol << endl;
2600}
2601
2602
[580]2603void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2604                                                                                                 ViewCell *vc,
[660]2605                                                                                                 const Plane3 *clipPlane) const
[482]2606{
2607        if (vc->GetMesh())
2608        {
[587]2609                exporter->ExportMesh(vc->GetMesh());
[726]2610       
[587]2611                return;
[482]2612        }
[587]2613
[726]2614       
[660]2615        if (clipPlane)
[591]2616        {
[726]2617                ViewCellContainer leaves;
2618                mViewCellsTree->CollectLeaves(vc, leaves);
2619                ViewCellContainer::const_iterator it, it_end = leaves.end();
[591]2620
[726]2621                for (it = leaves.begin(); it != it_end; ++ it)
[681]2622                {
[726]2623                        BspNodeGeometry geom;
2624
[681]2625                        BspNodeGeometry front;
2626                        BspNodeGeometry back;
[591]2627
[726]2628                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2629                        mBspTree->ConstructGeometry(leaf, geom);
[681]2630
[726]2631                        const float eps = 0.00000001f;
2632                        const int cf = geom.Side(*clipPlane, eps);
2633
2634                        if (cf == -1)
2635                        {
2636                                exporter->ExportPolygons(geom.GetPolys());
2637                        }
2638                        else if (cf == 0)
2639                        {
2640                                geom.SplitGeometry(front,
2641                                                                   back,
2642                                                                   *clipPlane,
2643                                                                   mViewSpaceBox,
2644                                                                   eps);
2645       
2646                                //Debug << "geo size: " << geom.Size() << endl;
2647                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
2648                                if (back.Valid())
2649                                {
2650                                        exporter->ExportPolygons(back.GetPolys());
2651                                }                       
2652                        }
[681]2653                }
[591]2654        }
2655        else
2656        {
[726]2657                BspNodeGeometry geom;
2658                mBspTree->ConstructGeometry(vc, geom);
2659                       
[678]2660                exporter->ExportPolygons(geom.GetPolys());
[591]2661        }
[482]2662}
2663
[503]2664
2665void BspViewCellsManager::CreateMesh(ViewCell *vc)
2666{
[726]2667        // delete previous mesh
2668        ///DEL_PTR(vc->GetMesh());
[587]2669        BspNodeGeometry geom;
2670        mBspTree->ConstructGeometry(vc, geom);
2671
2672        Mesh *mesh = new Mesh();
[726]2673
[840]2674        IncludeNodeGeomInMesh(geom, *mesh);
[587]2675        vc->SetMesh(mesh);
[840]2676
[726]2677        // put mesh into mesh container so we can savely delete it
[587]2678        mMeshContainer.push_back(mesh);
[503]2679}
2680
[551]2681
[587]2682void BspViewCellsManager::Finalize(ViewCell *viewCell,
2683                                                                   const bool createMesh)
[502]2684{
[587]2685        float area = 0;
2686        float volume = 0;
[572]2687
[587]2688        ViewCellContainer leaves;
2689        mViewCellsTree->CollectLeaves(viewCell, leaves);
2690
2691        ViewCellContainer::const_iterator it, it_end = leaves.end();
2692
[693]2693    for (it = leaves.begin(); it != it_end; ++ it)
[587]2694        {
2695                BspNodeGeometry geom;
2696                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2697                mBspTree->ConstructGeometry(leaf, geom);
2698
[719]2699                const float lVol = geom.GetVolume();
2700                const float lArea = geom.GetArea();
[693]2701
2702                //(*it)->SetVolume(vol);
2703                //(*it)->SetArea(area);
2704
2705                area += lArea;
2706                volume += lVol;
2707
2708        CreateMesh(*it);
[587]2709        }
2710
2711        viewCell->SetVolume(volume);
2712        viewCell->SetArea(area);
[502]2713}
2714
[580]2715
[879]2716ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
[580]2717{
[587]2718        if (!mBspTree)
2719                return NULL;
2720
2721        if (!mViewSpaceBox.IsInside(point))
2722                return NULL;
2723       
2724        return mBspTree->GetViewCell(point);
[580]2725}
2726
2727
[587]2728void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2729                                                                                                 vector<MergeCandidate> &candidates)
2730{
2731        cout << "collecting merge candidates ... " << endl;
2732
2733        if (mUseRaysForMerge)
2734        {
2735                mBspTree->CollectMergeCandidates(rays, candidates);
2736        }
2737        else
2738        {
2739                vector<BspLeaf *> leaves;
2740                mBspTree->CollectLeaves(leaves);
2741                mBspTree->CollectMergeCandidates(leaves, candidates);
2742        }
2743
2744        cout << "fininshed collecting candidates" << endl;
2745}
2746
2747
[440]2748
[931]2749bool BspViewCellsManager::ExportViewCells(const string filename, const bool exportPvs, const ObjectContainer &objects)
[590]2750{
[955]2751#if STILL_HAS_TODO
[590]2752        cout << "exporting view cells to xml ... ";
2753        std::ofstream stream;
[503]2754
[590]2755        // for output we need unique ids for each view cell
2756        CreateUniqueViewCellIds();
[503]2757
[590]2758
2759        stream.open(filename.c_str());
2760        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2761        stream << "<Visibility_Solution>" << endl;
2762
2763        //-- the view space bounding box
2764        stream << "<ViewSpaceBox"
2765                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
2766                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
2767
2768        //-- the type of the view cells hierarchy
2769        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
[840]2770        // NOTE: load in vsp bsp here because bsp and vsp bsp can use same tree and vsp bsp is bug free
2771        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
2772       
[590]2773        //-- load the view cells itself, i.e., the ids and the pvs
2774        stream << "<ViewCells>" << endl;
[610]2775
[871]2776        mViewCellsTree->Export(stream, exportPvs);
[590]2777
2778        stream << "</ViewCells>" << endl;
2779
2780        //-- load the hierarchy
2781        stream << "<Hierarchy>" << endl;
2782        mBspTree->Export(stream);
2783        stream << endl << "</Hierarchy>" << endl;
2784
2785        stream << "</Visibility_Solution>" << endl;
2786        stream.close();
2787
2788        cout << "finished" << endl;
[955]2789#endif
[590]2790        return true;
2791}
2792
2793
[650]2794ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[610]2795{
[752]2796        // terminate recursion
[650]2797        if (root->IsLeaf())
2798        {
[752]2799                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
2800                leaf->GetViewCell()->SetMergeCost(0.0f);
2801                return leaf->GetViewCell();
[650]2802        }
2803       
2804        BspInterior *interior = dynamic_cast<BspInterior *>(root);
2805        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2806               
[752]2807        // evaluate merge cost for priority traversal
[650]2808        float mergeCost = 1.0f / (float)root->mTimeStamp;
2809        viewCellInterior->SetMergeCost(mergeCost);
[649]2810
[650]2811        float volume = 0;
[649]2812       
[650]2813        BspNode *front = interior->GetFront();
2814        BspNode *back = interior->GetBack();
[649]2815
[752]2816
2817        //-- recursivly compute child hierarchies
[650]2818        ViewCell *backVc = ConstructSpatialMergeTree(back);
2819        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]2820
[752]2821
2822        viewCellInterior->SetupChildLink(backVc);
[650]2823        viewCellInterior->SetupChildLink(frontVc);
[610]2824
[650]2825        volume += backVc->GetVolume();
2826        volume += frontVc->GetVolume();
[649]2827
[650]2828        viewCellInterior->SetVolume(volume);
[649]2829
[650]2830        return viewCellInterior;
[610]2831}
2832
[650]2833
[752]2834void BspViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
2835{
2836        // terminate traversal
2837        if (root->IsLeaf())
2838        {
2839                pvs = root->GetPvs();
2840
2841                root->mPvsSize = pvs.GetSize();
2842                root->mPvsSizeValid = true;
2843
2844                return;
2845        }
2846
2847        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
2848        ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
2849
2850        vector<ObjectPvs> pvsList;
2851       
2852       
2853        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit)
2854        {
2855                ObjectPvs objPvs;
2856               
2857                //-- recursivly compute child pvss
2858                UpdatePvsForEvaluation(*vit, objPvs);
2859
2860                // store pvs in vector
2861                pvsList.push_back(objPvs);
2862        }
2863
2864#if 1
2865        Intersectable::NewMail();
2866
2867        //-- faster way of computing pvs:
2868        //   construct merged pvs by adding
2869        //   and only those of the next pvs which were not mailed.
2870        //   note: sumpdf is not correct!!
2871        vector<ObjectPvs>::iterator oit = pvsList.begin();
2872
2873        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
2874        {
2875               
2876        ObjectPvsMap::iterator pit, pit_end = (*oit).mEntries.end();
2877       
2878                for (pit = (*oit).mEntries.begin(); pit != pit_end; ++ pit)
2879                {
2880                       
2881                        Intersectable *intersect = (*pit).first;
2882
2883                        if (!intersect->Mailed())
2884                        {
2885                                pvs.AddSample(intersect, (*pit).second.mSumPdf);
2886                                intersect->Mail();
2887                        }
2888                }
2889        }
2890
2891        // store pvs in this node
2892        if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
2893        {
2894                interior->mPvs = pvs;
2895        }
2896       
2897        // set new pvs size
2898        interior->mPvsSize = pvs.GetSize();
2899        interior->mPvsSizeValid = true;
2900
2901#else
2902        // really merge cells: slow put sumpdf is correct
2903        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2904
2905        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2906        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
2907#endif
2908
2909}
2910
[590]2911/************************************************************************/
2912/*                   KdViewCellsManager implementation                  */
2913/************************************************************************/
2914
2915
2916
[938]2917KdViewCellsManager::KdViewCellsManager(KdTree *kdTree, Environment *env):
2918ViewCellsManager(env), mKdTree(kdTree), mKdPvsDepth(100)
[440]2919{
2920}
2921
[605]2922
[471]2923float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2924{
[479]2925        // compute view cell area / volume as subsititute for probability
[605]2926        if (0)
2927                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2928        else
2929                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[468]2930}
2931
2932
2933
[479]2934
[480]2935void KdViewCellsManager::CollectViewCells()
2936{
2937        //mKdTree->CollectViewCells(mViewCells); TODO
2938}
[479]2939
[519]2940
[574]2941int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]2942                                                                  const VssRayContainer &rays)
[440]2943{
[441]2944        // if view cells already constructed
[440]2945        if (ViewCellsConstructed())
2946                return 0;
[441]2947
[440]2948        mKdTree->Construct();
2949
[480]2950        mTotalAreaValid = false;
[469]2951        // create the view cells
2952        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]2953
[480]2954        // cast rays
[574]2955        ComputeSampleContributions(rays, true, false);
[480]2956
[479]2957        EvaluateViewCellsStats();
[660]2958        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[469]2959
[440]2960        return 0;
2961}
2962
[587]2963
[440]2964bool KdViewCellsManager::ViewCellsConstructed() const
2965{
2966        return mKdTree->GetRoot() != NULL;
2967}
2968
[503]2969int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2970                                                                        const VssRayContainer &rays)
[440]2971{
2972        return 0;
2973}
2974
2975void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2976                                                                   const VssRayContainer &sampleRays)
[440]2977{
[441]2978        if (!ViewCellsConstructed())
2979                return;
2980
[469]2981        // using view cells instead of the kd PVS of objects
2982        const bool useViewCells = true;
2983        bool exportRays = false;
[440]2984
2985        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]2986        const int pvsOut = min((int)objects.size(), 10);
[466]2987        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]2988
[469]2989        if (useViewCells)
[440]2990        {
[469]2991                const int leafOut = 10;
[503]2992
[469]2993                ViewCell::NewMail();
[503]2994
[469]2995                //-- some rays for output
2996                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
2997                Debug << "visualization using " << raysOut << " samples" << endl;
2998
2999                //-- some random view cells and rays for output
3000                vector<KdLeaf *> kdLeaves;
[503]3001
[469]3002                for (int i = 0; i < leafOut; ++ i)
3003                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]3004
[469]3005                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]3006                {
[469]3007                        KdLeaf *leaf = kdLeaves[i];
3008                        RayContainer vcRays;
[503]3009
[469]3010                        cout << "creating output for view cell " << i << " ... ";
[503]3011#if 0
[469]3012                        // check whether we can add the current ray to the output rays
[503]3013                        for (int k = 0; k < raysOut; ++ k)
[440]3014                        {
[469]3015                                Ray *ray = sampleRays[k];
[503]3016
[469]3017                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
3018                                {
3019                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]3020
3021                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]3022                                        {
3023                                                vcRays.push_back(ray);
3024                                        }
3025                                }
[479]3026                        }
[503]3027#endif
[469]3028                        Intersectable::NewMail();
[503]3029
[469]3030                        ViewCell *vc = leaf->mViewCell;
[503]3031
[469]3032                        //bspLeaves[j]->Mail();
3033                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]3034
[469]3035                        Exporter *exporter = Exporter::GetExporter(s);
3036                        exporter->SetFilled();
3037
3038                        exporter->SetWireframe();
3039                        //exporter->SetFilled();
[503]3040
[469]3041                        Material m;//= RandomMaterial();
3042                        m.mDiffuseColor = RgbColor(1, 1, 0);
3043                        exporter->SetForcedMaterial(m);
[503]3044
[469]3045                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
3046                        exporter->ExportBox(box);
3047
3048                        // export rays piercing this view cell
[503]3049                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
3050
[469]3051                        m.mDiffuseColor = RgbColor(1, 0, 0);
3052                        exporter->SetForcedMaterial(m);
[503]3053
[469]3054                        // exporter->SetWireframe();
3055                        exporter->SetFilled();
[503]3056
[469]3057                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
[752]3058                        // -- output PVS of view cell
[503]3059                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]3060                        {
3061                                Intersectable *intersect = (*it).first;
3062                                if (!intersect->Mailed())
3063                                {
3064                                        exporter->ExportIntersectable(intersect);
3065                                        intersect->Mail();
[503]3066                                }
[440]3067                        }
[503]3068
[469]3069                        DEL_PTR(exporter);
3070                        cout << "finished" << endl;
[440]3071                }
[469]3072
3073                DEL_PTR(rays);
[440]3074        }
[469]3075        else // using kd PVS of objects
3076        {
3077                for (int i = 0; i < limit; ++ i)
3078                {
3079                        VssRay *ray = sampleRays[i];
[503]3080
[469]3081                        // check whether we can add this to the rays
[503]3082                        for (int j = 0; j < pvsOut; j++)
[469]3083                        {
3084                                if (objects[j] == ray->mTerminationObject)
3085                                {
3086                                        rays[j].push_back(ray);
3087                                }
3088                        }
3089                }
[440]3090
[503]3091                if (exportRays)
[469]3092                {
3093                        Exporter *exporter = NULL;
3094                        exporter = Exporter::GetExporter("sample-rays.x3d");
3095                        exporter->SetWireframe();
3096                        exporter->ExportKdTree(*mKdTree);
[503]3097
[728]3098                        for (i = 0; i < pvsOut; i++)
[469]3099                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
3100
3101                        exporter->SetFilled();
[503]3102
[469]3103                        delete exporter;
3104                }
[440]3105
[503]3106                for (int k=0; k < pvsOut; k++)
[469]3107                {
3108                        Intersectable *object = objects[k];
[503]3109                        char s[64];
[469]3110                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]3111
[469]3112                        Exporter *exporter = Exporter::GetExporter(s);
3113                        exporter->SetWireframe();
[503]3114
[469]3115                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
3116                        Intersectable::NewMail();
[503]3117
[469]3118                        // avoid adding the object to the list
3119                        object->Mail();
3120                        ObjectContainer visibleObjects;
[503]3121
3122                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]3123                        {
3124                                KdNode *node = (*i).first;
3125                                exporter->ExportBox(mKdTree->GetBox(node));
[503]3126
[469]3127                                mKdTree->CollectObjects(node, visibleObjects);
3128                        }
[503]3129
[469]3130                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
3131                        exporter->SetFilled();
[503]3132
[469]3133                        for (int j = 0; j < visibleObjects.size(); j++)
3134                                exporter->ExportIntersectable(visibleObjects[j]);
[503]3135
[469]3136                        Material m;
3137                        m.mDiffuseColor = RgbColor(1, 0, 0);
3138                        exporter->SetForcedMaterial(m);
3139                        exporter->ExportIntersectable(object);
[503]3140
[469]3141                        delete exporter;
[440]3142                }
[503]3143        }
[440]3144}
3145
[469]3146
[482]3147void KdViewCellsManager::ExportColor(Exporter *exporter,
3148                                                                         ViewCell *vc) const
3149{
3150        // TODO
3151}
3152
[666]3153
[580]3154ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
3155{
3156        return new KdViewCell(mesh);
3157}
[482]3158
[580]3159
3160void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3161                                                                                                ViewCell *vc,
[660]3162                                                                                                const Plane3 *clipPlane) const
[482]3163{
[580]3164        ViewCellContainer leaves;
[485]3165
[580]3166        mViewCellsTree->CollectLeaves(vc, leaves);
3167        ViewCellContainer::const_iterator it, it_end = leaves.end();
3168
3169        for (it = leaves.begin(); it != it_end; ++ it)
3170        {
3171                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
3172       
3173                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
3174        }
[482]3175}
3176
3177
[440]3178int KdViewCellsManager::GetType() const
3179{
3180        return ViewCellsManager::KD;
3181}
3182
3183
[441]3184
[440]3185KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
3186{
3187        KdNode *node = leaf;
3188
3189        while (node->mParent && node->mDepth > mKdPvsDepth)
3190                node = node->mParent;
3191        return node;
3192}
3193
[469]3194int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
3195                                                                                const Vector3 &termination,
3196                                                                                ViewCellContainer &viewcells)
[466]3197{
[469]3198        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]3199}
3200
[469]3201
[503]3202void KdViewCellsManager::CreateMesh(ViewCell *vc)
3203{
[551]3204        // TODO
[503]3205}
3206
[580]3207
3208
3209void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3210                                                                                                vector<MergeCandidate> &candidates)
3211{
3212        // TODO
3213}
3214
3215
[440]3216/**********************************************************************/
3217/*                   VspKdViewCellsManager implementation             */
3218/**********************************************************************/
3219
[482]3220
[938]3221VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree, Environment *env):
3222ViewCellsManager(env), mVspKdTree(vspKdTree)
[440]3223{
[938]3224        mEnvironment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
[468]3225        mVspKdTree->SetViewCellsManager(this);
3226}
[462]3227
[471]3228float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]3229{
[605]3230        // compute view cell area / volume as subsititute for probability
3231        if (0)
3232                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
3233        else
3234                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[440]3235}
3236
[462]3237
[468]3238
[503]3239
[480]3240void VspKdViewCellsManager::CollectViewCells()
3241{
3242        mVspKdTree->CollectViewCells(mViewCells);
3243}
[462]3244
[570]3245
[574]3246int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
3247                                                                                                const VssRayContainer &rays)
[440]3248{
[441]3249        // if view cells already constructed
[440]3250        if (ViewCellsConstructed())
3251                return 0;
[503]3252
[469]3253        VssRayContainer constructionRays;
3254        VssRayContainer savedRays;
[440]3255
[503]3256        GetRaySets(rays,
[574]3257                           mInitialSamples,
[503]3258                           constructionRays,
[485]3259                           &savedRays);
[503]3260
3261        Debug << "constructing vsp kd tree using "
[469]3262                  << (int)constructionRays.size() << " samples" << endl;
[452]3263
[542]3264        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]3265        Debug << mVspKdTree->GetStatistics() << endl;
3266
[482]3267        // export leaf building blocks
3268        ExportLeaves(objects, rays);
[480]3269
[469]3270        // finally merge kd leaf building blocks to view cells
[485]3271        const int merged = mVspKdTree->MergeViewCells(rays);
3272
3273        // collapse siblings belonging to the same view cell
[486]3274        mVspKdTree->RefineViewCells(rays);
[485]3275
[542]3276        // collapse siblings belonging to the same view cell
[503]3277        mVspKdTree->CollapseTree();
3278
[482]3279        // evaluale view cell stats
3280        ResetViewCells();
[469]3281
[660]3282        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[482]3283
[485]3284        long startTime = GetTime();
[660]3285
[469]3286        // recast rest of rays
[574]3287        ComputeSampleContributions(savedRays, true, false);
[503]3288
3289        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]3290                  << " secs" << endl;
[469]3291
3292        return merged;
[440]3293}
3294
3295bool VspKdViewCellsManager::ViewCellsConstructed() const
3296{
3297        return mVspKdTree->GetRoot() != NULL;
3298}
3299
[441]3300
[462]3301ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
3302{
3303        return new VspKdViewCell(mesh);
3304}
3305
[503]3306int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]3307                                                                           const VssRayContainer &rays)
[440]3308{
[441]3309        if (!ViewCellsConstructed())
3310                return 0;
3311
[482]3312        // recalculate stats
3313        EvaluateViewCellsStats();
3314
[469]3315        return 0;
[440]3316}
3317
[482]3318
3319void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
3320                                                                                 const VssRayContainer &sampleRays)
[440]3321{
[441]3322        if (!ViewCellsConstructed())
3323                return;
3324
[482]3325        //-- export leaf building blocks
[503]3326        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]3327        if (!exporter)
3328                return;
3329
[598]3330        if (mExportGeometry)
3331                exporter->ExportGeometry(objects);
3332       
[482]3333        //exporter->SetWireframe();
3334        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
3335        exporter->ExportVspKdTree(*mVspKdTree);
3336
[503]3337        if (mExportRays)
[440]3338        {
[503]3339                const float prob = (float)mVisualizationSamples
[482]3340                        / ((float)sampleRays.size() + Limits::Small);
[440]3341
[482]3342                exporter->SetWireframe();
[440]3343
[482]3344                //-- collect uniformly distributed rays
3345                VssRayContainer rays;
[440]3346
[482]3347                for (int i = 0; i < sampleRays.size(); ++ i)
3348                {
3349                        if (RandomValue(0,1) < prob)
3350                                rays.push_back(sampleRays[i]);
[440]3351                }
[482]3352                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]3353        }
3354
[482]3355        delete exporter;
3356}
3357
[726]3358
[482]3359void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
3360                                                                          const VssRayContainer &sampleRays)
3361{
3362        if (!ViewCellsConstructed())
3363                return;
[503]3364
[482]3365        //-- export single view cells
3366        for (int i = 0; i < 10; ++ i)
[440]3367        {
[482]3368                char s[64];
3369                sprintf(s, "vsp_viewcell%04d.x3d", i);
3370                Exporter *exporter = Exporter::GetExporter(s);
[503]3371                const int idx =
[482]3372                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]3373
[503]3374                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]3375
3376                //-- export geometry
3377                Material m;
3378                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]3379
[482]3380                exporter->SetForcedMaterial(m);
3381                exporter->SetWireframe();
3382
[580]3383                ExportViewCellGeometry(exporter, vc);
[482]3384
3385                //-- export stored rays
[580]3386               
[485]3387                if (mExportRays)
[440]3388                {
[580]3389                        ViewCellContainer leaves;
3390                        mViewCellsTree->CollectLeaves(vc, leaves);
[440]3391
[580]3392                        ViewCellContainer::const_iterator it,
3393                                it_end = leaves.end();
3394
3395                        for (it = leaves.begin(); it != it_end; ++ it)
[482]3396                        {
[580]3397                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
3398                                VspKdLeaf *leaf = vspKdVc->mLeaf;
[482]3399                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]3400
[482]3401                                VssRayContainer vssRays;
[483]3402
3403                                VssRayContainer castRays;
3404                                VssRayContainer initRays;
3405
[482]3406                                leaf->GetRays(vssRays);
[440]3407
[482]3408                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]3409                                const float prop = 200.0f / (float)vssRays.size();
[440]3410
[482]3411                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]3412                                {
[485]3413                                        if (Random(1) < prop)
[483]3414                                                if ((*it)->mTerminationObject == NULL)
3415                                                        castRays.push_back(*it);
[503]3416                                                else
[483]3417                                                        initRays.push_back(*it);
3418                                }
3419
3420                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
3421                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]3422                        }
3423                }
[580]3424       
[482]3425                //-- output PVS of view cell
3426                m.mDiffuseColor = RgbColor(1, 0, 0);
3427                exporter->SetForcedMaterial(m);
[440]3428
[483]3429                Intersectable::NewMail();
3430
[482]3431                ObjectPvsMap::const_iterator it,
3432                        it_end = vc->GetPvs().mEntries.end();
3433
3434                exporter->SetFilled();
3435
[503]3436                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]3437                {
3438                        Intersectable *intersect = (*it).first;
3439
3440                        if (!intersect->Mailed())
3441                        {
3442                                Material m = RandomMaterial();
3443                                exporter->SetForcedMaterial(m);
3444
3445                                exporter->ExportIntersectable(intersect);
3446                                intersect->Mail();
[503]3447                        }
[482]3448                }
3449
3450                delete exporter;
[440]3451        }
[462]3452
3453        //-- export final view cells
[503]3454        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
3455
[483]3456
[508]3457        ExportViewCellsForViz(exporter);
[462]3458
[503]3459        if (mExportGeometry)
[465]3460        {
3461                exporter->SetFilled();
[462]3462                exporter->ExportGeometry(objects);
[465]3463        }
[469]3464
[503]3465        if (mExportRays)
[462]3466        {
[503]3467                const float prob = (float)mVisualizationSamples
[482]3468                        / ((float)sampleRays.size() + Limits::Small);
[503]3469
[462]3470                exporter->SetWireframe();
[503]3471
[466]3472                VssRayContainer rays;
[503]3473
[462]3474                for (int i = 0; i < sampleRays.size(); ++ i)
3475                {
[466]3476                  if (RandomValue(0,1) < prob)
3477                        rays.push_back(sampleRays[i]);
[462]3478                }
[503]3479                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]3480        }
3481
3482        delete exporter;
[440]3483}
3484
3485int VspKdViewCellsManager::GetType() const
3486{
3487        return VSP_KD;
3488}
[442]3489
[462]3490
[469]3491int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
3492                                                                                   const Vector3 &termination,
3493                                                                                   ViewCellContainer &viewcells)
[466]3494{
[469]3495        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]3496}
3497
[477]3498
[482]3499void VspKdViewCellsManager::ExportColor(Exporter *exporter,
3500                                                                                ViewCell *vc) const
3501{
3502        if (mColorCode == 0) // Random color
3503                return;
[503]3504
[482]3505        float importance = 0;
[477]3506
[482]3507        switch (mColorCode)
3508        {
3509        case 1: // pvs
3510                {
[801]3511                        importance = (float)mViewCellsTree->GetPvsSize(vc) /
[660]3512                                (float)mCurrentViewCellsStats.maxPvs;
[482]3513                }
3514                break;
[580]3515        case 2: // merged leaves
[482]3516                {
[744]3517                const int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
[580]3518                        importance = (float)lSize /
[660]3519                                (float)mCurrentViewCellsStats.maxLeaves;
[482]3520                }
3521                break;
[485]3522        case 3: // merged tree depth difference
[482]3523                {
[503]3524                        //importance = (float)GetMaxTreeDiff(vc) /
[482]3525                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3526                }
3527                break;
3528        default:
3529                break;
3530        }
3531
3532        Material m;
3533        m.mDiffuseColor.b = 1.0f;
3534        m.mDiffuseColor.r = importance;
3535        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3536        //Debug << "importance: " << importance << endl;
3537        exporter->SetForcedMaterial(m);
3538}
3539
3540
[580]3541void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3542                                                                                                   ViewCell *vc,
[660]3543                                                                                                   const Plane3 *clipPlane) const
[482]3544{
3545        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
3546
[486]3547        Mesh m;
[580]3548
3549        ViewCellContainer leaves;
3550        mViewCellsTree->CollectLeaves(vc, leaves);
3551
3552        ViewCellContainer::const_iterator it, it_end = leaves.end();
3553
3554        for (it = leaves.begin(); it != it_end; ++ it)
[486]3555        {
[580]3556                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
[860]3557                IncludeBoxInMesh(mVspKdTree->GetBBox(l), m);
[486]3558        }
3559
3560        exporter->ExportMesh(&m);
[482]3561}
3562
3563
[503]3564void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
3565{
[551]3566        //TODO
[503]3567}
[442]3568
[574]3569
[584]3570void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3571                                                                                                   vector<MergeCandidate> &candidates)
[580]3572{
3573        // TODO
3574}
[574]3575
[580]3576
[503]3577/**************************************************************************/
3578/*                   VspBspViewCellsManager implementation                */
3579/**************************************************************************/
[482]3580
[503]3581
[938]3582VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree, Environment *env):
3583ViewCellsManager(env), mVspBspTree(vspBspTree)
[442]3584{
[938]3585        mEnvironment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
[478]3586        mVspBspTree->SetViewCellsManager(this);
[590]3587        mVspBspTree->mViewCellsTree = mViewCellsTree;
[442]3588}
3589
[477]3590
[475]3591VspBspViewCellsManager::~VspBspViewCellsManager()
3592{
3593}
3594
[477]3595
[471]3596float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]3597{
[551]3598        if (0 && mVspBspTree->mUseAreaForPvs)
[547]3599                return GetArea(viewCell) / GetAccVcArea();
3600        else
3601                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]3602}
3603
[477]3604
[480]3605void VspBspViewCellsManager::CollectViewCells()
3606{
[581]3607        // view cells tree constructed
3608        if (!ViewCellsTreeConstructed())
3609        {
[590]3610                mVspBspTree->CollectViewCells(mViewCells, false);
[581]3611        }
3612        else
[664]3613        {       // we can use the view cells tree hierarchy to get the right set
[600]3614                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
[581]3615        }
[480]3616}
3617
3618
[442]3619bool VspBspViewCellsManager::ViewCellsConstructed() const
3620{
3621        return mVspBspTree->GetRoot() != NULL;
3622}
3623
[462]3624
[442]3625ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3626{
3627        return new BspViewCell(mesh);
3628}
3629
[569]3630
[574]3631int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[600]3632                                                                                                 const VssRayContainer &rays)
[442]3633{
[710]3634        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
3635
[503]3636        // if view cells were already constructed
3637        if (ViewCellsConstructed())
3638                return 0;
[442]3639
[503]3640        int sampleContributions = 0;
3641
3642        VssRayContainer sampleRays;
3643
[574]3644        int limit = min (mInitialSamples, (int)rays.size());
[503]3645
[469]3646        VssRayContainer constructionRays;
3647        VssRayContainer savedRays;
[442]3648
[660]3649        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
[664]3650                  << ", actual rays: " << (int)rays.size() << endl;
[587]3651
[574]3652        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
[487]3653
[574]3654        Debug << "initial rays: " << (int)constructionRays.size() << endl;
[508]3655        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]3656
[564]3657
[666]3658        //TODO: remove
[667]3659        if (1)
3660                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[666]3661        else
[667]3662                mVspBspTree->Construct(rays, &mViewSpaceBox);
3663
[490]3664        // collapse invalid regions
[491]3665        cout << "collapsing invalid tree regions ... ";
[495]3666        long startTime = GetTime();
[503]3667        int collapsedLeaves = mVspBspTree->CollapseTree();
[587]3668        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
3669                  << " seconds" << endl;
3670
[495]3671    cout << "finished" << endl;
[503]3672
[660]3673        // -- stats
3674        Debug << mVspBspTree->GetStatistics() << endl;
3675
[480]3676        ResetViewCells();
[660]3677        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[503]3678
[491]3679
[495]3680        startTime = GetTime();
[503]3681
[491]3682        cout << "Computing remaining ray contributions ... ";
[605]3683
[469]3684        // recast rest of rays
[605]3685        if (SAMPLE_AFTER_SUBDIVISION)
3686                ComputeSampleContributions(savedRays, true, false);
[752]3687
[491]3688        cout << "finished" << endl;
3689
[503]3690        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]3691                  << " secs" << endl;
[442]3692
[485]3693        cout << "construction finished" << endl;
[503]3694
[719]3695        // real meshes are contructed at this stage
3696        if (0)
3697        {
3698                cout << "finalizing view cells ... ";
3699                FinalizeViewCells(true);
3700                cout << "finished" << endl;
3701        }
3702
[442]3703        return sampleContributions;
3704}
3705
[489]3706
[503]3707void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
3708                                                                                        const ObjectContainer &objects)
[475]3709{
[442]3710    int vcSize = 0;
3711        int pvsSize = 0;
3712
[650]3713        //-- merge view cells
3714        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
3715        long startTime = GetTime();
3716
3717
[597]3718        if (mMergeViewCells)
3719        {
3720                // TODO: should be done BEFORE the ray casting
[710]3721                // compute tree by merging the nodes based on cost heuristics
[650]3722                mViewCellsTree->ConstructMergeTree(rays, objects);
3723        }
3724        else
3725        {
[710]3726                // compute tree by merging the nodes of the spatial hierarchy
3727                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
3728                mViewCellsTree->SetRoot(root);
[752]3729
3730                // compute pvs
3731                ObjectPvs pvs;
3732                UpdatePvsForEvaluation(root, pvs);
[650]3733        }
[442]3734
[666]3735        if (1)
3736        {
3737                char mstats[100];
[752]3738                ObjectPvs pvs;
3739
[938]3740                mEnvironment->GetStringValue("ViewCells.mergeStats", mstats);
[666]3741                mViewCellsTree->ExportStats(mstats);
3742        }
[485]3743
[650]3744        //-- stats and visualizations
3745        cout << "finished merging" << endl;
3746        cout << "merged view cells in "
3747                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[503]3748
[650]3749        Debug << "Postprocessing: Merged view cells in "
3750                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
3751       
3752
[600]3753        int savedColorCode = mColorCode;
3754       
[660]3755        // get currently active view cell set
3756        ResetViewCells();
3757        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
3758
[485]3759        //BspLeaf::NewMail();
[667]3760        if (1) // export merged view cells
[483]3761        {
[600]3762                mColorCode = 0;
[744]3763                Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
[660]3764               
[485]3765                cout << "exporting view cells after merge ... ";
3766
3767                if (exporter)
[483]3768                {
[600]3769                        if (0)
3770                                exporter->SetWireframe();
3771                        else
3772                                exporter->SetFilled();
3773
3774                        ExportViewCellsForViz(exporter);
3775
[485]3776                        if (mExportGeometry)
[483]3777                        {
[485]3778                                Material m;
3779                                m.mDiffuseColor = RgbColor(0, 1, 0);
3780                                exporter->SetForcedMaterial(m);
3781                                exporter->SetFilled();
[442]3782
[485]3783                                exporter->ExportGeometry(objects);
[442]3784                        }
[485]3785
[600]3786                        delete exporter;
3787                }
3788                cout << "finished" << endl;
3789        }
3790
[667]3791        if (1) // export merged view cells using pvs coding
[600]3792        {
3793                mColorCode = 1;
3794
[744]3795                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
[600]3796       
3797                cout << "exporting view cells after merge (pvs size) ... ";     
3798
3799                if (exporter)
3800                {
[598]3801                        if (0)
3802                                exporter->SetWireframe();
3803                        else
3804                                exporter->SetFilled();
3805
3806                        ExportViewCellsForViz(exporter);
3807
[600]3808                        if (mExportGeometry)
3809                        {
3810                                Material m;
3811                                m.mDiffuseColor = RgbColor(0, 1, 0);
3812                                exporter->SetForcedMaterial(m);
3813                                exporter->SetFilled();
3814
3815                                exporter->ExportGeometry(objects);
3816                        }
3817
[485]3818                        delete exporter;
[442]3819                }
[485]3820                cout << "finished" << endl;
[442]3821        }
[600]3822
3823        mColorCode = savedColorCode;
3824
[503]3825}
[475]3826
[503]3827
[609]3828bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
[607]3829{
[609]3830        return GetSpatialNode(viewCell) != NULL;
[607]3831}
3832
3833
[609]3834BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
[607]3835{
3836        if (!viewCell->IsLeaf())
3837        {
3838                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
3839
[609]3840                return bspVc->mLeaf;
3841        }
[607]3842        else
3843        {
3844                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
3845
3846                // cannot be node of binary tree
3847                if (interior->mChildren.size() != 2)
[609]3848                        return NULL;
[607]3849
3850                ViewCell *left = interior->mChildren[0];
3851                ViewCell *right = interior->mChildren[1];
3852
[609]3853                BspNode *leftNode = GetSpatialNode(left);
3854                BspNode *rightNode = GetSpatialNode(right);
[607]3855
[609]3856                if (leftNode && rightNode && leftNode->IsSibling(rightNode))
[607]3857                {
[609]3858                        return leftNode->GetParent();
[607]3859                }
[609]3860        }
[607]3861
[609]3862        return NULL;
[607]3863}
3864
3865
[564]3866void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
3867                                                                                         const ObjectContainer &objects)
[503]3868{
[485]3869        Debug << "render time before refine:" << endl;
3870        mRenderer->RenderScene();
[503]3871        SimulationStatistics ss;
[485]3872        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
3873    Debug << ss << endl;
3874
[489]3875        cout << "Refining the merged view cells ... ";
[503]3876        long startTime = GetTime();
[485]3877
3878        // refining the merged view cells
[580]3879        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
[485]3880
[442]3881        //-- stats and visualizations
3882        cout << "finished" << endl;
[485]3883        cout << "refined " << refined << " view cells in "
[442]3884                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
3885
[485]3886        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]3887                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]3888}
[495]3889
[517]3890
[503]3891int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
3892                                                                                const VssRayContainer &rays)
[840]3893{
[503]3894        if (!ViewCellsConstructed())
3895        {
[517]3896                Debug << "postprocess error: no view cells constructed" << endl;
[503]3897                return 0;
3898        }
[520]3899
[564]3900
[609]3901        // view cells already finished before post processing step
3902        // (i.e. because they were loaded)
[520]3903        if (mViewCellsFinished)
[542]3904        {
[551]3905                FinalizeViewCells(true);
[542]3906                EvaluateViewCellsStats();
[577]3907
[517]3908                return 0;
[542]3909        }
[448]3910
[710]3911        // check if new view cells turned invalid
3912        int minPvs, maxPvs;
[564]3913
[710]3914        if (0)
3915        {
3916                minPvs = mMinPvsSize;
3917                maxPvs = mMaxPvsSize;
3918        }
3919        else
3920        {
3921                minPvs = mPruneEmptyViewCells ? 1 : 0;
3922                maxPvs = mMaxPvsSize;
3923        }
[720]3924
[710]3925        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3926        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3927       
3928        SetValidity(minPvs, maxPvs);
3929
[574]3930        // update valid view space according to valid view cells
[720]3931        if (0) mVspBspTree->ValidateTree();
[542]3932
[720]3933        // area has to be recomputed
[574]3934        mTotalAreaValid = false;
[517]3935        VssRayContainer postProcessRays;
[605]3936        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3937
[517]3938        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]3939
[517]3940
[552]3941        // should maybe be done here to allow merge working with area or volume
3942        // and to correct the rendering statistics
[719]3943        if (0) FinalizeViewCells(false);
[720]3944               
[597]3945        //-- merge the individual view cells
3946        MergeViewCells(postProcessRays, objects);
[591]3947       
[720]3948
3949        // only for debugging purpose: test if the subdivision is valid
[693]3950        TestSubdivision();
3951
[597]3952        //-- refines the merged view cells
[720]3953        if (0) RefineViewCells(postProcessRays, objects);
[568]3954
[719]3955       
[660]3956        //-- render simulation after merge + refine
[605]3957        cout << "\nevaluating bsp view cells render time before compress ... ";
3958        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
3959        SimulationStatistics ss;
3960        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[600]3961 
[580]3962
[605]3963        cout << " finished" << endl;
3964        cout << ss << endl;
3965        Debug << ss << endl;
[600]3966
3967
3968        //-- compression
3969        if (ViewCellsTreeConstructed() && mCompressViewCells)
3970        {
3971                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3972                Debug << "number of entries before compress: " << pvsEntries << endl;
3973
[752]3974                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
[600]3975
3976                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3977                Debug << "number of entries after compress: " << pvsEntries << endl;
3978        }
3979
[660]3980
[517]3981        // collapse sibling leaves that share the same view cell
[840]3982        if (0) mVspBspTree->CollapseTree();
[586]3983
[574]3984        // recompute view cell list and statistics
[520]3985        ResetViewCells();
3986
[719]3987        // compute final meshes and volume / area
3988        if (1) FinalizeViewCells(true);
[517]3989
[508]3990        // write view cells to disc
3991        if (mExportViewCells)
3992        {
[840]3993                char filename[100];
[938]3994                mEnvironment->GetStringValue("ViewCells.filename", filename);
[931]3995                ExportViewCells(filename, mExportPvs, objects);
[840]3996        }
[517]3997
[840]3998       
3999        // export bounding boxes
4000        if (mExportBboxesForPvs)
4001        {
4002                char filename[100];
[938]4003                mEnvironment->GetStringValue("ViewCells.boxesFilename", filename);
[850]4004       
[840]4005                ExportBoundingBoxes(filename, objects);
[850]4006/*
4007                IndexedBoundingBoxContainer boxes;
4008                LoadBoundingBoxes(filename, boxes);
4009
4010                IndexedBoundingBoxContainer::const_iterator it, it_end = boxes.end();
4011
4012                for (it = boxes.begin(); it != it_end; ++ it)
4013                {
4014                        IndexedBoundingBox ibox = *it;
4015                        AxisAlignedBox3 box = ibox.second;
4016
4017                        Debug << ibox.first << " "
4018                                  << box.Min().x << " "
4019                                  << box.Min().y << " "
4020                                  << box.Min().z << " "
4021                                  << box.Max().x << " "
4022                                  << box.Max().y << " "
4023                  << box.Max().z << endl;       
4024                }*/
[508]4025        }
[503]4026
4027        return 0;
[442]4028}
4029
[490]4030
[442]4031int VspBspViewCellsManager::GetType() const
4032{
4033        return VSP_BSP;
4034}
4035
4036
[650]4037ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[609]4038{
[752]4039        // terminate recursion
[650]4040        if (root->IsLeaf())
4041        {
[752]4042                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
4043                leaf->GetViewCell()->SetMergeCost(0.0f);
4044                return leaf->GetViewCell();
[650]4045        }
4046       
[752]4047       
[650]4048        BspInterior *interior = dynamic_cast<BspInterior *>(root);
4049        ViewCellInterior *viewCellInterior = new ViewCellInterior();
4050               
[752]4051        // evaluate merge cost for priority traversal
[650]4052        float mergeCost = 1.0f / (float)root->mTimeStamp;
4053        viewCellInterior->SetMergeCost(mergeCost);
[610]4054
[650]4055        float volume = 0;
4056       
4057        BspNode *front = interior->GetFront();
4058        BspNode *back = interior->GetBack();
[649]4059
[752]4060
4061        ObjectPvs frontPvs, backPvs;
4062
4063        //-- recursivly compute child hierarchies
[650]4064        ViewCell *backVc = ConstructSpatialMergeTree(back);
4065        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]4066
[752]4067
4068        viewCellInterior->SetupChildLink(backVc);
[650]4069        viewCellInterior->SetupChildLink(frontVc);
4070
4071        volume += backVc->GetVolume();
4072        volume += frontVc->GetVolume();
4073
4074        viewCellInterior->SetVolume(volume);
4075
4076        return viewCellInterior;
[609]4077}
4078
4079
[752]4080
4081void VspBspViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
4082{
4083        // terminate traversal
4084        if (root->IsLeaf())
4085        {
4086                pvs = root->GetPvs();
4087
[801]4088                root->mPvsSize = root->GetPvs().GetSize();
[752]4089                root->mPvsSizeValid = true;
4090
4091                return;
4092        }
4093       
[801]4094        //-- interior node => propagate pvs up
[752]4095        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
[801]4096        interior->GetPvs().Clear();
4097        pvs.Clear();
4098        vector<ObjectPvs> pvsList;
4099
[752]4100        ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
4101
4102        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit)
4103        {
4104                ObjectPvs objPvs;
4105               
4106                //-- recursivly compute child pvss
4107                UpdatePvsForEvaluation(*vit, objPvs);
4108
4109                // store pvs in vector
4110                pvsList.push_back(objPvs);
4111        }
4112
4113#if 1
[801]4114
[752]4115        Intersectable::NewMail();
4116
4117        //-- faster way of computing pvs:
4118        //   construct merged pvs by adding
4119        //   and only those of the next pvs which were not mailed.
4120        //   note: sumpdf is not correct!!
4121        vector<ObjectPvs>::iterator oit = pvsList.begin();
4122
4123        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
4124        {
4125            ObjectPvsMap::iterator pit, pit_end = (*oit).mEntries.end();
4126       
4127                for (pit = (*oit).mEntries.begin(); pit != pit_end; ++ pit)
4128                {
4129                        Intersectable *intersect = (*pit).first;
4130
4131                        if (!intersect->Mailed())
4132                        {
4133                                pvs.AddSample(intersect, (*pit).second.mSumPdf);
4134                                intersect->Mail();
4135                        }
4136                }
4137        }
4138
4139        // store pvs in this node
4140        if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
4141        {
4142                interior->mPvs = pvs;
4143        }
4144       
4145        // set new pvs size
4146        interior->mPvsSize = pvs.GetSize();
4147        interior->mPvsSizeValid = true;
4148
4149#else
[801]4150
[752]4151        // really merge cells: slow put sumpdf is correct
4152        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
4153        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
4154#endif
4155
4156}
4157
4158
[490]4159bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
4160{
4161        if (!ViewCellsConstructed())
4162                return ViewCellsManager::GetViewPoint(viewPoint);
4163
4164        // TODO: set reasonable limit
4165        const int limit = 20;
4166
4167        for (int i = 0; i < limit; ++ i)
4168        {
[542]4169                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]4170                if (mVspBspTree->ViewPointValid(viewPoint))
4171                {
4172                        return true;
4173                }
4174        }
4175        Debug << "failed to find valid view point, taking " << viewPoint << endl;
4176        return false;
4177}
4178
4179
4180bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
4181{
[569]4182  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
4183  // validy update in preprocessor for all managers)
4184  return ViewCellsManager::ViewPointValid(viewPoint);
[570]4185
[569]4186  //    return mViewSpaceBox.IsInside(viewPoint) &&
4187  //               mVspBspTree->ViewPointValid(viewPoint);
[490]4188}
4189
4190
[442]4191void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]4192                                                                           const VssRayContainer &sampleRays)
[442]4193{
4194        if (!ViewCellsConstructed())
4195                return;
4196
[485]4197        VssRayContainer visRays;
4198        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]4199
[600]4200       
[651]4201        if (1) // export view cells
[612]4202        {       // hack pvs
[600]4203                int savedColorCode = mColorCode;
[801]4204                mColorCode = 1;
4205       
[822]4206                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[600]4207               
[442]4208                if (exporter)
4209                {
[580]4210                        cout << "exporting view cells after post process ... ";
4211
[600]4212                        if (0)
[542]4213                        {
4214                                exporter->SetWireframe();
4215                                exporter->ExportBox(mViewSpaceBox);
4216                                exporter->SetFilled();
4217                        }
4218
[485]4219                        if (mExportGeometry)
[542]4220                        {
[485]4221                                exporter->ExportGeometry(objects);
[542]4222                        }
[489]4223
4224                        // export rays
[490]4225                        if (mExportRays)
[489]4226                        {
[490]4227                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
4228                        }
[564]4229
[801]4230                        //exporter->SetFilled();
4231                        bool b = mUseClipPlaneForViz;
4232                        mUseClipPlaneForViz = false;
[508]4233                        ExportViewCellsForViz(exporter);
[801]4234                        mUseClipPlaneForViz = b;
4235               
[442]4236                        delete exporter;
[580]4237                        cout << "finished" << endl;
[442]4238                }
[600]4239
4240                mColorCode = savedColorCode;
[557]4241        }
[503]4242
[600]4243        if (0)
[577]4244        {
4245                cout << "exporting depth map ... ";
4246
4247                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
4248                if (exporter)
4249                {
4250                        if (1)
4251                        {
4252                                exporter->SetWireframe();
4253                                exporter->ExportBox(mViewSpaceBox);
4254                                exporter->SetFilled();
4255                        }
4256
4257                        if (mExportGeometry)
4258                        {
4259                                exporter->ExportGeometry(objects);
4260                        }
4261
4262                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
4263
4264                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
4265
4266                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
4267                        {
[582]4268                                ViewCell *vc = *vit;
[577]4269
[580]4270                                ViewCellContainer leaves;
4271                                mViewCellsTree->CollectLeaves(vc, leaves);
[577]4272
[580]4273                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
4274
4275                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
[577]4276                                {
[580]4277                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
[577]4278
4279                                        Material m;
4280
4281                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
4282                                        m.mDiffuseColor.r = relDepth;
4283                                        m.mDiffuseColor.g = 0.0f;
4284                                        m.mDiffuseColor.b = 1.0f - relDepth;
4285
4286                    exporter->SetForcedMaterial(m);
4287                               
4288
4289                                        BspNodeGeometry geom;
4290                                        mVspBspTree->ConstructGeometry(leaf, geom);
[678]4291                                        exporter->ExportPolygons(geom.GetPolys());
[577]4292                                }
4293                        }
4294
4295                        delete exporter;
4296                }
4297
4298
4299                cout << "finished" << endl;
4300        }
4301
[442]4302        //-- visualization of the BSP splits
4303        bool exportSplits = false;
[938]4304        mEnvironment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]4305
[442]4306        if (exportSplits)
4307        {
4308                cout << "exporting splits ... ";
[485]4309                ExportSplits(objects, visRays);
[442]4310                cout << "finished" << endl;
4311        }
4312
[542]4313        //-- export single view cells
[485]4314        ExportBspPvs(objects, visRays);
[442]4315}
4316
[503]4317
[485]4318void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
4319                                                                                  const VssRayContainer &rays)
[442]4320{
4321        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
4322
[503]4323        if (exporter)
4324        {
4325                Material m;
[442]4326                m.mDiffuseColor = RgbColor(1, 0, 0);
4327                exporter->SetForcedMaterial(m);
4328                exporter->SetWireframe();
[503]4329
[448]4330                exporter->ExportBspSplits(*mVspBspTree, true);
[442]4331
4332                // take forced material, else big scenes cannot be viewed
4333                m.mDiffuseColor = RgbColor(0, 1, 0);
4334                exporter->SetForcedMaterial(m);
4335                exporter->SetFilled();
4336
4337                exporter->ResetForcedMaterial();
[503]4338
[442]4339                // export rays
[485]4340                if (mExportRays)
4341                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]4342
[485]4343                if (mExportGeometry)
[442]4344                        exporter->ExportGeometry(objects);
4345
4346                delete exporter;
4347        }
4348}
4349
[503]4350
[485]4351void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
4352                                                                                  const VssRayContainer &rays)
[442]4353{
[639]4354        const int leafOut = 20;
[503]4355
[442]4356        ViewCell::NewMail();
[503]4357
[639]4358        cout << "visualization using " << (int)rays.size() << " samples" << endl;
4359        Debug << "visualization using " << (int)rays.size() << " samples" << endl;
[475]4360        Debug << "\nOutput view cells: " << endl;
[503]4361
[694]4362        const bool sortViewCells = true;
[801]4363       
[694]4364
[485]4365        // sort view cells to visualize the largest view cells
[694]4366        if (sortViewCells)
[801]4367        {
4368                //stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
4369                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
4370        }
4371
[503]4372        int limit = min(leafOut, (int)mViewCells.size());
[483]4373
[639]4374        int raysOut = 0;
[587]4375
[485]4376        //-- some rays for output
[478]4377        for (int i = 0; i < limit; ++ i)
[442]4378        {
[478]4379                cout << "creating output for view cell " << i << " ... ";
[503]4380
[582]4381                ViewCell *vc;
[574]4382       
[694]4383                if (sortViewCells) // largest view cell pvs first
[582]4384                        vc = mViewCells[i];
[574]4385                else
[639]4386                        vc = mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
[442]4387
[801]4388                ObjectPvs pvs;
4389                mViewCellsTree->GetPvs(vc, pvs);
4390
[639]4391                //bspLeaves[j]->Mail();
4392                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
4393                Exporter *exporter = Exporter::GetExporter(s);
4394               
4395                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc) << endl;
[587]4396
[801]4397                //-- export the sample rays
[639]4398                if (1 || mExportRays)
[442]4399                {
[694]4400                        // output rays stored with the view cells during subdivision
[643]4401                        if (0)
[442]4402                        {
[639]4403                                VssRayContainer vcRays;
4404                VssRayContainer collectRays;
4405
4406                                raysOut = min((int)rays.size(), 100);
4407
4408                                // collect intial view cells
4409                                ViewCellContainer leaves;
4410                                mViewCellsTree->CollectLeaves(vc, leaves);
4411
4412                                ViewCellContainer::const_iterator vit, vit_end = leaves.end();
4413       
4414                                for (vit = leaves.begin(); vit != vit_end; ++ vit)
[574]4415                                {
[639]4416                                        BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaf;
4417                               
4418                                        VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
[587]4419
[639]4420                                        for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
4421                                        {
4422                                                collectRays.push_back(*rit);
4423                                        }
[574]4424                                }
[639]4425
4426                                VssRayContainer::const_iterator rit, rit_end = collectRays.end();
4427
4428                                for (rit = collectRays.begin(); rit != rit_end; ++ rit)
4429                                {
4430                                        float p = RandomValue(0.0f, (float)collectRays.size());
4431                       
4432                                        if (p < raysOut)
4433                                                vcRays.push_back(*rit);
4434                                }
[801]4435
[639]4436                                //-- export rays piercing this view cell
4437                                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[442]4438                        }
[651]4439               
[694]4440                        // associate new rays with output view cell
[643]4441                        if (1)
[639]4442                        {
4443                                VssRayContainer vcRays;
4444                                raysOut = min((int)rays.size(), mVisualizationSamples);
[801]4445
[639]4446                                // check whether we can add the current ray to the output rays
4447                                for (int k = 0; k < raysOut; ++ k)
4448                                {
4449                                        VssRay *ray = rays[k];
4450                                        for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
4451                                        {
4452                                                ViewCell *rayvc = ray->mViewCells[j];
4453       
4454                                                if (rayvc == vc)
4455                                                        vcRays.push_back(ray);
4456                                        }
4457                                }       
4458                               
4459                                //-- export rays piercing this view cell
4460                                exporter->ExportRays(vcRays, RgbColor(1, 1, 0));
4461                        }
4462
[442]4463                }
[639]4464               
[574]4465
[478]4466                exporter->SetWireframe();
[442]4467
[478]4468                Material m;//= RandomMaterial();
4469                m.mDiffuseColor = RgbColor(0, 1, 0);
4470                exporter->SetForcedMaterial(m);
[442]4471
[580]4472                ExportViewCellGeometry(exporter, vc);
[639]4473       
4474                exporter->SetFilled();
[503]4475
[801]4476                //-- export pvs
[574]4477                if (1)
4478                {
[639]4479                        ObjectPvsMap::const_iterator oit,
[801]4480                                oit_end = pvs.mEntries.end();
[483]4481
[801]4482                        Intersectable::NewMail();
[580]4483
[639]4484                        // output PVS of view cell
[801]4485                        for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
[639]4486                        {               
4487                                Intersectable *intersect = (*oit).first;
[442]4488
[639]4489                                if (!intersect->Mailed())
4490                                {
[643]4491                                        m = RandomMaterial();
4492                                        exporter->SetForcedMaterial(m);
[442]4493
[639]4494                                        exporter->ExportIntersectable(intersect);
4495                                        intersect->Mail();
4496                                }
[503]4497                        }
[442]4498                }
[801]4499               
4500                if (0)
4501                {   // export scene geometry
[643]4502                        m.mDiffuseColor = RgbColor(1, 0, 0);
4503                        exporter->SetForcedMaterial(m);
4504
[639]4505                        exporter->ExportGeometry(objects);
4506                }
[503]4507
[478]4508                DEL_PTR(exporter);
4509                cout << "finished" << endl;
[442]4510        }
[475]4511
4512        Debug << endl;
[442]4513}
4514
4515
[697]4516int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const
4517{
4518        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
4519}
4520
4521
[469]4522int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
4523                                                                                        const Vector3 &termination,
4524                                                                                        ViewCellContainer &viewcells)
[466]4525{
[469]4526        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]4527}
[482]4528
4529
[503]4530void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]4531                                                                                 ViewCell *vc) const
4532{
[564]4533        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[503]4534
[482]4535        float importance = 0;
[564]4536        static Material m;
4537
[482]4538        switch (mColorCode)
4539        {
[564]4540        case 0: // Random
4541                {
4542                        if (vcValid)
4543                        {
[598]4544                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
4545                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
4546                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
[564]4547                        }
4548                        else
4549                        {
4550                                m.mDiffuseColor.r = 0.0f;
4551                                m.mDiffuseColor.g = 1.0f;
4552                                m.mDiffuseColor.b = 0.0f;
4553                        }
[591]4554
4555                        exporter->SetForcedMaterial(m);
4556                        return;
[564]4557                }
[591]4558               
[482]4559        case 1: // pvs
4560                {
[827]4561                        importance = (float)mViewCellsTree->GetPvsSize(vc) / (float)mCurrentViewCellsStats.maxPvs;
[482]4562                }
4563                break;
4564        case 2: // merges
4565                {
[736]4566            int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
[660]4567                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]4568                }
4569                break;
4570        case 3: // merge tree differene
4571                {
[503]4572                        importance = (float)GetMaxTreeDiff(vc) /
[482]4573                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]4574
[482]4575                }
4576                break;
4577        default:
4578                break;
4579        }
4580
[564]4581        // special color code for invalid view cells
[482]4582        m.mDiffuseColor.r = importance;
4583        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[564]4584        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[547]4585
[482]4586        //Debug << "importance: " << importance << endl;
4587        exporter->SetForcedMaterial(m);
4588}
4589
4590
[580]4591void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]4592                                                    ViewCell *vc,
[660]4593                                                                                                        const Plane3 *clipPlane) const
[482]4594{
[660]4595        if (clipPlane)
[591]4596        {
4597                ViewCellContainer leaves;
4598                mViewCellsTree->CollectLeaves(vc, leaves);
4599                ViewCellContainer::const_iterator it, it_end = leaves.end();
4600
4601                for (it = leaves.begin(); it != it_end; ++ it)
4602                {
4603                        BspNodeGeometry geom;
4604
4605                        BspNodeGeometry front;
4606                        BspNodeGeometry back;
4607
4608                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4609                        mVspBspTree->ConstructGeometry(leaf, geom);
4610
[710]4611                        const float eps = 0.00000001f;
4612                        const int cf = geom.Side(*clipPlane, eps);
[682]4613
[710]4614                        if (cf == -1)
[682]4615                        {
4616                                exporter->ExportPolygons(geom.GetPolys());
4617                        }
[710]4618                        else if (cf == 0)
[684]4619                        {
[682]4620                                geom.SplitGeometry(front,
4621                                                                   back,
4622                                                                   *clipPlane,
4623                                                                   mViewSpaceBox,
[710]4624                                                                   eps);
[682]4625       
[694]4626                                //Debug << "geo size: " << geom.Size() << endl;
4627                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
[801]4628
[683]4629                                if (back.Valid())
4630                                {
[682]4631                                        exporter->ExportPolygons(back.GetPolys());
[708]4632                                }                       
[684]4633                        }
[591]4634                }
4635        }
4636        else
4637        {
[801]4638                // export mesh if available
4639        /*      if (vc->GetMesh())
4640                {
4641                        exporter->ExportMesh(vc->GetMesh());
4642                }
4643                else
4644                {*/
4645                        BspNodeGeometry geom;
4646                        mVspBspTree->ConstructGeometry(vc, geom);
4647                        exporter->ExportPolygons(geom.GetPolys());
4648                //}
[591]4649        }
[482]4650}
4651
4652
4653int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
4654{
[580]4655        ViewCellContainer leaves;
4656        mViewCellsTree->CollectLeaves(vc, leaves);
[482]4657
4658        int maxDist = 0;
[580]4659       
[482]4660        // compute max height difference
[580]4661        for (int i = 0; i < (int)leaves.size(); ++ i)
4662                for (int j = 0; j < (int)leaves.size(); ++ j)
[482]4663        {
[580]4664                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
[482]4665
4666                if (i != j)
4667                {
[580]4668                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
[482]4669                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
4670                        if (dist > maxDist)
4671                                maxDist = dist;
4672                }
4673        }
[580]4674
[492]4675        return maxDist;
4676}
[482]4677
[492]4678
[879]4679ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
[492]4680{
[508]4681        if (!mVspBspTree)
4682                return NULL;
[572]4683
4684        if (!mViewSpaceBox.IsInside(point))
4685          return NULL;
4686
[879]4687        return mVspBspTree->GetViewCell(point, active);
[492]4688}
[503]4689
4690
4691void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
4692{
[726]4693        //if (vc->GetMesh()) delete vc->GetMesh();
[503]4694        BspNodeGeometry geom;
[590]4695
4696        mVspBspTree->ConstructGeometry(vc, geom);
[582]4697       
[503]4698        Mesh *mesh = new Mesh();
[840]4699        IncludeNodeGeomInMesh(geom, *mesh);
4700
[503]4701        vc->SetMesh(mesh);
[726]4702        // put mesh into mesh container so we can savely delete it
[503]4703        mMeshContainer.push_back(mesh);
4704}
[508]4705
4706
[938]4707ViewCellsManager *ViewCellsManager::LoadViewCells(const string &filename,
[931]4708                                                                                                  ObjectContainer *objects,
[938]4709                                                                                                  Environment *env,
[944]4710                                                                                                  const bool finalizeViewCells,
[931]4711                                                                                                  BoundingBoxConverter *bconverter)
[944]4712                                                                                                 
[508]4713{
4714        ViewCellsParser parser;
[564]4715
[577]4716        ViewCellsManager *vm = NULL;
[564]4717
[944]4718        if (parser.ParseFile(filename, &vm, objects, bconverter, env))
4719        {
4720                long startTime = GetTime();
[931]4721
[590]4722                //vm->PrepareLoadedViewCells();
[577]4723                vm->ResetViewCells();
[564]4724
[577]4725                vm->mViewCellsFinished = true;
4726                vm->mMaxPvsSize = (int)objects->size();
[517]4727
[719]4728                // create the meshes and compute volumes
[944]4729                if (finalizeViewCells)
4730                {
4731                        vm->FinalizeViewCells(true);
4732                        vm->mViewCellsTree->AssignRandomColors();
4733                }
[564]4734
[944]4735                Debug << (int)vm->mViewCells.size() << " view cells loaded in "
4736                          << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[577]4737        }
4738        else
4739        {
[870]4740                Debug << "Error: loading view cells failed!" << endl;
[577]4741                DEL_PTR(vm);
4742        }
4743
4744        return vm;
[508]4745}
4746
4747
[931]4748bool VspBspViewCellsManager::ExportViewCells(const string filename,
4749                                                                                         const bool exportPvs,
4750                                                                                         const ObjectContainer &objects)
[508]4751{
[564]4752        cout << "exporting view cells to xml ... ";
[955]4753       
4754        //ogzstream stream(filename.c_str());
4755        std::ofstream stream(filename.c_str());
[508]4756
[577]4757        // for output we need unique ids for each view cell
[590]4758        CreateUniqueViewCellIds();
[508]4759
4760        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
4761        stream << "<Visibility_Solution>" << endl;
[564]4762
[577]4763        //-- the view space bounding box
4764        stream << "<ViewSpaceBox"
4765                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
4766                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
4767
[955]4768       
4769        //-- export bounding boxes
4770        stream << "<BoundingBoxes>" << endl;
[840]4771
[955]4772        ObjectContainer::const_iterator oit, oit_end = objects.end();
[577]4773
[955]4774        for (oit = objects.begin(); oit != oit_end; ++ oit)
4775        {
4776                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*oit);
4777                        const AxisAlignedBox3 box = mi->GetBox();
4778
4779                        //-- the bounding boxes
4780                        stream << "<BoundingBox" << " id=\"" << mi->GetId() << "\""
4781                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
4782                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
4783        }
4784
4785        stream << "</BoundingBoxes>" << endl;
4786
4787
[840]4788        //-- export the view cells and the pvs
[944]4789        const int numViewCells = mCurrentViewCellsStats.viewCells;
4790
[955]4791        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
[840]4792       
[871]4793        mViewCellsTree->Export(stream, exportPvs);
[564]4794
[508]4795        stream << "</ViewCells>" << endl;
[564]4796
[840]4797
[931]4798        //-- export the spatial hierarchy
[955]4799       
4800        // the type of the view cells hierarchy
4801        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
[508]4802        mVspBspTree->Export(stream);
[590]4803        stream << endl << "</Hierarchy>" << endl;
[564]4804
[840]4805
4806
[508]4807        stream << "</Visibility_Solution>" << endl;
4808
[955]4809
4810        stream.close();
[508]4811        cout << "finished" << endl;
4812
4813        return true;
[532]4814}
4815
4816
4817int VspBspViewCellsManager::CastBeam(Beam &beam)
4818{
[535]4819        return mVspBspTree->CastBeam(beam);
[532]4820}
[551]4821
4822
[587]4823void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
4824                                                                          const bool createMesh)
[551]4825{
4826        float area = 0;
4827        float volume = 0;
4828
[580]4829        ViewCellContainer leaves;
[582]4830        mViewCellsTree->CollectLeaves(viewCell, leaves);
[580]4831
4832        ViewCellContainer::const_iterator it, it_end = leaves.end();
4833
[693]4834    for (it = leaves.begin(); it != it_end; ++ it)
[551]4835        {
4836                BspNodeGeometry geom;
[580]4837                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
[551]4838                mVspBspTree->ConstructGeometry(leaf, geom);
4839
[719]4840                const float lVol = geom.GetVolume();
4841                const float lArea = geom.GetArea();
[693]4842
4843                //(*it)->SetVolume(vol);
4844                //(*it)->SetArea(area);
4845
4846                area += lArea;
4847                volume += lVol;
4848
4849        CreateMesh(*it);
[551]4850        }
4851
4852        viewCell->SetVolume(volume);
4853        viewCell->SetArea(area);
[563]4854}
[575]4855
4856
[693]4857void VspBspViewCellsManager::TestSubdivision()
4858{
4859        ViewCellContainer leaves;
4860        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
4861
4862        ViewCellContainer::const_iterator it, it_end = leaves.end();
4863
4864        const float vol = mViewSpaceBox.GetVolume();
4865        float subdivVol = 0;
4866        float newVol = 0;
4867
4868        for (it = leaves.begin(); it != it_end; ++ it)
4869        {
4870                BspNodeGeometry geom;
4871                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4872                mVspBspTree->ConstructGeometry(leaf, geom);
4873
4874                const float lVol = geom.GetVolume();
4875               
4876                newVol += lVol;
4877                subdivVol += (*it)->GetVolume();
[697]4878               
[704]4879                float thres = 0.9f;
[697]4880                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
4881                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]4882        }
4883       
4884        Debug << "exact volume: " << vol << endl;
4885        Debug << "subdivision volume: " << subdivVol << endl;
4886        Debug << "new volume: " << newVol << endl;
4887}
4888
4889
[577]4890void VspBspViewCellsManager::PrepareLoadedViewCells()
4891{
4892        // TODO: do I still need this here?
[590]4893        if (0)
[693]4894                mVspBspTree->RepairViewCellsLeafLists();
[577]4895}
[575]4896
[859]4897void
[884]4898ViewCellsManager::ApplySpatialFilter(
4899                                                                         KdTree *kdTree,
4900                                                                         const float spatialFilterSize,
4901                                                                         ObjectPvs &pvs
4902                                                                         )
[859]4903{
4904
4905  // now compute a new Pvs by including also objects intersecting the extended boxes of
4906  // visible objects
4907
4908  Intersectable::NewMail();
4909 
4910  std::map<Intersectable *,
4911        PvsData<Intersectable *>,
4912        LtSample<Intersectable *> >::const_iterator oi;
4913 
4914  for (oi = pvs.mEntries.begin(); oi != pvs.mEntries.end(); ++oi) {
4915        Intersectable *object = (*oi).first;
4916        object->Mail();
4917  }
4918
4919  ObjectPvs nPvs;
[884]4920  int nPvsSize=0;
[859]4921  // now go through the pvs again
4922  for (oi = pvs.mEntries.begin(); oi != pvs.mEntries.end(); ++oi) {
4923        Intersectable *object = (*oi).first;
4924
4925        //      Vector3 center = object->GetBox().Center();
4926        //      AxisAlignedBox3 box(center - Vector3(spatialFilterSize/2),
4927        //                                              center + Vector3(spatialFilterSize/2));
4928
4929        AxisAlignedBox3 box = object->GetBox();
4930        box.Enlarge(Vector3(spatialFilterSize/2));
4931
4932        ObjectContainer objects;
4933
4934        // $$ warning collect objects takes only unmailed ones!
4935        kdTree->CollectObjects(box,
4936                                                   objects);
4937        //      cout<<"collected objects="<<objects.size()<<endl;
4938        ObjectContainer::const_iterator noi = objects.begin();
4939        for (; noi != objects.end(); ++noi) {
4940          Intersectable *o = *noi;
[884]4941          // $$ JB warning: pdfs are not correct at this point!
4942          nPvs.AddSample(o, Limits::Small);
4943          nPvsSize++;
[859]4944        }
4945  }
[884]4946  //  cout<<"nPvs size = "<<nPvsSize<<endl;
[859]4947  pvs.Merge(nPvs);
4948}
4949
[884]4950void
4951ViewCellsManager::ApplyFilter(ViewCell *viewCell,
4952                                                          KdTree *kdTree,
4953                                                          const float viewSpaceFilterSize,
4954                                                          const float spatialFilterSize,
4955                                                          ObjectPvs &pvs
4956                                                          )
4957{
4958  // extend the pvs of the viewcell by pvs of its neighbors
4959  // and apply spatial filter by including all neighbors of the objects
4960  // in the pvs
[859]4961
[884]4962  // get all viewcells intersecting the viewSpaceFilterBox
4963  // and compute the pvs union
4964 
4965  //Vector3 center = viewCell->GetBox().Center();
4966  //  Vector3 center = m->mBox.Center();
4967 
4968  //  AxisAlignedBox3 box(center - Vector3(viewSpaceFilterSize/2),
4969  //                                      center + Vector3(viewSpaceFilterSize/2));
[904]4970
4971  if (viewSpaceFilterSize >=0.0f) {
4972
4973  bool usePrVS = false;
4974
[884]4975 
[904]4976  if (!usePrVS) {
4977        AxisAlignedBox3 box = GetViewCellBox(viewCell);
4978        box.Enlarge(Vector3(viewSpaceFilterSize/2));
4979       
4980        ViewCellContainer viewCells;
4981        ComputeBoxIntersections(box, viewCells);
4982       
4983  //  cout<<"box="<<box<<endl;
4984        ViewCellContainer::const_iterator it=viewCells.begin(), it_end = viewCells.end();
4985       
4986        int i;
4987        for (i=0; it != it_end; ++it, i++) {
4988          //    cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
4989          pvs.Merge((*it)->GetPvs());
4990        }
4991  } else {
4992        PrVs prvs;
4993        AxisAlignedBox3 box = GetViewCellBox(viewCell);
[859]4994
[904]4995        //  mViewCellsManager->SetMaxFilterSize(1);
4996        GetPrVS(box.Center(), prvs, viewSpaceFilterSize);
4997        pvs = prvs.mViewCell->GetPvs();
4998        DeleteLocalMergeTree(prvs.mViewCell);
[884]4999  }
[904]5000  } else
5001        pvs = viewCell->GetPvs();
[884]5002 
[904]5003  if (spatialFilterSize >=0.0f)
5004        ApplySpatialFilter(kdTree, spatialFilterSize, pvs);
5005
[884]5006}
5007
5008
5009
[859]5010void
5011ViewCellsManager::ApplyFilter(KdTree *kdTree,
5012                                                          const float relViewSpaceFilterSize,
5013                                                          const float relSpatialFilterSize
5014                                                          )
5015{
5016
5017  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
5018
5019  ObjectPvs *newPvs;
5020  newPvs = new ObjectPvs[mViewCells.size()];
5021
5022  float viewSpaceFilterSize = Magnitude(mViewSpaceBox.Size())*relViewSpaceFilterSize;
5023  float spatialFilterSize = Magnitude(kdTree->GetBox().Size())*relSpatialFilterSize;
5024 
5025  int i;
5026  for (i=0, it = mViewCells.begin(); it != it_end; ++ it, i++) {
5027        ApplyFilter(*it,
5028                                kdTree,
5029                                viewSpaceFilterSize,
5030                                spatialFilterSize,
5031                                newPvs[i]
5032                                );
5033  }
5034
5035  // now replace all pvss
5036  for (i= 0, it = mViewCells.begin(); it != it_end; ++ it, i++) {
5037        ObjectPvs &pvs = (*it)->GetPvs();
5038        pvs.Clear();
5039        pvs = newPvs[i];
[904]5040        newPvs[i].Clear();
[859]5041  }
5042 
[904]5043  delete newPvs;
[859]5044}
5045
[697]5046void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
5047{
5048        Exporter *exporter = Exporter::GetExporter("filter.x3d");
[580]5049
[704]5050        Vector3 bsize = mViewSpaceBox.Size();
5051        const Vector3 viewPoint(mViewSpaceBox.Center());
[880]5052        float w = Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
[746]5053        const Vector3 width = Vector3(w);
[704]5054       
5055        PrVs testPrVs;
5056       
[697]5057        if (exporter)
5058        {
5059                ViewCellContainer viewCells;
[704]5060       
5061        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
5062
[904]5063                GetPrVS(viewPoint, testPrVs, GetFilterWidth());
[704]5064
[697]5065                exporter->SetWireframe();
5066
5067                exporter->SetForcedMaterial(RgbColor(1,1,1));
[704]5068                exporter->ExportBox(tbox);
[697]5069               
5070                exporter->SetFilled();
5071
[705]5072                exporter->SetForcedMaterial(RgbColor(0,1,0));
[880]5073                ExportViewCellGeometry(exporter, GetViewCell(viewPoint));
[705]5074
5075                //exporter->ResetForcedMaterial();
5076                exporter->SetForcedMaterial(RgbColor(0,0,1));
[704]5077                ExportViewCellGeometry(exporter, testPrVs.mViewCell);
5078
5079        exporter->SetForcedMaterial(RgbColor(1,0,0));
[697]5080                exporter->ExportGeometry(objects);
5081
5082                delete exporter;
5083        }
5084}
5085
5086
[580]5087void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
5088                                                                                                        vector<MergeCandidate> &candidates)
5089{       
5090        cout << "collecting merge candidates ... " << endl;
5091
5092        if (mUseRaysForMerge)
5093        {
5094                mVspBspTree->CollectMergeCandidates(rays, candidates);
5095        }
5096        else
5097        {
5098                vector<BspLeaf *> leaves;
5099                mVspBspTree->CollectLeaves(leaves);
[708]5100       
[580]5101                mVspBspTree->CollectMergeCandidates(leaves, candidates);
5102        }
5103
5104        cout << "fininshed collecting candidates" << endl;
5105}
5106
5107
5108//////////////////////////////////
[575]5109ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
5110{
5111        //TODO
5112        return NULL;// new VspBspViewCellsManager();
5113}
[580]5114
[860]5115
[878]5116}
Note: See TracBrowser for help on using the repository browser.