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

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