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

Revision 1486, 140.0 KB checked in by mattausch, 18 years ago (diff)

worked on guided visibility sampling

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