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

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