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

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