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

Revision 1520, 140.1 KB checked in by mattausch, 18 years ago (diff)

moved raycasting out of preprocessor into specific ray casting interface

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