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

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