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

Revision 1952, 165.0 KB checked in by bittner, 18 years ago (diff)

mutation strategy

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