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

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