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

Revision 1077, 137.7 KB checked in by mattausch, 18 years ago (diff)

worked on object space /view space partitioning

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