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

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