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

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

updated view cells loading. probably no optimal for performance

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