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

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