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

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