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

Revision 727, 101.4 KB checked in by mattausch, 19 years ago (diff)

added view cell description bsp tree

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"
10#include "VspKdTree.h"
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"
[440]17
[712]18// HACK
19const static bool SAMPLE_AFTER_SUBDIVISION = true;
20const static bool TEST_EMPTY_VIEW_CELLS = false;
[517]21
[697]22
23
24template <typename T> class myless
25{
26public:
27        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
28        bool operator() (T v1, T v2) const
29        {
30                return (v1->GetMergeCost() < v2->GetMergeCost());
31        }
32};
33
[706]34//typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > FilterQueue;
[697]35
36
37
[440]38ViewCellsManager::ViewCellsManager():
[480]39mRenderer(NULL),
[574]40mInitialSamples(0),
[440]41mConstructionSamples(0),
42mPostProcessSamples(0),
[470]43mVisualizationSamples(0),
44mTotalAreaValid(false),
[517]45mTotalArea(0.0f),
[547]46mViewCellsFinished(false),
[562]47mMaxPvsSize(9999999),
[564]48mMinPvsSize(0), // one means only empty view cells are invalid
[719]49mMaxPvsRatio(1.0),
50mViewCellPvsIsUpdated(false)
[440]51{
[542]52        mViewSpaceBox.Initialize();
[482]53        ParseEnvironment();
[580]54
55        mViewCellsTree = new ViewCellsTree(this);
[440]56}
57
[517]58
[482]59void ViewCellsManager::ParseEnvironment()
60{
[503]61        // visualization stuff
[485]62        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
63        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
[547]64        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[664]65       
[710]66        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", mPruneEmptyViewCells);
[664]67
[710]68        // HACK
69        if (0)
70                mMinPvsSize = mPruneEmptyViewCells ? 1 : 0;
71        else
72                mMinPvsSize = 0;
73
[564]74        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]75
[574]76        environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
77        environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
[595]78        environment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
79
[574]80        environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
81
82        environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
[577]83        environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
[581]84       
[600]85        environment->GetIntValue("ViewCells.active", mNumActiveViewCells);
[586]86        environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
[660]87        environment->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
[591]88        environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
[664]89        environment->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
[666]90        environment->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
[697]91        environment->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
92        environment->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
[710]93
[664]94        char buf[100];
95        environment->GetStringValue("ViewCells.samplingType", buf);
96
[660]97       
[664]98        if (strcmp(buf, "box") == 0)
[722]99        {
[660]100                mSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[722]101        }
[664]102        else if (strcmp(buf, "directional") == 0)
[722]103        {
[660]104                mSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
[722]105        }
[666]106        else
107        {
108                Debug << "error! wrong sampling type" << endl;
109                exit(0);
110        }
[660]111
[722]112        environment->GetStringValue("ViewCells.Evaluation.samplingType", buf);
113       
114        if (strcmp(buf, "box") == 0)
115        {
116                mEvaluationSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
117        }
118        else if (strcmp(buf, "directional") == 0)
119        {
120                mEvaluationSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
121        }
122        else
123        {
124                Debug << "error! wrong sampling type" << endl;
125                exit(0);
126        }
[503]127
[722]128    environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
129
[482]130        if (strcmp(buf, "PVS") == 0)
131                mColorCode = 1;
132        else if (strcmp(buf, "MergedLeaves") == 0)
133                mColorCode = 2;
134        else if (strcmp(buf, "MergedTreeDiff") == 0)
135                mColorCode = 3;
136        else
137                mColorCode = 0;
138
[664]139
[710]140
[664]141        Debug << "***********View Cells options ****************" << endl;
142        Debug << "color code: " << mColorCode << endl;
143
144        Debug << "export rays: " << mExportRays << endl;
145        Debug << "export geometry: " << mExportGeometry << endl;
146        Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
147       
[710]148        Debug << "prune empty view cells: " << mPruneEmptyViewCells << endl;
[664]149       
150        Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
151        Debug << "construction samples: " << mConstructionSamples << endl;
152        Debug << "post process samples: " << mPostProcessSamples << endl;
153        Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
154        Debug << "visualization samples: " << mVisualizationSamples << endl;
155        Debug << "construction samples per pass: " << mSamplesPerPass << endl;
156        Debug << "export to file: " << mExportViewCells << endl;
157       
158        Debug << "active: " << mNumActiveViewCells << endl;
159        Debug << "post process compress: " << mCompressViewCells << endl;
160        Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
161        Debug << "post process merge: " << mMergeViewCells << endl;
162        Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
163        Debug << "sampling type: " << mSamplingType << endl;
[666]164        Debug << "show visualization: " << mShowVisualization << endl;
[697]165        Debug << "filter width: " << mFilterWidth << endl;
[710]166        Debug << "sample after subdivision: " << SAMPLE_AFTER_SUBDIVISION << endl;
[664]167        Debug << endl;
[440]168}
169
[485]170
[440]171ViewCellsManager::~ViewCellsManager()
172{
[480]173        DEL_PTR(mRenderer);
[580]174
[598]175        if (!ViewCellsTreeConstructed())
176                CLEAR_CONTAINER(mViewCells);
177        else
178                DEL_PTR(mViewCellsTree);
179
[503]180        CLEAR_CONTAINER(mMeshContainer);
[440]181}
182
[485]183
[693]184void ViewCellsManager::CollectEmptyViewCells()
185{
186        mEmptyViewCells.clear();
187        ViewCellContainer leaves;
188        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
189
190        ViewCellContainer::const_iterator it, it_end = leaves.end();
191
192        cout << "collecting empty view cells" << endl;
[694]193       
[693]194        for (it = leaves.begin(); it != it_end; ++ it)
195        {
196                if ((*it)->GetPvs().Empty())
197                {
198                        mEmptyViewCells.push_back(*it);
199                }
200        }
[694]201        Debug << "empty view cells found: " << (int)mEmptyViewCells.size() << endl;
[693]202}
203
204
[694]205void ViewCellsManager::TestEmptyViewCells(const ObjectContainer &obj)
[693]206{
207        ViewCellContainer::const_iterator it, it_end = mEmptyViewCells.end();
208
209        char buf[50];
210        int i = 0;
211        for (it = mEmptyViewCells.begin(); it != it_end; ++ it)
212        {
213                if (!(*it)->GetPvs().Empty())
214                {
[694]215                        sprintf(buf, "empty-viewcells-%09d.x3d", i/*(*it)->GetId()*/);
[693]216                        Exporter *exporter = Exporter::GetExporter(buf);
217                       
218                        if (exporter && i < 20)
219                        {
[694]220                                Ray *pray = (*it)->mPiercingRays[0];
[697]221                                Debug << "view cell " << (*it)->GetId() << " not empty, pvs: " << (*it)->GetPvs().GetSize() << " " << (int)pray->intersections.size() << endl;
[694]222
223                                exporter->ExportRays((*it)->mPiercingRays);
224                                                       
225                                exporter->SetFilled();
226                                exporter->SetForcedMaterial(RgbColor(0,0,1));
227
228                                for (int j = 0; j < (int)pray->intersections.size(); ++ j)
229                                {
230                                        if (pray->intersections[j].mObject)
231                                                exporter->ExportIntersectable(pray->intersections[j].mObject);
232                                }
233
234                                //exporter->SetWireframe();
235                                exporter->SetForcedMaterial(RgbColor(0,1,0));
236                                exporter->ExportGeometry(obj);
237
238                                exporter->SetFilled();
239
240                                exporter->SetForcedMaterial(RgbColor(1,0,0));
[693]241                                ExportViewCellGeometry(exporter, *it);
[694]242
243                                delete exporter;               
[693]244                        }
245
[694]246               
[693]247                        ++ i;
248                }
249        }
[694]250        Debug << "\nSampled " << i << " new view cells (" << " of " << (int)mEmptyViewCells.size() << ")" << endl << endl;
[693]251}
252
253
[574]254int ViewCellsManager::CastPassSamples(const int samplesPerPass,
255                                                                          const int sampleType,
256                                                                          VssRayContainer &passSamples) const
[527]257{
[570]258        SimpleRayContainer simpleRays;
[540]259
[573]260        preprocessor->GenerateRays(samplesPerPass,
261                                                           sampleType,
[570]262                                                           simpleRays);
[564]263
[573]264        // shoot simple ray and add it to importance samples
265        preprocessor->CastRays(simpleRays, passSamples);
[570]266
[574]267        return (int)passSamples.size();
268}
[570]269
[574]270
[607]271
[574]272/// helper function which destroys rays or copies them into the output ray container
[639]273inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
[574]274{
275        cout << "disposing samples ... ";
[582]276        long startTime = GetTime();
277        int n = (int)rays.size();
278
[573]279        if (outRays)
[542]280        {
[574]281                VssRayContainer::const_iterator it, it_end = rays.end();
282
283                for (it = rays.begin(); it != it_end; ++ it)
284                {
285                        outRays->push_back(*it);
286                }
[573]287        }
288        else
289        {
[639]290                VssRayContainer::const_iterator it, it_end = rays.end();
291
292                for (it = rays.begin(); it != it_end; ++ it)
293                {
294                        //(*it)->Unref();
295                        if (!(*it)->IsActive())
296                                delete (*it);
297                }
[573]298        }
[639]299
[574]300        cout << "finished" << endl;
[582]301        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[573]302}
[570]303
304
[573]305int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
306{
307        int numSamples = 0;
308        SimpleRayContainer simpleRays;
309       
[574]310        VssRayContainer initialSamples;
[540]311
[574]312        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
[712]313
[573]314        //-- construction rays => we use uniform samples for this
[574]315        CastPassSamples(mInitialSamples,
[660]316                                        mSamplingType,
[574]317                                        initialSamples);
[573]318       
[574]319        cout << "finished" << endl;
320
[660]321       
[573]322        // construct view cells
[574]323        const int numInitialSamples =
324                ConstructSubdivision(preprocessor->mObjects, initialSamples);
[540]325
[727]326        // initial samples count for overall samples ...
[574]327        numSamples += numInitialSamples;
[542]328
[574]329        // rays can be passed or deleted
[639]330        disposeRays(initialSamples, outRays);
[574]331       
[720]332        // testing the view cell filter functionality   
333        if (0) TestFilter(preprocessor->mObjects);
[570]334
[660]335        // -- stats after contruction
336        ResetViewCells();
337
[667]338        Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
339
[683]340        if (1) // export initial view cells
[660]341        {
[712]342                const char filename[] = "view_cells.wrl";
343                Exporter *exporter = Exporter::GetExporter(filename);
[660]344
[712]345       
[660]346                if (exporter)
347                {
[712]348                        cout << "exporting initial view cells (=leaves) to " << filename << " ... ";
[660]349                        if (mExportGeometry)
[712]350                        {
[660]351                                exporter->ExportGeometry(preprocessor->mObjects);
[712]352                        }
[660]353
[712]354                        //exporter->SetWireframe();
[660]355                        ExportViewCellsForViz(exporter);
356
357                        delete exporter;
[712]358                        cout << "finished" << endl;
[660]359                }
360        }
361
[573]362        //-- guided rays are used for further sampling
[574]363        const int n = mConstructionSamples; //+initialSamples;
[570]364
[666]365        // should we use directional samples?
[694]366        bool dirSamples = (mSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
[573]367
[712]368        // -- the main loop
[573]369        while (numSamples < n)
370        {
[596]371                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
[727]372                Debug << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
373
[574]374                VssRayContainer constructionSamples;
375
[694]376                const int samplingType = mSamplingType;
377                        /*dirSamples ?
[574]378                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
[694]379                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;*/
[667]380
[720]381                if (0) dirSamples = !dirSamples; // toggle sampling method
[667]382
[727]383                // cast new samples
[574]384                numSamples += CastPassSamples(mSamplesPerPass,
[666]385                                                                          samplingType,
[574]386                                                                          constructionSamples);
387
388                cout << "finished" << endl;
389
390                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
391
[727]392                // computes sample contribution of cast rays TODO: leak?
393                if (SAMPLE_AFTER_SUBDIVISION)
[605]394                        ComputeSampleContributions(constructionSamples, true, false);
[712]395
[574]396                cout << "finished" << endl;
397
398
[639]399                disposeRays(constructionSamples, outRays);
[574]400
401                cout << "total samples: " << numSamples << endl;
[542]402        }
[573]403       
[570]404
[573]405        //-- post processing
406        VssRayContainer postProcessSamples;
[570]407
[694]408        //-- construction rays
[574]409        CastPassSamples(mPostProcessSamples,
[694]410                                        mSamplingType,
[574]411                                        postProcessSamples);
[660]412
413
414        // stats before post processing (i.e., merge)
415        EvaluateViewCellsStats();
416        Debug << "\noriginal view cell partition before post process:\n" << mCurrentViewCellsStats << endl;
417
418        mRenderer->RenderScene();
419        SimulationStatistics ss;
420        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
421
422    Debug << ss << endl;
423
424
425
[574]426        cout << "starting post processing and visualization" << endl;
427
[660]428
[666]429        // store view cells for postprocessing
[574]430        const bool storeViewCells = true;
[605]431
[660]432
[605]433        if (SAMPLE_AFTER_SUBDIVISION)
434                ComputeSampleContributions(postProcessSamples, true, storeViewCells);
[663]435
[720]436        //-- post processing (e.g.,merging) of the view cells
[573]437        PostProcess(preprocessor->mObjects, postProcessSamples);
[570]438
[720]439        // only for debugging purpose
[694]440        if (TEST_EMPTY_VIEW_CELLS)
441                CollectEmptyViewCells();
[570]442
[693]443
[574]444        //-- visualization
[666]445        if (mShowVisualization)
446        {
447                VssRayContainer visualizationSamples;
[574]448
[666]449                //-- construction rays => we use uniform samples for this
450                CastPassSamples(mVisualizationSamples,
451                                            Preprocessor::DIRECTION_BASED_DISTRIBUTION,
452                                                visualizationSamples);
[574]453
[666]454                if (SAMPLE_AFTER_SUBDIVISION)
455                        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
[574]456
[666]457                // different visualizations
458                Visualize(preprocessor->mObjects, visualizationSamples);
[574]459
[666]460                disposeRays(visualizationSamples, outRays);
461        }
[574]462
[707]463        // needed to fix empty view cells
[710]464    //SetValidity(0, 99999999999);
[707]465
[720]466
467        // evaluation of the paritition, i.e., a number of new samples are cast
[664]468        if (mEvaluateViewCells)
469        {
[666]470                EvalViewCellPartition(preprocessor);
[664]471        }
[666]472       
[667]473        if (0)
474        {
475                ViewCellContainer leaves;
476                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
477                mViewCellsTree->ResetPvs();
478                VssRayContainer dummyRays;
479                CastPassSamples(mInitialSamples, mSamplingType, dummyRays);
[666]480       
[667]481                //ComputeSampleContributions(initialSamples, true, false);
482                ComputeSampleContributions(dummyRays, true, false);
[664]483
[667]484                ViewCellContainer::const_iterator it, it_end = leaves.end();
[666]485
[667]486                for (it = leaves.begin(); it != it_end; ++ it)
487                {
488                        mViewCellsTree->PropagatePvs(*it);
489                }
490
491                mViewCellsTree->ExportStats("dummy.log");
[666]492        }
493
[573]494        return numSamples;
[527]495}
496
[547]497
[664]498void ViewCellsManager::EvalViewCellPartition(Preprocessor *preprocessor)
[660]499{
500        int samplesPerPass;
501        int numSamples;
502        int castSamples = 0;
503
[664]504        char s[64];
505
[660]506        environment->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
507        environment->GetIntValue("ViewCells.Evaluation.samples", numSamples);
508
[664]509        char statsPrefix[100];
510        environment->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
[663]511
[664]512        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
513        Debug << "view cell evaluation samples: " << numSamples << endl;
514        Debug << "view cell stats prefix: " << statsPrefix << endl;
515
516        //VssRayContainer outRays;
[666]517        // should directional sampling be used?
[722]518        bool dirSamples = (mEvaluationSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
[664]519
520        cout << "Evaluating view cell partition" << endl;
521
522        ViewCellContainer leaves;
523        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
524
[666]525        bool startFromZero = true;
526
527        // reset pvs and start over from zero
528        if (startFromZero)
529        {
530                mViewCellsTree->ResetPvs();
531        }
532        else // statistics without addidtional samples
533        {
534                cout << "compute new statistics ... ";
535                sprintf(s, "-%09d-eval.log", castSamples);
536                string fName = string(statsPrefix) + string(s);
537
538                mViewCellsTree->ExportStats(fName);
539                cout << "finished" << endl;
540        }
541       
542
[660]543        while (castSamples < numSamples)
544        {
[664]545                VssRayContainer evaluationSamples;
[663]546
[722]547                const int samplingType = mEvaluationSamplingType;
[666]548                /*      dirSamples ?
[664]549                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
550                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[666]551                */
[664]552                //-- construction rays => we use uniform samples for this
553                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
554               
555                castSamples += samplesPerPass;
556
557                cout << "casting " << (int)evaluationSamples.size() << " samples " << endl;
558
559                ComputeSampleContributions(evaluationSamples, true, false);
560
561                cout << "compute new statistics ... ";
562
563                ViewCellContainer::const_iterator it, it_end = leaves.end();
564
565                for (it = leaves.begin(); it != it_end; ++ it)
566                {
567                        mViewCellsTree->PropagatePvs(*it);
568                }
569
570                // output stats
[667]571                sprintf(s, "-%09d-eval.log", castSamples);
[664]572                string fileName = string(statsPrefix) + string(s);
573
574                mViewCellsTree->ExportStats(fileName);
575
576                cout << "finished" << endl;
577       
578                disposeRays(evaluationSamples, NULL);
[660]579        }
[693]580
581        // find empty view cells bug
[694]582        if (TEST_EMPTY_VIEW_CELLS)
[719]583        {
[694]584                TestEmptyViewCells(preprocessor->mObjects);
[719]585        }
[660]586}
587
[704]588
589inline float EvalMergeCost(ViewCell *root, ViewCell *candidate)
[703]590{
[704]591        return root->GetPvs().GetPvsHomogenity(candidate->GetPvs());
592}
[660]593
[703]594
[704]595int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
596{
[705]597        int bestViewCellIdx = 0;
[703]598
[704]599        float mergeCost = Limits::Infinity;
600        int i = 0;
[703]601
[704]602        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
[703]603
[704]604        for (it = neighborhood.begin(); it != it_end; ++ it, ++ i)
[703]605        {
[704]606                const float mc = EvalMergeCost(root, *it);
[705]607               
608                if (mc < mergeCost)
[704]609                {
610                        mergeCost = mc;
611                        bestViewCellIdx = i;
[703]612                }
[704]613        }
[703]614
[704]615        return bestViewCellIdx;
616}
[703]617
618
[704]619ViewCell *ViewCellsManager::ConstructLocalMergeTree(ViewCell *currentViewCell,
620                                                                                                        const ViewCellContainer &viewCells)
621{
622        ViewCell *root = currentViewCell;
623        ViewCellContainer neighborhood = viewCells;
[703]624
[704]625        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
[703]626
[704]627        const int n = min(mMaxFilterSize, (int)neighborhood.size());
628        //-- use priority queue to merge leaf pairs
[703]629
[705]630        //cout << "neighborhood: " << neighborhood.size() << endl;
[704]631        //const float maxAvgCost = 350;
632        for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
[703]633        {
[704]634                const int bestViewCellIdx = GetBestViewCellIdx(root, neighborhood);
[703]635               
[704]636                ViewCell *bestViewCell = neighborhood[bestViewCellIdx];
[706]637       
[704]638                // remove from vector
639                swap(neighborhood[bestViewCellIdx], neighborhood.back());
640                neighborhood.pop_back();
[705]641       
[713]642                //              cout << "vc idx: " << bestViewCellIdx << endl;
[704]643                if (!bestViewCell || !root)
644                        cout << "warning!!" << endl;
[705]645               
[704]646                // create new root of the hierarchy
647                root = MergeViewCells(root, bestViewCell);
[703]648        }
649
[704]650        return root;   
[703]651}
652
[704]653
[713]654struct SortableViewCellEntry {
655
656  SortableViewCellEntry() {}
657  SortableViewCellEntry(const float v, ViewCell *cell):mValue(v), mViewCell(cell) {}
658 
659  float mValue;
660  ViewCell *mViewCell;
661
662  friend bool operator<(const SortableViewCellEntry &a, const SortableViewCellEntry &b) {
663        return a.mValue < b.mValue;
664  }
665};
666
667ViewCell *
668ViewCellsManager::ConstructLocalMergeTree2(ViewCell *currentViewCell,
669                                                                                   const ViewCellContainer &viewCells)
670{
671 
672  vector<SortableViewCellEntry> neighborhood(viewCells.size());
673  int i, j;
674  for (i = 0, j = 0; i < viewCells.size(); i++) {
675        if (viewCells[i] != currentViewCell)
676          neighborhood[j++] = SortableViewCellEntry(
677                                                                                                EvalMergeCost(currentViewCell, viewCells[i]),
678                                                                                                viewCells[i]);
679  }
680  neighborhood.resize(j);
681 
682  sort(neighborhood.begin(), neighborhood.end());
683 
684  ViewCell *root = currentViewCell;
685 
686  vector<SortableViewCellEntry>::const_iterator it, it_end = neighborhood.end();
687 
688  const int n = min(mMaxFilterSize, (int)neighborhood.size());
689  //-- use priority queue to merge leaf pairs
690 
691  //cout << "neighborhood: " << neighborhood.size() << endl;
692  for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
693        {
694          ViewCell *bestViewCell = neighborhood[nMergedViewCells].mViewCell;
695          //cout <<nMergedViewCells<<":"<<"homogenity=" <<neighborhood[nMergedViewCells].mValue<<endl;
696          // create new root of the hierarchy
697          root = MergeViewCells(root, bestViewCell);
698          // set negative cost so that this view cell gets deleted
699          root->SetMergeCost(-1.0f);
700        }
701 
702  return root; 
703}
704
705void
706ViewCellsManager::DeleteLocalMergeTree(ViewCell *vc
707                                                                           ) const
708{
709  if (!vc->IsLeaf() && vc->GetMergeCost() < 0.0f) {
710        ViewCellInterior *vci = (ViewCellInterior *) vc;
711        ViewCellContainer::const_iterator it, it_end = vci->mChildren.end();
712       
713        for (it = vci->mChildren.begin(); it != it_end; ++ it)
714          DeleteLocalMergeTree(*it);
715        vci->mChildren.clear();
716        delete vci;
717  }
718}
719
[564]720bool ViewCellsManager::CheckValidity(ViewCell *vc,
721                                                                         int minPvsSize,
[562]722                                                                         int maxPvsSize) const
[547]723{
[569]724
[710]725        if ((vc->GetPvs().GetSize() > maxPvsSize) ||
726                (vc->GetPvs().GetSize() < minPvsSize))
[564]727        {
[710]728                return false;
[561]729        }
[570]730
[710]731        return true;
[547]732}
733
734
[710]735bool ViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
736{
737        return false;
738}
739
740int ViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
741                                                                                          ViewCellContainer &viewCells) const
742{
743        return 0;
744};
745
[697]746AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
747                                                                                                const float width) const
748{
749        Vector3 min = viewPoint - width * 0.5f;
750        Vector3 max = viewPoint + width * 0.5;
751
752        return AxisAlignedBox3(min, max);
753}
754
755
756void ViewCellsManager::GetPrVS(const Vector3 &viewPoint, PrVs &prvs)
757{
758        const AxisAlignedBox3 box = GetFilterBBox(viewPoint, mFilterWidth);
759
[704]760        ViewCell *currentViewCell = GetViewCell(viewPoint);
761
[697]762        ViewCellContainer viewCells;
763        ComputeBoxIntersections(box, viewCells);
764
[713]765        ViewCell *root = ConstructLocalMergeTree2(currentViewCell, viewCells);
[704]766
767        prvs.mViewCell = root;
768        //prvs.mPvs = root->GetPvs();
[697]769}
770
771
[581]772bool ViewCellsManager::ViewCellsTreeConstructed() const
773{
774        return mViewCellsTree->GetRoot();
775}
776
777
[564]778void ViewCellsManager::SetValidity(ViewCell *vc,
779                                                                   int minPvs,
[562]780                                                                   int maxPvs) const
781{
782        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
783}
784
[577]785
[569]786void
787ViewCellsManager::SetValidity(
[570]788                                                          int minPvsSize,
[569]789                                                          int maxPvsSize) const
790{
791  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[570]792
[569]793  for (it = mViewCells.begin(); it != it_end; ++ it) {
794        SetValidity(*it, minPvsSize, maxPvsSize);
795  }
796}
[562]797
[569]798void
799ViewCellsManager::SetValidityPercentage(
800                                                                                const float minValid,
801                                                                                const float maxValid
802                                                                                )
803{
804  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[570]805
[569]806  int start = mViewCells.size()*minValid;
807  int end = mViewCells.size()*maxValid;
[570]808
[569]809  for (int i=0; i < mViewCells.size(); i++)
810        mViewCells[i]->SetValid(i >= start && i <= end);
811}
812
813int
814ViewCellsManager::CountValidViewcells() const
815{
816  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
817  int valid = 0;
818  for (it = mViewCells.begin(); it != it_end; ++ it) {
819        if ((*it)->GetValid())
[706]820          valid ++;
[569]821  }
822  return valid;
823}
824
[577]825
826bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
[440]827{
828        X3dParser parser;
[503]829
[440]830        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]831
[440]832        bool success = parser.ParseFile(filename, *this);
833        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
834
835        return success;
836}
837
[485]838
[487]839bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
840{
[542]841        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]842
843        return true;
844}
845
846
[557]847float ViewCellsManager::GetViewSpaceVolume()
848{
[610]849        return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
[557]850}
851
852
[490]853bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
854{
[569]855  if (!ViewCellsConstructed())
[542]856        return mViewSpaceBox.IsInside(viewPoint);
[569]857  else {
858        if (!mViewSpaceBox.IsInside(viewPoint))
859          return false;
860        ViewCell *viewcell = GetViewCell(viewPoint);
861        if (!viewcell || !viewcell->GetValid())
862          return false;
863  }
864  return true;
[490]865}
866
[501]867
[563]868float
869ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
[574]870                                                                                         const bool addRays,
871                                                                                         const bool storeViewCells
[563]872                                                                                         )
[440]873{
[563]874  // view cells not yet constructed
875  if (!ViewCellsConstructed())
876        return 0.0f;
[564]877
[563]878  VssRayContainer::const_iterator it, it_end = rays.end();
[503]879
[563]880  float sum = 0.0f;
[664]881  for (it = rays.begin(); it != it_end; ++ it)
882  {
883          sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
884          //ComputeSampleContributions(*(*it), addRays);
885          //    sum += (*it)->mPvsContribution;
[563]886  }
[664]887
[563]888  return sum;
[440]889}
890
[485]891
[479]892void ViewCellsManager::EvaluateViewCellsStats()
893{
[660]894        mCurrentViewCellsStats.Reset();
[479]895
896        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
897
898        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]899        {
[660]900                mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
[487]901        }
[479]902}
903
[485]904
[580]905void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
[579]906                                                                                                float &expectedRenderCost,
[580]907                                                                                                float &deviation,
908                                                                                                float &variance,
909                                                                                                int &totalPvs,
910                                                                                                float &avgRenderCost)
[579]911{
912        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
913
[580]914
[579]915        //-- compute expected value
916
917        totalRenderCost = 0;
[580]918        totalPvs = 0;
[579]919
920        for (it = mViewCells.begin(); it != it_end; ++ it)
921        {
922                ViewCell *vc = *it;
923                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
[580]924                totalPvs += (int)vc->GetPvs().GetSize();
[579]925        }
926
[580]927        // normalize with view space box
928        totalRenderCost /= mViewSpaceBox.GetVolume();
[579]929        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
[580]930        avgRenderCost = totalPvs / (float)mViewCells.size();
[579]931
932
[580]933        //-- compute standard defiation
[579]934        variance = 0;
[580]935        deviation = 0;
[579]936
937        for (it = mViewCells.begin(); it != it_end; ++ it)
938        {
939                ViewCell *vc = *it;
940
941                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
[580]942                float dev;
[579]943
[580]944                if (1)
945                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
946                else
947                        dev = fabs(expectedRenderCost - renderCost);
[579]948
[580]949                deviation += dev;
950                variance += dev * dev;
[579]951        }
[580]952
[579]953        variance /= (float)mViewCells.size();
[580]954        deviation /= (float)mViewCells.size();
[579]955}
956
957
958
[440]959void ViewCellsManager::AddViewCell(ViewCell *viewCell)
960{
961        mViewCells.push_back(viewCell);
962}
963
[485]964
[478]965float ViewCellsManager::GetArea(ViewCell *viewCell) const
966{
967        return viewCell->GetArea();
968}
969
970
971float ViewCellsManager::GetVolume(ViewCell *viewCell) const
972{
973        return viewCell->GetVolume();
974}
975
[485]976
[503]977void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
978                                                                           ViewCellContainer &viewCells,
[440]979                                                                           const int maxViewCells) const
980{
981        // maximal max viewcells
[503]982        int limit = maxViewCells > 0 ?
[440]983                Min((int)objects.size(), maxViewCells) : (int)objects.size();
984
985        for (int i = 0; i < limit; ++ i)
986        {
987                Intersectable *object = objects[i];
[503]988
[440]989                // extract the mesh instances
990                if (object->Type() == Intersectable::MESH_INSTANCE)
991                {
992                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
993
994                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
995                        viewCells.push_back(viewCell);
996                }
997                //TODO: transformed meshes
998        }
999}
1000
[485]1001
[503]1002ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]1003                                                                                        const float height) const
1004{
1005        // one mesh per view cell
1006        Mesh *mesh = new Mesh();
[503]1007
[440]1008        //-- construct prism
1009
[503]1010        // bottom
[440]1011        mesh->mFaces.push_back(new Face(2,1,0));
1012        // top
1013    mesh->mFaces.push_back(new Face(3,4,5));
1014        // sides
1015        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
1016        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
1017        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
1018
1019        //--- extrude new vertices for top of prism
1020        Vector3 triNorm = baseTri.GetNormal();
1021
[503]1022        Triangle3 topTri;
[440]1023
1024        // add base vertices and calculate top vertices
1025        for (int i = 0; i < 3; ++ i)
1026                mesh->mVertices.push_back(baseTri.mVertices[i]);
[503]1027
1028        // add top vertices
[440]1029        for (int i = 0; i < 3; ++ i)
1030                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]1031
[440]1032        mesh->Preprocess();
1033
1034        return GenerateViewCell(mesh);
1035}
1036
[485]1037
[551]1038void ViewCellsManager::FinalizeViewCells(const bool createMesh)
1039{
1040        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[693]1041
1042        // volume and area of the view cells are recomputed and a view cell mesh is created
[551]1043        for (it = mViewCells.begin(); it != it_end; ++ it)
1044        {
1045                Finalize(*it, createMesh);
1046        }
[555]1047
1048        mTotalAreaValid = false;
[551]1049}
1050
1051
1052void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
1053{
1054        // implemented in subclasses
1055}
1056
1057
[582]1058ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
[440]1059{
[580]1060        // generate parent view cell
1061        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
[710]1062
[610]1063        vc->GetPvs() = left->GetPvs();
[440]1064        // merge pvs
[610]1065        vc->GetPvs().Merge(right->GetPvs());
[440]1066
[462]1067        //-- merge ray sets
[564]1068        if (0)
1069        {
[582]1070                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
1071                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
[440]1072
[582]1073                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
1074                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
[564]1075                                   vc->mPiercingRays.begin());
1076        }
[440]1077
[710]1078        // set only links to child (not from child to parent, maybe not wished!!)
1079        vc->mChildren.push_back(left);
1080        vc->mChildren.push_back(right);
1081
[440]1082        return vc;
1083}
1084
[485]1085
[582]1086ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
1087{
1088        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
1089
1090        ViewCellContainer::const_iterator it, it_end = children.end();
1091
1092        for (it = children.begin(); it != it_end; ++ it)
1093        {
1094                // merge pvs
[610]1095                vc->GetPvs().Merge((*it)->GetPvs());
[710]1096                vc->mChildren.push_back(*it);
1097                //vc->SetupChildLink(*it);
[582]1098        }
1099
1100        return vc;
1101}
1102
1103
[480]1104void ViewCellsManager::SetRenderer(Renderer *renderer)
1105{
1106        mRenderer = renderer;
1107}
[441]1108
[485]1109
[580]1110ViewCellsTree *ViewCellsManager::GetViewCellsTree()
[440]1111{
[580]1112        return mViewCellsTree;
[440]1113}
1114
1115
1116void ViewCellsManager::SetVisualizationSamples(const int visSamples)
1117{
[444]1118        mVisualizationSamples = visSamples;
[440]1119}
1120
[485]1121
[440]1122void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
1123{
1124        mConstructionSamples = constructionSamples;
1125}
1126
[485]1127
[574]1128void ViewCellsManager::SetInitialSamples(const int initialSamples)
1129{
1130        mInitialSamples = initialSamples;
1131}
1132
1133
[440]1134void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
1135{
1136        mPostProcessSamples = postProcessSamples;
1137}
1138
[485]1139
[440]1140int ViewCellsManager::GetVisualizationSamples() const
1141{
1142        return mVisualizationSamples;
1143}
1144
[485]1145
[440]1146int ViewCellsManager::GetConstructionSamples() const
1147{
1148        return mConstructionSamples;
1149}
1150
[485]1151
[440]1152int ViewCellsManager::GetPostProcessSamples() const
1153{
1154        return mPostProcessSamples;
1155}
1156
[485]1157
[719]1158void ViewCellsManager::UpdatePvs()
1159{
[720]1160        if (mViewCellPvsIsUpdated || !ViewCellsTreeConstructed())
[719]1161                return;
1162
1163        mViewCellPvsIsUpdated = true;
1164
1165        ViewCellContainer leaves;
1166        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
1167
1168        ViewCellContainer::const_iterator it, it_end = leaves.end();
1169
1170        for (it = leaves.begin(); it != it_end; ++ it)
1171        {
1172                mViewCellsTree->PropagatePvs(*it);
1173        }
1174}
1175
1176
[485]1177void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]1178{
[719]1179        // update pvs of view cells tree if necessary
1180        UpdatePvs();
[467]1181
[719]1182        ViewCellContainer::const_iterator it = mViewCells.begin();
1183
1184        stat.viewcells = 0;
1185        stat.minPvs = 100000000;
1186        stat.maxPvs = 0;
1187        stat.avgPvs = 0.0f;
1188
1189        for (; it != mViewCells.end(); ++ it)
1190        {
1191                ViewCell *viewcell = *it;
1192               
1193                const int pvsSize = mViewCellsTree->GetPvsSize(viewcell);
1194               
1195                if (pvsSize < stat.minPvs)
1196                        stat.minPvs = pvsSize;
1197                if (pvsSize > stat.maxPvs)
1198                        stat.maxPvs = pvsSize;
1199                stat.avgPvs += pvsSize;
1200               
1201                ++ stat.viewcells;
1202        }
1203
1204        if (stat.viewcells)
1205                stat.avgPvs/=stat.viewcells;
[467]1206}
1207
[485]1208
[480]1209void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]1210{
1211  s<<"############# Viewcell PVS STAT ##################\n";
1212  PvsStatistics pvsStat;
1213  GetPvsStatistics(pvsStat);
1214  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
1215  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
1216  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
1217}
1218
[485]1219
[532]1220int ViewCellsManager::CastBeam(Beam &beam)
1221{
1222        return 0;
1223}
1224
[547]1225
[468]1226ViewCellContainer &ViewCellsManager::GetViewCells()
1227{
1228        return mViewCells;
1229}
1230
[485]1231
[487]1232void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
1233{
[542]1234        mViewSpaceBox = box;
[591]1235
[660]1236        CreateClipPlane();
[591]1237       
[577]1238        mTotalAreaValid = false;
[487]1239}
1240
1241
[660]1242void ViewCellsManager::CreateClipPlane()
[591]1243{
1244        int axis = 0;
[667]1245        float pos;
[591]1246
[667]1247        environment->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
[591]1248
[667]1249        Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
1250
[660]1251        if (mUseClipPlaneForViz)
1252        environment->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
[591]1253
1254        Vector3 normal(0,0,0);
1255        normal[axis] = 1;
1256
[660]1257        mClipPlane = Plane3(normal, point);
[591]1258}
1259
1260
[519]1261AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
1262{
[542]1263        return mViewSpaceBox;
[519]1264}
1265
1266
[480]1267void ViewCellsManager::ResetViewCells()
1268{
[720]1269        // recollect view cells
[480]1270        mViewCells.clear();
1271        CollectViewCells();
[590]1272       
[720]1273       
1274        // stats are computed once more
[660]1275        mCurrentViewCellsStats.Reset();
[480]1276        EvaluateViewCellsStats();
[590]1277
[520]1278        // has to be recomputed
[480]1279        mTotalAreaValid = false;
1280}
1281
[485]1282
[547]1283int ViewCellsManager::GetMaxPvsSize() const
1284{
1285        return mMaxPvsSize;
1286}
1287
[590]1288
[563]1289void
1290ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
1291{
1292  if (!ViewCellsConstructed())
1293        return;
[564]1294
[563]1295  VssRayContainer::const_iterator it, it_end = rays.end();
[564]1296
[563]1297  for (it = rays.begin(); it != it_end; ++ it) {
1298        AddSampleContributions(*(*it));
1299  }
1300}
[547]1301
[581]1302
[562]1303int ViewCellsManager::GetMinPvsSize() const
1304{
1305        return mMinPvsSize;
1306}
1307
1308
1309
[561]1310float ViewCellsManager::GetMaxPvsRatio() const
1311{
1312        return mMaxPvsRatio;
1313}
1314
1315
[563]1316void
1317ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]1318{
[563]1319  // assumes viewcells have been stored...
1320  ViewCellContainer *viewcells = &ray.mViewCells;
1321  ViewCellContainer::const_iterator it;
1322  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
1323        ViewCell *viewcell = *it;
[569]1324        if (viewcell->GetValid()) {
1325          // if ray not outside of view space
1326          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1327        }
[563]1328  }
1329}
[503]1330
[574]1331
[570]1332float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
[574]1333                                                                                                   const bool addRays,
1334                                                                                                   const bool storeViewCells)
[563]1335{
[570]1336        ViewCellContainer viewcells;
[564]1337
[570]1338        ray.mPvsContribution = 0;
1339        ray.mRelativePvsContribution = 0.0f;
[485]1340
[570]1341        static Ray hray;
[564]1342        hray.Init(ray);
1343        //hray.mFlags |= Ray::CULL_BACKFACES;
1344        //Ray hray(ray);
1345
1346        float tmin = 0, tmax = 1.0;
1347
1348        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
[565]1349                return 0;
[564]1350
1351        Vector3 origin = hray.Extrap(tmin);
1352        Vector3 termination = hray.Extrap(tmax);
1353
1354        CastLineSegment(origin, termination, viewcells);
[664]1355
[570]1356        // copy viewcells memory efficiently
[574]1357        //const bool storeViewcells = !addRays;
[564]1358
[574]1359        if (storeViewCells)
[570]1360        {
1361                ray.mViewCells.reserve(viewcells.size());
1362                ray.mViewCells = viewcells;
1363        }
[564]1364
[570]1365        ViewCellContainer::const_iterator it = viewcells.begin();
[564]1366
[664]1367        for (; it != viewcells.end(); ++ it)
1368        {
1369                ViewCell *viewcell = *it;
[694]1370
[708]1371                if (viewcell->GetValid())
[664]1372                {
[694]1373                        // HACK
[706]1374#if TEST_EMPTY_VIEW_CELLS
[694]1375                                for (int i = 0; i < mEmptyViewCells.size(); ++i)
1376                                {
1377                                        if (viewcell == mEmptyViewCells[i])
1378                                        {
1379                                                viewcell->mPiercingRays.push_back(new Ray(ray));
1380                                                Debug << "empty view cell ray found: " << ray.mOriginObject << ", " << ray.mTerminationObject << endl;
1381                                        }
1382                                }
[706]1383#endif
[664]1384                        // if ray not outside of view space
1385                        float contribution;
[666]1386                        if (ray.mTerminationObject &&
1387                                viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
[664]1388                                                                                                                 ray.mPdf,
1389                                                                                                                 contribution))
1390                        {
1391                                ++ ray.mPvsContribution;
1392                                ray.mRelativePvsContribution += contribution;
1393                        }
[718]1394
1395                        //for directional sampling it is important to count only contributions
1396                        // made in one direction!!!
1397                        // the other contributions of this sample will be counted for the oposite ray!
1398#if 0
[666]1399                        if (ray.mOriginObject &&
1400                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
1401                                                                                                                 ray.mPdf,
1402                                                                                                                 contribution))
1403                        {
1404                                ++ ray.mPvsContribution;
1405                                ray.mRelativePvsContribution += contribution;
1406                        }
[718]1407#endif
[664]1408                }
[569]1409        }
[564]1410
[664]1411       
1412        if (addRays)
1413        {
1414                for (it = viewcells.begin(); it != viewcells.end(); ++ it)
1415                {
1416                        ViewCell *viewcell = *it;
1417           
[706]1418                        if (viewcell->GetValid())
[664]1419                        {
1420                                // if ray not outside of view space
[666]1421                                 if (ray.mTerminationObject)
1422                                         viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
[718]1423
1424#if 0
[666]1425                                 if (ray.mOriginObject)
1426                                         viewcell->GetPvs().AddSample(ray.mOriginObject, ray.mPdf);
[718]1427#endif
[664]1428                        }
1429                }
[563]1430        }
[570]1431
1432        return ray.mRelativePvsContribution;
[468]1433}
1434
1435
[469]1436void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]1437                                                                  const int maxSize,
[503]1438                                                                  VssRayContainer &usedRays,
[485]1439                                                                  VssRayContainer *savedRays) const
[469]1440{
[485]1441        const int limit = min(maxSize, (int)sourceRays.size());
[473]1442        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]1443
[485]1444        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]1445        for (it = sourceRays.begin(); it != it_end; ++ it)
1446        {
[473]1447                if (Random(1.0f) < prop)
[485]1448                        usedRays.push_back(*it);
1449                else if (savedRays)
1450                        savedRays->push_back(*it);
[469]1451        }
1452}
1453
[477]1454
[605]1455float ViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1456{
1457        return mViewCellsTree->GetPvsSize(viewCell) * objRendercost;
1458}
1459
1460
[477]1461float ViewCellsManager::GetAccVcArea()
[470]1462{
1463        // if already computed
1464        if (mTotalAreaValid)
1465                return mTotalArea;
1466
1467        mTotalArea = 0;
1468        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1469
1470        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]1471        {
1472                //Debug << "area: " << GetArea(*it);
[470]1473        mTotalArea += GetArea(*it);
[480]1474        }
1475
[470]1476        mTotalAreaValid = true;
1477
1478        return mTotalArea;
1479}
1480
[482]1481
[475]1482void ViewCellsManager::PrintStatistics(ostream &s) const
1483{
[660]1484        s << mCurrentViewCellsStats << endl;
[475]1485}
1486
[477]1487
[508]1488void ViewCellsManager::CreateUniqueViewCellIds()
[482]1489{
[651]1490        if (ViewCellsTreeConstructed())
1491                mViewCellsTree->CreateUniqueViewCellsIds();
1492        else
1493                for (int i = 0; i < (int)mViewCells.size(); ++ i)
1494                        mViewCells[i]->SetId(i);
[508]1495}
1496
1497
1498void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
1499{
[482]1500        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1501
1502        for (it = mViewCells.begin(); it != it_end; ++ it)
1503        {
[574]1504                if (!mOnlyValidViewCells || (*it)->GetValid())
1505                {
[582]1506                        ExportColor(exporter, *it);             
[591]1507                        ExportViewCellGeometry(exporter, *it,
[660]1508                                mUseClipPlaneForViz ? &mClipPlane : NULL);
[574]1509                }
[482]1510        }
1511}
1512
1513
[517]1514void ViewCellsManager::CreateViewCellMeshes()
[503]1515{
1516        // convert to meshes
1517        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1518
1519        for (it = mViewCells.begin(); it != it_end; ++ it)
1520        {
[517]1521                if (!(*it)->GetMesh())
1522                        CreateMesh(*it);
[503]1523        }
1524}
1525
[508]1526
[564]1527bool ViewCellsManager::ExportViewCells(const string filename)
1528{
[508]1529        return false;
1530}
1531
1532
[610]1533void ViewCellsManager::CollectViewCells(const int n)
[508]1534{
[610]1535        mNumActiveViewCells = n;
1536        mViewCells.clear();
1537        CollectViewCells();
1538}
[508]1539
1540
[660]1541void ViewCellsManager::SetViewCellsActive()
1542{
1543        ++ ViewCell::sLastUpdated;
1544        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1545        for (it = mViewCells.begin(); it != it_end; ++ it)
1546        {
1547                (*it)->SetActive();
1548        }
1549}
[508]1550
[440]1551/**********************************************************************/
1552/*                   BspViewCellsManager implementation               */
1553/**********************************************************************/
1554
[482]1555
[574]1556BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
1557ViewCellsManager(), mBspTree(bspTree)
[440]1558{
[574]1559        environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
[587]1560        mBspTree->SetViewCellsManager(this);
[590]1561        mBspTree->mViewCellsTree = mViewCellsTree;
[440]1562}
1563
[462]1564
[440]1565bool BspViewCellsManager::ViewCellsConstructed() const
1566{
1567        return mBspTree->GetRoot() != NULL;
1568}
1569
[480]1570
[440]1571ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1572{
1573        return new BspViewCell(mesh);
1574}
1575
[480]1576
[574]1577int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1578                                                                                          const VssRayContainer &rays)
[440]1579{
[441]1580        // if view cells were already constructed
[440]1581        if (ViewCellsConstructed())
1582                return 0;
1583
1584        int sampleContributions = 0;
[503]1585
[469]1586        // construct view cells using the collected samples
1587        RayContainer constructionRays;
1588        VssRayContainer savedRays;
[440]1589
[574]1590        const int limit = min(mInitialSamples, (int)rays.size());
[440]1591
[469]1592        VssRayContainer::const_iterator it, it_end = rays.end();
[448]1593
[473]1594        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
1595
[469]1596        for (it = rays.begin(); it != it_end; ++ it)
1597        {
[473]1598                if (Random(1.0f) < prop)
[469]1599                        constructionRays.push_back(new Ray(*(*it)));
1600                else
1601                        savedRays.push_back(*it);
1602        }
[440]1603
[503]1604    if (mViewCells.empty())
1605        {
1606                // no view cells loaded
[587]1607                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
[469]1608                // collect final view cells
1609                mBspTree->CollectViewCells(mViewCells);
[503]1610        }
[469]1611        else
1612        {
1613                mBspTree->Construct(mViewCells);
1614        }
1615
1616        // destroy rays created only for construction
1617        CLEAR_CONTAINER(constructionRays);
1618
[440]1619        Debug << mBspTree->GetStatistics() << endl;
[503]1620
1621        //EvaluateViewCellsStats();
[660]1622        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[480]1623
[469]1624        // recast rest of the rays
[649]1625        if (SAMPLE_AFTER_SUBDIVISION)
1626                ComputeSampleContributions(savedRays, true, false);
[469]1627
[719]1628        // real meshes are contructed at this stage
1629        if (0)
1630        {
1631                cout << "finalizing view cells ... ";
1632                FinalizeViewCells(true);
1633                cout << "finished" << endl;     
1634        }
1635
[440]1636        return sampleContributions;
1637}
1638
[503]1639
[480]1640void BspViewCellsManager::CollectViewCells()
1641{
[587]1642        // view cells tree constructed
1643        if (!ViewCellsTreeConstructed())
[591]1644        {               
[587]1645                mBspTree->CollectViewCells(mViewCells);
1646        }
1647        else
1648        {
1649                // we can use the view cells tree hierarchy to get the right set
[591]1650                mViewCellsTree->CollectBestViewCellSet(mViewCells,
[600]1651                                                                                           mNumActiveViewCells);
[587]1652        }
[480]1653}
[468]1654
[503]1655
[471]1656float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]1657{
[471]1658        // compute view cell area as subsititute for probability
[591]1659        if (1)
1660                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1661        else
1662                return GetArea(viewCell) / GetAccVcArea();
[466]1663}
[440]1664
[503]1665
[440]1666
[468]1667int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1668                                                                                 const Vector3 &termination,
1669                                                                                 ViewCellContainer &viewcells)
[440]1670{
[468]1671        return mBspTree->CastLineSegment(origin, termination, viewcells);
1672}
1673
1674
[503]1675int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]1676                                                                         const VssRayContainer &rays)
1677{
[469]1678        if (!ViewCellsConstructed())
[441]1679        {
1680                Debug << "view cells not constructed" << endl;
1681                return 0;
1682        }
[590]1683       
1684        // view cells already finished before post processing step (i.e. because they were loaded)
1685        if (mViewCellsFinished)
1686        {
1687                FinalizeViewCells(true);
1688                EvaluateViewCellsStats();
1689
1690                return 0;
1691        }
1692
[440]1693        //-- post processing of bsp view cells
[600]1694
[440]1695    int vcSize = 0;
1696        int pvsSize = 0;
1697
[591]1698        //-- merge view cells
[649]1699        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1700        long startTime = GetTime();
1701       
1702        VssRayContainer postProcessRays;
1703        GetRaySets(rays, mPostProcessSamples, postProcessRays);
1704
[592]1705        if (mMergeViewCells)
[591]1706        {
[660]1707                cout << "constructing visibility based merge tree" << endl;
[650]1708                mViewCellsTree->ConstructMergeTree(rays, objects);
[649]1709        }
1710        else
1711        {
[660]1712                cout << "constructing spatial merge tree" << endl;
[649]1713                // create spatial merge hierarchy
[650]1714                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mBspTree->GetRoot()));
[649]1715        }
[440]1716
[660]1717        // export statistics after merge
[666]1718        if (1)
1719        {
1720                char mstats[100];
1721                environment->GetStringValue("ViewCells.mergeStats", mstats);
1722                mViewCellsTree->ExportStats(mstats);
1723        }
[650]1724
[649]1725        //-- stats and visualizations
1726        cout << "finished" << endl;
[650]1727        cout << "merged view cells in "
[649]1728                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[440]1729
[650]1730        Debug << "Postprocessing: Merged view cells in "
[649]1731                << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1732       
[503]1733
[660]1734        //-- visualization and statistics
[600]1735    // reset view cells and stats
[480]1736        ResetViewCells();
[660]1737        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
[600]1738
[660]1739
[600]1740        int savedColorCode  = mColorCode;
[605]1741       
[600]1742        //BspLeaf::NewMail();
1743        if (1) // export merged view cells
1744        {
1745                mColorCode = 0;
[605]1746               
[600]1747                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[605]1748               
[600]1749
1750                cout << "exporting view cells after merge ... ";
1751
1752                if (exporter)
1753                {
1754                        if (mExportGeometry)
1755                                exporter->ExportGeometry(objects);
1756
1757                        //exporter->SetWireframe();
1758                        exporter->SetFilled();
1759                        ExportViewCellsForViz(exporter);
1760
1761
1762                        delete exporter;
1763                }
1764                cout << "finished" << endl;
1765        }
1766
1767        if (1) // export merged view cells
1768        {
1769                mColorCode = 1;
1770
1771                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
1772       
1773                cout << "exporting view cells after merge (pvs size) ... ";     
1774
1775                if (exporter)
1776                {
1777                        //exporter->SetWireframe();
1778                       
1779                        if (mExportGeometry)
1780                                exporter->ExportGeometry(objects);
1781
1782                        //exporter->SetWireframe();
1783                        exporter->SetFilled();
1784                        ExportViewCellsForViz(exporter);
1785
1786                        delete exporter;
1787                }
1788                cout << "finished" << endl;
1789        }
1790
[693]1791       
1792        // only for testing
1793        TestSubdivision();
1794
[600]1795        mColorCode = savedColorCode;
1796
[719]1797        // compute final meshes and volume / area
1798        if (1) FinalizeViewCells(true);
1799
[587]1800        // write view cells to disc
1801        if (mExportViewCells)
1802        {
1803                char buff[100];
1804                environment->GetStringValue("ViewCells.filename", buff);
1805                string vcFilename(buff);
1806
1807                ExportViewCells(buff);
1808        }
1809
[650]1810        return 0;
[440]1811}
1812
[477]1813
1814BspViewCellsManager::~BspViewCellsManager()
1815{
1816}
1817
1818
[440]1819int BspViewCellsManager::GetType() const
1820{
1821        return BSP;
1822}
1823
1824
1825void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1826                                                                        const VssRayContainer &sampleRays)
[440]1827{
[469]1828        if (!ViewCellsConstructed())
1829                return;
[574]1830       
[600]1831        int savedColorCode = mColorCode;
1832
1833       
1834       
1835        if (1) // export final view cells
[440]1836        {
[600]1837                mColorCode = 1;
[587]1838
[712]1839                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
[600]1840       
1841                cout << "exporting view cells after merge (pvs size) ... ";     
[587]1842
[469]1843                if (exporter)
[440]1844                {
[600]1845                        //exporter->SetWireframe();
1846                       
1847                        if (mExportGeometry)
1848                                exporter->ExportGeometry(objects);
[590]1849
[600]1850                        //exporter->SetWireframe();
1851                        exporter->SetFilled();
[508]1852                        ExportViewCellsForViz(exporter);
[587]1853
[469]1854                        delete exporter;
[440]1855                }
[469]1856                cout << "finished" << endl;
[503]1857        }
[477]1858
[600]1859        mColorCode = savedColorCode;
1860
[469]1861        //-- visualization of the BSP splits
1862        bool exportSplits = false;
1863        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]1864
[469]1865        if (exportSplits)
[440]1866        {
[469]1867                cout << "exporting splits ... ";
[477]1868                ExportSplits(objects);
[469]1869                cout << "finished" << endl;
[440]1870        }
[477]1871
[600]1872        // export single view cells
[477]1873        ExportBspPvs(objects);
[440]1874}
1875
1876
[503]1877inline bool vc_gt(ViewCell *a, ViewCell *b)
1878{
[440]1879        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1880}
1881
[477]1882
1883void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]1884{
1885        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1886
[503]1887        if (exporter)
1888        {
[598]1889                //exporter->SetFilled();
1890
1891                if (mExportGeometry)
1892                        exporter->ExportGeometry(objects);
1893
[503]1894                Material m;
[440]1895                m.mDiffuseColor = RgbColor(1, 0, 0);
1896                exporter->SetForcedMaterial(m);
1897                exporter->SetWireframe();
[503]1898
[440]1899                exporter->ExportBspSplits(*mBspTree, true);
1900
[482]1901                //NOTE: take forced material, else big scenes cannot be viewed
[440]1902                m.mDiffuseColor = RgbColor(0, 1, 0);
1903                exporter->SetForcedMaterial(m);
[482]1904                //exporter->ResetForcedMaterial();
1905
[440]1906                delete exporter;
1907        }
1908}
1909
[477]1910
1911void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]1912{
[477]1913        const int leafOut = 10;
[503]1914
[477]1915        ViewCell::NewMail();
[440]1916
[477]1917        //-- some rays for output
1918        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]1919
[477]1920        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1921        Debug << "\nOutput view cells: " << endl;
[503]1922
[478]1923        // sort view cells to get largest view cells
[587]1924        if (0)
1925                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1926
[503]1927        int limit = min(leafOut, (int)mViewCells.size());
1928
[478]1929        for (int i = 0; i < limit; ++ i)
[477]1930        {
[478]1931                cout << "creating output for view cell " << i << " ... ";
1932                VssRayContainer vcRays;
1933                Intersectable::NewMail();
[582]1934                ViewCell *vc;
1935
1936                if (0)
1937                        vc = mViewCells[i];
1938                else
1939                        vc = mViewCells[Random((int)mViewCells.size())];
1940
[478]1941                cout << "creating output for view cell " << i << " ... ";
[469]1942
[587]1943                if(0)
[477]1944                {
[587]1945                        // check whether we can add the current ray to the output rays
1946                        for (int k = 0; k < raysOut; ++ k)
[477]1947                        {
[587]1948                                BspRay *ray = mBspRays[k];
1949                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1950                                {
1951                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1952                                        if (vc == leaf->GetViewCell())
1953                                                vcRays.push_back(ray->vssRay);
1954                                }
[477]1955                        }
1956                }
[587]1957
[478]1958                //bspLeaves[j]->Mail();
1959                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]1960
[478]1961                Exporter *exporter = Exporter::GetExporter(s);
[503]1962
[478]1963                exporter->SetWireframe();
[477]1964
[478]1965                Material m;//= RandomMaterial();
1966                m.mDiffuseColor = RgbColor(0, 1, 0);
1967                exporter->SetForcedMaterial(m);
[477]1968
[587]1969                ExportViewCellGeometry(exporter, vc);
1970               
[478]1971                // export rays piercing this view cell
1972                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
[580]1973
[478]1974                m.mDiffuseColor = RgbColor(1, 0, 0);
1975                exporter->SetForcedMaterial(m);
[440]1976
[478]1977                ObjectPvsMap::const_iterator it,
1978                        it_end = vc->GetPvs().mEntries.end();
[440]1979
[478]1980                exporter->SetFilled();
[469]1981
[478]1982                // output PVS of view cell
[503]1983                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]1984                {
1985                        Intersectable *intersect = (*it).first;
[469]1986
[478]1987                        if (!intersect->Mailed())
1988                        {
1989                                Material m = RandomMaterial();
1990                                exporter->SetForcedMaterial(m);
1991
1992                                exporter->ExportIntersectable(intersect);
1993                                intersect->Mail();
[503]1994                        }
[477]1995                }
[503]1996
[478]1997                DEL_PTR(exporter);
1998                cout << "finished" << endl;
[477]1999        }
2000
2001        Debug << endl;
[440]2002}
2003
[441]2004
[503]2005void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]2006                                                                          ViewCell *vc) const
2007{
[600]2008        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[482]2009
2010        float importance = 0;
[598]2011        static Material m;
[482]2012
2013        switch (mColorCode)
2014        {
[598]2015        case 0: // Random
2016                {
2017                        if (vcValid)
2018                        {
2019                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
2020                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
[600]2021                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
[598]2022                        }
2023                        else
2024                        {
2025                                m.mDiffuseColor.r = 0.0f;
2026                                m.mDiffuseColor.g = 1.0f;
2027                                m.mDiffuseColor.b = 0.0f;
2028                        }
2029
2030                        exporter->SetForcedMaterial(m);
2031                        return;
2032                }
2033               
[482]2034        case 1: // pvs
2035                {
[503]2036                        importance = (float)vc->GetPvs().GetSize() /
[660]2037                                (float)mCurrentViewCellsStats.maxPvs;
[598]2038
[482]2039                }
2040                break;
2041        case 2: // merges
2042                {
[598]2043            int lSize = mViewCellsTree->GetSize(vc);
[660]2044                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]2045                }
[598]2046                //break;
[482]2047        case 3: // merge tree differene
2048                {
2049                        // TODO
[598]2050                        //importance = (float)GetMaxTreeDiff(vc) /
2051                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2052
[482]2053                }
2054                break;
2055        default:
2056                break;
2057        }
2058
[598]2059        // special color code for invalid view cells
[482]2060        m.mDiffuseColor.r = importance;
2061        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[598]2062        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[503]2063
[598]2064        //Debug << "importance: " << importance << endl;
[482]2065        exporter->SetForcedMaterial(m);
2066}
2067
[587]2068
[693]2069void BspViewCellsManager::TestSubdivision()
2070{
2071        ViewCellContainer leaves;
2072        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
2073
2074        ViewCellContainer::const_iterator it, it_end = leaves.end();
2075
2076        const float vol = mViewSpaceBox.GetVolume();
2077        float subdivVol = 0;
2078        float newVol = 0;
2079
2080        for (it = leaves.begin(); it != it_end; ++ it)
2081        {
2082                BspNodeGeometry geom;
2083                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2084                mBspTree->ConstructGeometry(leaf, geom);
2085
2086                const float lVol = geom.GetVolume();
2087               
2088                newVol += lVol;
2089                subdivVol += (*it)->GetVolume();
[694]2090
[704]2091                float thres = 0.9f;
[694]2092                if ((lVol < ((*it)->GetVolume() * thres)) ||
2093                        (lVol * thres > ((*it)->GetVolume())))
2094                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]2095        }
2096       
2097        Debug << "exact volume: " << vol << endl;
2098        Debug << "subdivision volume: " << subdivVol << endl;
2099        Debug << "new volume: " << newVol << endl;
2100}
2101
2102
[580]2103void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2104                                                                                                 ViewCell *vc,
[660]2105                                                                                                 const Plane3 *clipPlane) const
[482]2106{
2107        if (vc->GetMesh())
2108        {
[587]2109                exporter->ExportMesh(vc->GetMesh());
[726]2110       
[587]2111                return;
[482]2112        }
[587]2113
[726]2114       
[660]2115        if (clipPlane)
[591]2116        {
[726]2117                ViewCellContainer leaves;
2118                mViewCellsTree->CollectLeaves(vc, leaves);
2119                ViewCellContainer::const_iterator it, it_end = leaves.end();
[591]2120
[726]2121                for (it = leaves.begin(); it != it_end; ++ it)
[681]2122                {
[726]2123                        BspNodeGeometry geom;
2124
[681]2125                        BspNodeGeometry front;
2126                        BspNodeGeometry back;
[591]2127
[726]2128                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2129                        mBspTree->ConstructGeometry(leaf, geom);
[681]2130
[726]2131                        const float eps = 0.00000001f;
2132                        const int cf = geom.Side(*clipPlane, eps);
2133
2134                        if (cf == -1)
2135                        {
2136                                exporter->ExportPolygons(geom.GetPolys());
2137                        }
2138                        else if (cf == 0)
2139                        {
2140                                geom.SplitGeometry(front,
2141                                                                   back,
2142                                                                   *clipPlane,
2143                                                                   mViewSpaceBox,
2144                                                                   eps);
2145       
2146                                //Debug << "geo size: " << geom.Size() << endl;
2147                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
2148                                if (back.Valid())
2149                                {
2150                                        exporter->ExportPolygons(back.GetPolys());
2151                                }                       
2152                        }
[681]2153                }
[591]2154        }
2155        else
2156        {
[726]2157                BspNodeGeometry geom;
2158                mBspTree->ConstructGeometry(vc, geom);
2159                       
[678]2160                exporter->ExportPolygons(geom.GetPolys());
[591]2161        }
[482]2162}
2163
[503]2164
2165void BspViewCellsManager::CreateMesh(ViewCell *vc)
2166{
[726]2167        // delete previous mesh
2168        ///DEL_PTR(vc->GetMesh());
[587]2169        BspNodeGeometry geom;
2170        mBspTree->ConstructGeometry(vc, geom);
2171
2172        Mesh *mesh = new Mesh();
[726]2173
[587]2174        geom.AddToMesh(*mesh);
2175        vc->SetMesh(mesh);
[726]2176        // put mesh into mesh container so we can savely delete it
[587]2177        mMeshContainer.push_back(mesh);
[503]2178}
2179
[551]2180
[587]2181void BspViewCellsManager::Finalize(ViewCell *viewCell,
2182                                                                   const bool createMesh)
[502]2183{
[587]2184        float area = 0;
2185        float volume = 0;
[572]2186
[587]2187        ViewCellContainer leaves;
2188        mViewCellsTree->CollectLeaves(viewCell, leaves);
2189
2190        ViewCellContainer::const_iterator it, it_end = leaves.end();
2191
[693]2192    for (it = leaves.begin(); it != it_end; ++ it)
[587]2193        {
2194                BspNodeGeometry geom;
2195                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2196                mBspTree->ConstructGeometry(leaf, geom);
2197
[719]2198                const float lVol = geom.GetVolume();
2199                const float lArea = geom.GetArea();
[693]2200
2201                //(*it)->SetVolume(vol);
2202                //(*it)->SetArea(area);
2203
2204                area += lArea;
2205                volume += lVol;
2206
2207        CreateMesh(*it);
[587]2208        }
2209
2210        viewCell->SetVolume(volume);
2211        viewCell->SetArea(area);
[502]2212}
2213
[580]2214
[587]2215ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
[580]2216{
[587]2217        if (!mBspTree)
2218                return NULL;
2219
2220        if (!mViewSpaceBox.IsInside(point))
2221                return NULL;
2222       
2223        return mBspTree->GetViewCell(point);
[580]2224}
2225
2226
[587]2227void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2228                                                                                                 vector<MergeCandidate> &candidates)
2229{
2230        cout << "collecting merge candidates ... " << endl;
2231
2232        if (mUseRaysForMerge)
2233        {
2234                mBspTree->CollectMergeCandidates(rays, candidates);
2235        }
2236        else
2237        {
2238                vector<BspLeaf *> leaves;
2239                mBspTree->CollectLeaves(leaves);
2240                mBspTree->CollectMergeCandidates(leaves, candidates);
2241        }
2242
2243        cout << "fininshed collecting candidates" << endl;
2244}
2245
2246
[440]2247
[590]2248bool BspViewCellsManager::ExportViewCells(const string filename)
2249{
2250        cout << "exporting view cells to xml ... ";
2251        std::ofstream stream;
[503]2252
[590]2253        // for output we need unique ids for each view cell
2254        CreateUniqueViewCellIds();
[503]2255
[590]2256
2257        stream.open(filename.c_str());
2258        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2259        stream << "<Visibility_Solution>" << endl;
2260
2261        //-- the view space bounding box
2262        stream << "<ViewSpaceBox"
2263                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
2264                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
2265
2266        //-- the type of the view cells hierarchy
2267        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
2268        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
2269        //-- load the view cells itself, i.e., the ids and the pvs
2270        stream << "<ViewCells>" << endl;
[610]2271
2272#if 0
2273       
[590]2274        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[610]2275               
[590]2276        for (it = mViewCells.begin(); it != it_end; ++ it)
2277                ExportViewCell(*it, stream);
[610]2278#else
2279        mViewCellsTree->Export(stream);
2280#endif
[590]2281
2282        stream << "</ViewCells>" << endl;
2283
2284        //-- load the hierarchy
2285        stream << "<Hierarchy>" << endl;
2286        mBspTree->Export(stream);
2287        stream << endl << "</Hierarchy>" << endl;
2288
2289        stream << "</Visibility_Solution>" << endl;
2290        stream.close();
2291
2292        cout << "finished" << endl;
2293
2294        return true;
2295}
2296
2297
2298void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
2299{
2300        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2301        for (it = mViewCells.begin(); it != it_end; ++ it)
2302        {
2303                ViewCell *vc = *it;
2304                ViewCellContainer leaves;
2305                mViewCellsTree->CollectLeaves(vc, leaves);
2306               
2307                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2308
2309                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2310                {
2311                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
2312                        bspVc->mLeaf->SetViewCell(vc);
2313                }
2314        }
2315}
2316
[610]2317
[650]2318ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[610]2319{
[650]2320        if (root->IsLeaf())
2321        {
2322                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
[610]2323
[650]2324                viewCell->SetMergeCost(0.0f);
[610]2325
[650]2326                return viewCell;
2327        }
2328       
2329        BspInterior *interior = dynamic_cast<BspInterior *>(root);
2330        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2331               
2332        float mergeCost = 1.0f / (float)root->mTimeStamp;
2333        //Debug << "timestamp: " << root->mTimeStamp;
2334        //Debug << "merge cost: " << mergeCost << endl;
[649]2335
[650]2336        viewCellInterior->SetMergeCost(mergeCost);
[649]2337
[650]2338        float volume = 0;
[649]2339       
[650]2340        BspNode *front = interior->GetFront();
2341        BspNode *back = interior->GetBack();
[649]2342
[650]2343        // recursivly compute child hierarchies
2344        ViewCell *backVc = ConstructSpatialMergeTree(back);
2345        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]2346
[650]2347        viewCellInterior->SetupChildLink(frontVc);
2348        viewCellInterior->SetupChildLink(backVc);
[610]2349
[649]2350
[650]2351        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2352        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
[649]2353
[650]2354        volume += backVc->GetVolume();
2355        volume += frontVc->GetVolume();
[649]2356
[650]2357        viewCellInterior->SetVolume(volume);
[649]2358
[650]2359        return viewCellInterior;
[610]2360}
2361
[650]2362
[590]2363/************************************************************************/
2364/*                   KdViewCellsManager implementation                  */
2365/************************************************************************/
2366
2367
2368
[440]2369KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]2370ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]2371{
2372}
2373
[605]2374
[471]2375float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2376{
[479]2377        // compute view cell area / volume as subsititute for probability
[605]2378        if (0)
2379                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2380        else
2381                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[468]2382}
2383
2384
2385
[479]2386
[480]2387void KdViewCellsManager::CollectViewCells()
2388{
2389        //mKdTree->CollectViewCells(mViewCells); TODO
2390}
[479]2391
[519]2392
[574]2393int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]2394                                                                  const VssRayContainer &rays)
[440]2395{
[441]2396        // if view cells already constructed
[440]2397        if (ViewCellsConstructed())
2398                return 0;
[441]2399
[440]2400        mKdTree->Construct();
2401
[480]2402        mTotalAreaValid = false;
[469]2403        // create the view cells
2404        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]2405
[480]2406        // cast rays
[574]2407        ComputeSampleContributions(rays, true, false);
[480]2408
[479]2409        EvaluateViewCellsStats();
[660]2410        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[469]2411
[440]2412        return 0;
2413}
2414
[587]2415
[440]2416bool KdViewCellsManager::ViewCellsConstructed() const
2417{
2418        return mKdTree->GetRoot() != NULL;
2419}
2420
[503]2421int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2422                                                                        const VssRayContainer &rays)
[440]2423{
2424        return 0;
2425}
2426
2427void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2428                                                                   const VssRayContainer &sampleRays)
[440]2429{
[441]2430        if (!ViewCellsConstructed())
2431                return;
2432
[469]2433        // using view cells instead of the kd PVS of objects
2434        const bool useViewCells = true;
2435        bool exportRays = false;
[440]2436
2437        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]2438        const int pvsOut = min((int)objects.size(), 10);
[466]2439        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]2440
[469]2441        if (useViewCells)
[440]2442        {
[469]2443                const int leafOut = 10;
[503]2444
[469]2445                ViewCell::NewMail();
[503]2446
[469]2447                //-- some rays for output
2448                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
2449                Debug << "visualization using " << raysOut << " samples" << endl;
2450
2451                //-- some random view cells and rays for output
2452                vector<KdLeaf *> kdLeaves;
[503]2453
[469]2454                for (int i = 0; i < leafOut; ++ i)
2455                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]2456
[469]2457                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]2458                {
[469]2459                        KdLeaf *leaf = kdLeaves[i];
2460                        RayContainer vcRays;
[503]2461
[469]2462                        cout << "creating output for view cell " << i << " ... ";
[503]2463#if 0
[469]2464                        // check whether we can add the current ray to the output rays
[503]2465                        for (int k = 0; k < raysOut; ++ k)
[440]2466                        {
[469]2467                                Ray *ray = sampleRays[k];
[503]2468
[469]2469                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
2470                                {
2471                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]2472
2473                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]2474                                        {
2475                                                vcRays.push_back(ray);
2476                                        }
2477                                }
[479]2478                        }
[503]2479#endif
[469]2480                        Intersectable::NewMail();
[503]2481
[469]2482                        ViewCell *vc = leaf->mViewCell;
[503]2483
[469]2484                        //bspLeaves[j]->Mail();
2485                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]2486
[469]2487                        Exporter *exporter = Exporter::GetExporter(s);
2488                        exporter->SetFilled();
2489
2490                        exporter->SetWireframe();
2491                        //exporter->SetFilled();
[503]2492
[469]2493                        Material m;//= RandomMaterial();
2494                        m.mDiffuseColor = RgbColor(1, 1, 0);
2495                        exporter->SetForcedMaterial(m);
[503]2496
[469]2497                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
2498                        exporter->ExportBox(box);
2499
2500                        // export rays piercing this view cell
[503]2501                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
2502
[469]2503                        m.mDiffuseColor = RgbColor(1, 0, 0);
2504                        exporter->SetForcedMaterial(m);
[503]2505
[469]2506                        // exporter->SetWireframe();
2507                        exporter->SetFilled();
[503]2508
[469]2509                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
2510                        // output PVS of view cell
[503]2511                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]2512                        {
2513                                Intersectable *intersect = (*it).first;
2514                                if (!intersect->Mailed())
2515                                {
2516                                        exporter->ExportIntersectable(intersect);
2517                                        intersect->Mail();
[503]2518                                }
[440]2519                        }
[503]2520
[469]2521                        DEL_PTR(exporter);
2522                        cout << "finished" << endl;
[440]2523                }
[469]2524
2525                DEL_PTR(rays);
[440]2526        }
[469]2527        else // using kd PVS of objects
2528        {
2529                for (int i = 0; i < limit; ++ i)
2530                {
2531                        VssRay *ray = sampleRays[i];
[503]2532
[469]2533                        // check whether we can add this to the rays
[503]2534                        for (int j = 0; j < pvsOut; j++)
[469]2535                        {
2536                                if (objects[j] == ray->mTerminationObject)
2537                                {
2538                                        rays[j].push_back(ray);
2539                                }
2540                        }
2541                }
[440]2542
[503]2543                if (exportRays)
[469]2544                {
2545                        Exporter *exporter = NULL;
2546                        exporter = Exporter::GetExporter("sample-rays.x3d");
2547                        exporter->SetWireframe();
2548                        exporter->ExportKdTree(*mKdTree);
[503]2549
2550                        for (i=0; i < pvsOut; i++)
[469]2551                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
2552
2553                        exporter->SetFilled();
[503]2554
[469]2555                        delete exporter;
2556                }
[440]2557
[503]2558                for (int k=0; k < pvsOut; k++)
[469]2559                {
2560                        Intersectable *object = objects[k];
[503]2561                        char s[64];
[469]2562                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]2563
[469]2564                        Exporter *exporter = Exporter::GetExporter(s);
2565                        exporter->SetWireframe();
[503]2566
[469]2567                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
2568                        Intersectable::NewMail();
[503]2569
[469]2570                        // avoid adding the object to the list
2571                        object->Mail();
2572                        ObjectContainer visibleObjects;
[503]2573
2574                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]2575                        {
2576                                KdNode *node = (*i).first;
2577                                exporter->ExportBox(mKdTree->GetBox(node));
[503]2578
[469]2579                                mKdTree->CollectObjects(node, visibleObjects);
2580                        }
[503]2581
[469]2582                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
2583                        exporter->SetFilled();
[503]2584
[469]2585                        for (int j = 0; j < visibleObjects.size(); j++)
2586                                exporter->ExportIntersectable(visibleObjects[j]);
[503]2587
[469]2588                        Material m;
2589                        m.mDiffuseColor = RgbColor(1, 0, 0);
2590                        exporter->SetForcedMaterial(m);
2591                        exporter->ExportIntersectable(object);
[503]2592
[469]2593                        delete exporter;
[440]2594                }
[503]2595        }
[440]2596}
2597
[469]2598
[482]2599void KdViewCellsManager::ExportColor(Exporter *exporter,
2600                                                                         ViewCell *vc) const
2601{
2602        // TODO
2603}
2604
[666]2605
[580]2606ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2607{
2608        return new KdViewCell(mesh);
2609}
[482]2610
[580]2611
2612void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2613                                                                                                ViewCell *vc,
[660]2614                                                                                                const Plane3 *clipPlane) const
[482]2615{
[580]2616        ViewCellContainer leaves;
[485]2617
[580]2618        mViewCellsTree->CollectLeaves(vc, leaves);
2619        ViewCellContainer::const_iterator it, it_end = leaves.end();
2620
2621        for (it = leaves.begin(); it != it_end; ++ it)
2622        {
2623                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
2624       
2625                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
2626        }
[482]2627}
2628
2629
[440]2630int KdViewCellsManager::GetType() const
2631{
2632        return ViewCellsManager::KD;
2633}
2634
2635
[441]2636
[440]2637KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
2638{
2639        KdNode *node = leaf;
2640
2641        while (node->mParent && node->mDepth > mKdPvsDepth)
2642                node = node->mParent;
2643        return node;
2644}
2645
[469]2646int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
2647                                                                                const Vector3 &termination,
2648                                                                                ViewCellContainer &viewcells)
[466]2649{
[469]2650        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]2651}
2652
[469]2653
[503]2654void KdViewCellsManager::CreateMesh(ViewCell *vc)
2655{
[551]2656        // TODO
[503]2657}
2658
[580]2659
2660
2661void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2662                                                                                                vector<MergeCandidate> &candidates)
2663{
2664        // TODO
2665}
2666
2667
[440]2668/**********************************************************************/
2669/*                   VspKdViewCellsManager implementation             */
2670/**********************************************************************/
2671
[482]2672
[574]2673VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
2674ViewCellsManager(), mVspKdTree(vspKdTree)
[440]2675{
[574]2676        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
[468]2677        mVspKdTree->SetViewCellsManager(this);
2678}
[462]2679
[471]2680float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2681{
[605]2682        // compute view cell area / volume as subsititute for probability
2683        if (0)
2684                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2685        else
2686                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[440]2687}
2688
[462]2689
[468]2690
[503]2691
[480]2692void VspKdViewCellsManager::CollectViewCells()
2693{
2694        mVspKdTree->CollectViewCells(mViewCells);
2695}
[462]2696
[570]2697
[574]2698int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2699                                                                                                const VssRayContainer &rays)
[440]2700{
[441]2701        // if view cells already constructed
[440]2702        if (ViewCellsConstructed())
2703                return 0;
[503]2704
[469]2705        VssRayContainer constructionRays;
2706        VssRayContainer savedRays;
[440]2707
[503]2708        GetRaySets(rays,
[574]2709                           mInitialSamples,
[503]2710                           constructionRays,
[485]2711                           &savedRays);
[503]2712
2713        Debug << "constructing vsp kd tree using "
[469]2714                  << (int)constructionRays.size() << " samples" << endl;
[452]2715
[542]2716        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]2717        Debug << mVspKdTree->GetStatistics() << endl;
2718
[482]2719        // export leaf building blocks
2720        ExportLeaves(objects, rays);
[480]2721
[469]2722        // finally merge kd leaf building blocks to view cells
[485]2723        const int merged = mVspKdTree->MergeViewCells(rays);
2724
2725        // collapse siblings belonging to the same view cell
[486]2726        mVspKdTree->RefineViewCells(rays);
[485]2727
[542]2728        // collapse siblings belonging to the same view cell
[503]2729        mVspKdTree->CollapseTree();
2730
[482]2731        // evaluale view cell stats
2732        ResetViewCells();
[469]2733
[660]2734        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[482]2735
[485]2736        long startTime = GetTime();
[660]2737
[469]2738        // recast rest of rays
[574]2739        ComputeSampleContributions(savedRays, true, false);
[503]2740
2741        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]2742                  << " secs" << endl;
[469]2743
2744        return merged;
[440]2745}
2746
2747bool VspKdViewCellsManager::ViewCellsConstructed() const
2748{
2749        return mVspKdTree->GetRoot() != NULL;
2750}
2751
[441]2752
[462]2753ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2754{
2755        return new VspKdViewCell(mesh);
2756}
2757
[503]2758int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2759                                                                           const VssRayContainer &rays)
[440]2760{
[441]2761        if (!ViewCellsConstructed())
2762                return 0;
2763
[482]2764        // recalculate stats
2765        EvaluateViewCellsStats();
2766
[469]2767        return 0;
[440]2768}
2769
[482]2770
2771void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2772                                                                                 const VssRayContainer &sampleRays)
[440]2773{
[441]2774        if (!ViewCellsConstructed())
2775                return;
2776
[482]2777        //-- export leaf building blocks
[503]2778        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]2779        if (!exporter)
2780                return;
2781
[598]2782        if (mExportGeometry)
2783                exporter->ExportGeometry(objects);
2784       
[482]2785        //exporter->SetWireframe();
2786        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2787        exporter->ExportVspKdTree(*mVspKdTree);
2788
[503]2789        if (mExportRays)
[440]2790        {
[503]2791                const float prob = (float)mVisualizationSamples
[482]2792                        / ((float)sampleRays.size() + Limits::Small);
[440]2793
[482]2794                exporter->SetWireframe();
[440]2795
[482]2796                //-- collect uniformly distributed rays
2797                VssRayContainer rays;
[440]2798
[482]2799                for (int i = 0; i < sampleRays.size(); ++ i)
2800                {
2801                        if (RandomValue(0,1) < prob)
2802                                rays.push_back(sampleRays[i]);
[440]2803                }
[482]2804                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]2805        }
2806
[482]2807        delete exporter;
2808}
2809
[726]2810
[482]2811void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2812                                                                          const VssRayContainer &sampleRays)
2813{
2814        if (!ViewCellsConstructed())
2815                return;
[503]2816
[482]2817        //-- export single view cells
2818        for (int i = 0; i < 10; ++ i)
[440]2819        {
[482]2820                char s[64];
2821                sprintf(s, "vsp_viewcell%04d.x3d", i);
2822                Exporter *exporter = Exporter::GetExporter(s);
[503]2823                const int idx =
[482]2824                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]2825
[503]2826                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]2827
2828                //-- export geometry
2829                Material m;
2830                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]2831
[482]2832                exporter->SetForcedMaterial(m);
2833                exporter->SetWireframe();
2834
[580]2835                ExportViewCellGeometry(exporter, vc);
[482]2836
2837                //-- export stored rays
[580]2838               
[485]2839                if (mExportRays)
[440]2840                {
[580]2841                        ViewCellContainer leaves;
2842                        mViewCellsTree->CollectLeaves(vc, leaves);
[440]2843
[580]2844                        ViewCellContainer::const_iterator it,
2845                                it_end = leaves.end();
2846
2847                        for (it = leaves.begin(); it != it_end; ++ it)
[482]2848                        {
[580]2849                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2850                                VspKdLeaf *leaf = vspKdVc->mLeaf;
[482]2851                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]2852
[482]2853                                VssRayContainer vssRays;
[483]2854
2855                                VssRayContainer castRays;
2856                                VssRayContainer initRays;
2857
[482]2858                                leaf->GetRays(vssRays);
[440]2859
[482]2860                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]2861                                const float prop = 200.0f / (float)vssRays.size();
[440]2862
[482]2863                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]2864                                {
[485]2865                                        if (Random(1) < prop)
[483]2866                                                if ((*it)->mTerminationObject == NULL)
2867                                                        castRays.push_back(*it);
[503]2868                                                else
[483]2869                                                        initRays.push_back(*it);
2870                                }
2871
2872                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2873                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]2874                        }
2875                }
[580]2876       
[482]2877                //-- output PVS of view cell
2878                m.mDiffuseColor = RgbColor(1, 0, 0);
2879                exporter->SetForcedMaterial(m);
[440]2880
[483]2881                Intersectable::NewMail();
2882
[482]2883                ObjectPvsMap::const_iterator it,
2884                        it_end = vc->GetPvs().mEntries.end();
2885
2886                exporter->SetFilled();
2887
[503]2888                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]2889                {
2890                        Intersectable *intersect = (*it).first;
2891
2892                        if (!intersect->Mailed())
2893                        {
2894                                Material m = RandomMaterial();
2895                                exporter->SetForcedMaterial(m);
2896
2897                                exporter->ExportIntersectable(intersect);
2898                                intersect->Mail();
[503]2899                        }
[482]2900                }
2901
2902                delete exporter;
[440]2903        }
[462]2904
2905        //-- export final view cells
[503]2906        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2907
[483]2908
[508]2909        ExportViewCellsForViz(exporter);
[462]2910
[503]2911        if (mExportGeometry)
[465]2912        {
2913                exporter->SetFilled();
[462]2914                exporter->ExportGeometry(objects);
[465]2915        }
[469]2916
[503]2917        if (mExportRays)
[462]2918        {
[503]2919                const float prob = (float)mVisualizationSamples
[482]2920                        / ((float)sampleRays.size() + Limits::Small);
[503]2921
[462]2922                exporter->SetWireframe();
[503]2923
[466]2924                VssRayContainer rays;
[503]2925
[462]2926                for (int i = 0; i < sampleRays.size(); ++ i)
2927                {
[466]2928                  if (RandomValue(0,1) < prob)
2929                        rays.push_back(sampleRays[i]);
[462]2930                }
[503]2931                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]2932        }
2933
2934        delete exporter;
[440]2935}
2936
2937int VspKdViewCellsManager::GetType() const
2938{
2939        return VSP_KD;
2940}
[442]2941
[462]2942
[469]2943int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2944                                                                                   const Vector3 &termination,
2945                                                                                   ViewCellContainer &viewcells)
[466]2946{
[469]2947        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]2948}
2949
[477]2950
[482]2951void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2952                                                                                ViewCell *vc) const
2953{
2954        if (mColorCode == 0) // Random color
2955                return;
[503]2956
[482]2957        float importance = 0;
[477]2958
[482]2959        switch (mColorCode)
2960        {
2961        case 1: // pvs
2962                {
[503]2963                        importance = (float)vc->GetPvs().GetSize() /
[660]2964                                (float)mCurrentViewCellsStats.maxPvs;
[482]2965                }
2966                break;
[580]2967        case 2: // merged leaves
[482]2968                {
[580]2969                int lSize = mViewCellsTree->GetSize(vc);
2970                        importance = (float)lSize /
[660]2971                                (float)mCurrentViewCellsStats.maxLeaves;
[482]2972                }
2973                break;
[485]2974        case 3: // merged tree depth difference
[482]2975                {
[503]2976                        //importance = (float)GetMaxTreeDiff(vc) /
[482]2977                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2978                }
2979                break;
2980        default:
2981                break;
2982        }
2983
2984        Material m;
2985        m.mDiffuseColor.b = 1.0f;
2986        m.mDiffuseColor.r = importance;
2987        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2988        //Debug << "importance: " << importance << endl;
2989        exporter->SetForcedMaterial(m);
2990}
2991
2992
[580]2993void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2994                                                                                                   ViewCell *vc,
[660]2995                                                                                                   const Plane3 *clipPlane) const
[482]2996{
2997        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2998
[486]2999        Mesh m;
[580]3000
3001        ViewCellContainer leaves;
3002        mViewCellsTree->CollectLeaves(vc, leaves);
3003
3004        ViewCellContainer::const_iterator it, it_end = leaves.end();
3005
3006        for (it = leaves.begin(); it != it_end; ++ it)
[486]3007        {
[580]3008                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
3009                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
[486]3010        }
3011
3012        exporter->ExportMesh(&m);
[482]3013}
3014
3015
[503]3016void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
3017{
[551]3018        //TODO
[503]3019}
[442]3020
[574]3021
[584]3022void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3023                                                                                                   vector<MergeCandidate> &candidates)
[580]3024{
3025        // TODO
3026}
[574]3027
[580]3028
[503]3029/**************************************************************************/
3030/*                   VspBspViewCellsManager implementation                */
3031/**************************************************************************/
[482]3032
[503]3033
[574]3034VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
3035ViewCellsManager(), mVspBspTree(vspBspTree)
[442]3036{
[574]3037        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
[478]3038        mVspBspTree->SetViewCellsManager(this);
[590]3039        mVspBspTree->mViewCellsTree = mViewCellsTree;
[442]3040}
3041
[477]3042
[475]3043VspBspViewCellsManager::~VspBspViewCellsManager()
3044{
3045}
3046
[477]3047
[471]3048float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]3049{
[551]3050        if (0 && mVspBspTree->mUseAreaForPvs)
[547]3051                return GetArea(viewCell) / GetAccVcArea();
3052        else
3053                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]3054}
3055
[477]3056
[480]3057void VspBspViewCellsManager::CollectViewCells()
3058{
[581]3059        // view cells tree constructed
3060        if (!ViewCellsTreeConstructed())
3061        {
[590]3062                mVspBspTree->CollectViewCells(mViewCells, false);
[581]3063        }
3064        else
[664]3065        {       // we can use the view cells tree hierarchy to get the right set
[600]3066                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
[581]3067        }
[480]3068}
3069
3070
[442]3071bool VspBspViewCellsManager::ViewCellsConstructed() const
3072{
3073        return mVspBspTree->GetRoot() != NULL;
3074}
3075
[462]3076
[442]3077ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3078{
3079        return new BspViewCell(mesh);
3080}
3081
[569]3082
[574]3083int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[600]3084                                                                                                 const VssRayContainer &rays)
[442]3085{
[710]3086        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
3087
[503]3088        // if view cells were already constructed
3089        if (ViewCellsConstructed())
3090                return 0;
[442]3091
[503]3092        int sampleContributions = 0;
3093
3094        VssRayContainer sampleRays;
3095
[574]3096        int limit = min (mInitialSamples, (int)rays.size());
[503]3097
[469]3098        VssRayContainer constructionRays;
3099        VssRayContainer savedRays;
[442]3100
[660]3101        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
[664]3102                  << ", actual rays: " << (int)rays.size() << endl;
[587]3103
[574]3104        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
[487]3105
[574]3106        Debug << "initial rays: " << (int)constructionRays.size() << endl;
[508]3107        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]3108
[564]3109
[666]3110        //TODO: remove
[667]3111        if (1)
3112                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[666]3113        else
[667]3114                mVspBspTree->Construct(rays, &mViewSpaceBox);
3115
[490]3116        // collapse invalid regions
[491]3117        cout << "collapsing invalid tree regions ... ";
[495]3118        long startTime = GetTime();
[503]3119        int collapsedLeaves = mVspBspTree->CollapseTree();
[587]3120        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
3121                  << " seconds" << endl;
3122
[495]3123    cout << "finished" << endl;
[503]3124
[660]3125        // -- stats
3126        Debug << mVspBspTree->GetStatistics() << endl;
3127
[480]3128        ResetViewCells();
[660]3129        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[503]3130
[491]3131
[495]3132        startTime = GetTime();
[503]3133
[491]3134        cout << "Computing remaining ray contributions ... ";
[605]3135
[469]3136        // recast rest of rays
[605]3137        if (SAMPLE_AFTER_SUBDIVISION)
3138                ComputeSampleContributions(savedRays, true, false);
[491]3139        cout << "finished" << endl;
3140
[503]3141        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]3142                  << " secs" << endl;
[442]3143
[485]3144        cout << "construction finished" << endl;
[503]3145
[719]3146        // real meshes are contructed at this stage
3147        if (0)
3148        {
3149                cout << "finalizing view cells ... ";
3150                FinalizeViewCells(true);
3151                cout << "finished" << endl;
3152        }
3153
[442]3154        return sampleContributions;
3155}
3156
[489]3157
[503]3158void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
3159                                                                                        const ObjectContainer &objects)
[475]3160{
[442]3161    int vcSize = 0;
3162        int pvsSize = 0;
3163
[650]3164        //-- merge view cells
3165        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
3166        long startTime = GetTime();
3167
3168
[597]3169        if (mMergeViewCells)
3170        {
3171                // TODO: should be done BEFORE the ray casting
[710]3172                // compute tree by merging the nodes based on cost heuristics
[650]3173                mViewCellsTree->ConstructMergeTree(rays, objects);
3174        }
3175        else
3176        {
[710]3177                // compute tree by merging the nodes of the spatial hierarchy
3178                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
3179                mViewCellsTree->SetRoot(root);
[650]3180        }
[442]3181
[666]3182        if (1)
3183        {
3184                char mstats[100];
3185                environment->GetStringValue("ViewCells.mergeStats", mstats);
3186                mViewCellsTree->ExportStats(mstats);
3187        }
[485]3188
[650]3189        //-- stats and visualizations
3190        cout << "finished merging" << endl;
3191        cout << "merged view cells in "
3192                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[503]3193
[650]3194        Debug << "Postprocessing: Merged view cells in "
3195                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
3196       
3197
[600]3198        int savedColorCode = mColorCode;
3199       
[660]3200        // get currently active view cell set
3201        ResetViewCells();
3202        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
3203
[485]3204        //BspLeaf::NewMail();
[667]3205        if (1) // export merged view cells
[483]3206        {
[600]3207                mColorCode = 0;
[485]3208                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[660]3209               
[485]3210                cout << "exporting view cells after merge ... ";
3211
3212                if (exporter)
[483]3213                {
[600]3214                        if (0)
3215                                exporter->SetWireframe();
3216                        else
3217                                exporter->SetFilled();
3218
3219                        ExportViewCellsForViz(exporter);
3220
[485]3221                        if (mExportGeometry)
[483]3222                        {
[485]3223                                Material m;
3224                                m.mDiffuseColor = RgbColor(0, 1, 0);
3225                                exporter->SetForcedMaterial(m);
3226                                exporter->SetFilled();
[442]3227
[485]3228                                exporter->ExportGeometry(objects);
[442]3229                        }
[485]3230
[600]3231                        delete exporter;
3232                }
3233                cout << "finished" << endl;
3234        }
3235
[667]3236        if (1) // export merged view cells using pvs coding
[600]3237        {
3238                mColorCode = 1;
3239
3240                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
3241       
3242                cout << "exporting view cells after merge (pvs size) ... ";     
3243
3244                if (exporter)
3245                {
[598]3246                        if (0)
3247                                exporter->SetWireframe();
3248                        else
3249                                exporter->SetFilled();
3250
3251                        ExportViewCellsForViz(exporter);
3252
[600]3253                        if (mExportGeometry)
3254                        {
3255                                Material m;
3256                                m.mDiffuseColor = RgbColor(0, 1, 0);
3257                                exporter->SetForcedMaterial(m);
3258                                exporter->SetFilled();
3259
3260                                exporter->ExportGeometry(objects);
3261                        }
3262
[485]3263                        delete exporter;
[442]3264                }
[485]3265                cout << "finished" << endl;
[442]3266        }
[600]3267
3268        mColorCode = savedColorCode;
3269
[503]3270}
[475]3271
[503]3272
[609]3273bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
[607]3274{
[609]3275        return GetSpatialNode(viewCell) != NULL;
[607]3276}
3277
3278
[609]3279BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
[607]3280{
3281        if (!viewCell->IsLeaf())
3282        {
3283                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
3284
[609]3285                return bspVc->mLeaf;
3286        }
[607]3287        else
3288        {
3289                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
3290
3291                // cannot be node of binary tree
3292                if (interior->mChildren.size() != 2)
[609]3293                        return NULL;
[607]3294
3295                ViewCell *left = interior->mChildren[0];
3296                ViewCell *right = interior->mChildren[1];
3297
[609]3298                BspNode *leftNode = GetSpatialNode(left);
3299                BspNode *rightNode = GetSpatialNode(right);
[607]3300
[609]3301                if (leftNode && rightNode && leftNode->IsSibling(rightNode))
[607]3302                {
[609]3303                        return leftNode->GetParent();
[607]3304                }
[609]3305        }
[607]3306
[609]3307        return NULL;
[607]3308}
3309
3310
[564]3311void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
3312                                                                                         const ObjectContainer &objects)
[503]3313{
[485]3314        Debug << "render time before refine:" << endl;
3315        mRenderer->RenderScene();
[503]3316        SimulationStatistics ss;
[485]3317        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
3318    Debug << ss << endl;
3319
[489]3320        cout << "Refining the merged view cells ... ";
[503]3321        long startTime = GetTime();
[485]3322
3323        // refining the merged view cells
[580]3324        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
[485]3325
[442]3326        //-- stats and visualizations
3327        cout << "finished" << endl;
[485]3328        cout << "refined " << refined << " view cells in "
[442]3329                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
3330
[485]3331        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]3332                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]3333}
[495]3334
[517]3335
[503]3336int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
3337                                                                                const VssRayContainer &rays)
3338{
3339        if (!ViewCellsConstructed())
3340        {
[517]3341                Debug << "postprocess error: no view cells constructed" << endl;
[503]3342                return 0;
3343        }
[520]3344
[564]3345
[609]3346        // view cells already finished before post processing step
3347        // (i.e. because they were loaded)
[520]3348        if (mViewCellsFinished)
[542]3349        {
[551]3350                FinalizeViewCells(true);
[542]3351                EvaluateViewCellsStats();
[577]3352
[517]3353                return 0;
[542]3354        }
[448]3355
[710]3356        // check if new view cells turned invalid
3357        int minPvs, maxPvs;
[564]3358
[710]3359        if (0)
3360        {
3361                minPvs = mMinPvsSize;
3362                maxPvs = mMaxPvsSize;
3363        }
3364        else
3365        {
3366                minPvs = mPruneEmptyViewCells ? 1 : 0;
3367                maxPvs = mMaxPvsSize;
3368        }
[720]3369
[710]3370        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3371        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3372       
3373        SetValidity(minPvs, maxPvs);
3374
[574]3375        // update valid view space according to valid view cells
[720]3376        if (0) mVspBspTree->ValidateTree();
[542]3377
[720]3378        // area has to be recomputed
[574]3379        mTotalAreaValid = false;
[517]3380        VssRayContainer postProcessRays;
[605]3381        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3382
[517]3383        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]3384
[517]3385
[552]3386        // should maybe be done here to allow merge working with area or volume
3387        // and to correct the rendering statistics
[719]3388        if (0) FinalizeViewCells(false);
[720]3389               
[597]3390        //-- merge the individual view cells
3391        MergeViewCells(postProcessRays, objects);
[591]3392       
[720]3393
3394        // only for debugging purpose: test if the subdivision is valid
[693]3395        TestSubdivision();
3396
[597]3397        //-- refines the merged view cells
[720]3398        if (0) RefineViewCells(postProcessRays, objects);
[568]3399
[719]3400       
[660]3401        //-- render simulation after merge + refine
[605]3402        cout << "\nevaluating bsp view cells render time before compress ... ";
3403        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
3404        SimulationStatistics ss;
3405        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[600]3406 
[580]3407
[605]3408        cout << " finished" << endl;
3409        cout << ss << endl;
3410        Debug << ss << endl;
[600]3411
3412
3413        //-- compression
3414        if (ViewCellsTreeConstructed() && mCompressViewCells)
3415        {
3416                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3417                Debug << "number of entries before compress: " << pvsEntries << endl;
3418
3419                mViewCellsTree->CompressViewCellsPvs();
3420
3421                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3422                Debug << "number of entries after compress: " << pvsEntries << endl;
3423        }
3424
[660]3425
[517]3426        // collapse sibling leaves that share the same view cell
[586]3427        if (0)
3428                mVspBspTree->CollapseTree();
3429
[574]3430        // recompute view cell list and statistics
[520]3431        ResetViewCells();
3432
[719]3433        // compute final meshes and volume / area
3434        if (1) FinalizeViewCells(true);
[517]3435
[719]3436
[508]3437        // write view cells to disc
3438        if (mExportViewCells)
3439        {
[517]3440                char buff[100];
3441                environment->GetStringValue("ViewCells.filename", buff);
3442                string vcFilename(buff);
3443
3444                ExportViewCells(buff);
[508]3445        }
[503]3446
3447        return 0;
[442]3448}
3449
[490]3450
[442]3451int VspBspViewCellsManager::GetType() const
3452{
3453        return VSP_BSP;
3454}
3455
3456
[650]3457ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[609]3458{
[650]3459        if (root->IsLeaf())
3460        {
3461                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
[610]3462
[650]3463                viewCell->SetMergeCost(0.0f);
[649]3464
[650]3465                return viewCell;
3466        }
3467       
3468        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3469        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3470               
3471        float mergeCost = 1.0f / (float)root->mTimeStamp;
3472        //Debug << "timestamp: " << root->mTimeStamp;
3473        //Debug << "merge cost: " << mergeCost << endl;
[610]3474
[650]3475        viewCellInterior->SetMergeCost(mergeCost);
[610]3476
[650]3477        float volume = 0;
3478       
3479        BspNode *front = interior->GetFront();
3480        BspNode *back = interior->GetBack();
[649]3481
[650]3482        // recursivly compute child hierarchies
3483        ViewCell *backVc = ConstructSpatialMergeTree(back);
3484        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]3485
[650]3486        viewCellInterior->SetupChildLink(frontVc);
3487        viewCellInterior->SetupChildLink(backVc);
3488
3489
3490        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
3491        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
3492
3493        volume += backVc->GetVolume();
3494        volume += frontVc->GetVolume();
3495
3496        viewCellInterior->SetVolume(volume);
3497
3498        return viewCellInterior;
[609]3499}
3500
3501
[490]3502bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
3503{
3504        if (!ViewCellsConstructed())
3505                return ViewCellsManager::GetViewPoint(viewPoint);
3506
3507        // TODO: set reasonable limit
3508        const int limit = 20;
3509
3510        for (int i = 0; i < limit; ++ i)
3511        {
[542]3512                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]3513                if (mVspBspTree->ViewPointValid(viewPoint))
3514                {
3515                        return true;
3516                }
3517        }
3518        Debug << "failed to find valid view point, taking " << viewPoint << endl;
3519        return false;
3520}
3521
3522
3523bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
3524{
[569]3525  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
3526  // validy update in preprocessor for all managers)
3527  return ViewCellsManager::ViewPointValid(viewPoint);
[570]3528
[569]3529  //    return mViewSpaceBox.IsInside(viewPoint) &&
3530  //               mVspBspTree->ViewPointValid(viewPoint);
[490]3531}
3532
3533
[442]3534void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]3535                                                                           const VssRayContainer &sampleRays)
[442]3536{
3537        if (!ViewCellsConstructed())
3538                return;
3539
[485]3540        VssRayContainer visRays;
3541        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]3542
[600]3543       
[651]3544        if (1) // export view cells
[612]3545        {       // hack pvs
[600]3546                int savedColorCode = mColorCode;
[651]3547                mColorCode = 0;
[712]3548                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
[600]3549               
[442]3550                if (exporter)
3551                {
[580]3552                        cout << "exporting view cells after post process ... ";
3553
[600]3554                        if (0)
[542]3555                        {
3556                                exporter->SetWireframe();
3557                                exporter->ExportBox(mViewSpaceBox);
3558                                exporter->SetFilled();
3559                        }
3560
[485]3561                        if (mExportGeometry)
[542]3562                        {
[485]3563                                exporter->ExportGeometry(objects);
[542]3564                        }
[489]3565
3566                        // export rays
[490]3567                        if (mExportRays)
[489]3568                        {
[490]3569                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
3570                        }
[564]3571
[508]3572                        ExportViewCellsForViz(exporter);
[442]3573                        delete exporter;
[580]3574                        cout << "finished" << endl;
[442]3575                }
[600]3576
3577                mColorCode = savedColorCode;
[557]3578        }
[503]3579
[600]3580        if (0)
[577]3581        {
3582                cout << "exporting depth map ... ";
3583
3584                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
3585                if (exporter)
3586                {
3587                        if (1)
3588                        {
3589                                exporter->SetWireframe();
3590                                exporter->ExportBox(mViewSpaceBox);
3591                                exporter->SetFilled();
3592                        }
3593
3594                        if (mExportGeometry)
3595                        {
3596                                exporter->ExportGeometry(objects);
3597                        }
3598
3599                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
3600
3601                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
3602
3603                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
3604                        {
[582]3605                                ViewCell *vc = *vit;
[577]3606
[580]3607                                ViewCellContainer leaves;
3608                                mViewCellsTree->CollectLeaves(vc, leaves);
[577]3609
[580]3610                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3611
3612                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
[577]3613                                {
[580]3614                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
[577]3615
3616                                        Material m;
3617
3618                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
3619                                        m.mDiffuseColor.r = relDepth;
3620                                        m.mDiffuseColor.g = 0.0f;
3621                                        m.mDiffuseColor.b = 1.0f - relDepth;
3622
3623                    exporter->SetForcedMaterial(m);
3624                               
3625
3626                                        BspNodeGeometry geom;
3627                                        mVspBspTree->ConstructGeometry(leaf, geom);
[678]3628                                        exporter->ExportPolygons(geom.GetPolys());
[577]3629                                }
3630                        }
3631
3632                        delete exporter;
3633                }
3634
3635
3636                cout << "finished" << endl;
3637        }
3638
[442]3639        //-- visualization of the BSP splits
3640        bool exportSplits = false;
[489]3641        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]3642
[442]3643        if (exportSplits)
3644        {
3645                cout << "exporting splits ... ";
[485]3646                ExportSplits(objects, visRays);
[442]3647                cout << "finished" << endl;
3648        }
3649
[542]3650        //-- export single view cells
[485]3651        ExportBspPvs(objects, visRays);
[442]3652}
3653
[503]3654
[485]3655void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3656                                                                                  const VssRayContainer &rays)
[442]3657{
3658        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3659
[503]3660        if (exporter)
3661        {
3662                Material m;
[442]3663                m.mDiffuseColor = RgbColor(1, 0, 0);
3664                exporter->SetForcedMaterial(m);
3665                exporter->SetWireframe();
[503]3666
[448]3667                exporter->ExportBspSplits(*mVspBspTree, true);
[442]3668
3669                // take forced material, else big scenes cannot be viewed
3670                m.mDiffuseColor = RgbColor(0, 1, 0);
3671                exporter->SetForcedMaterial(m);
3672                exporter->SetFilled();
3673
3674                exporter->ResetForcedMaterial();
[503]3675
[442]3676                // export rays
[485]3677                if (mExportRays)
3678                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]3679
[485]3680                if (mExportGeometry)
[442]3681                        exporter->ExportGeometry(objects);
3682
3683                delete exporter;
3684        }
3685}
3686
[503]3687
[485]3688void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3689                                                                                  const VssRayContainer &rays)
[442]3690{
[639]3691        const int leafOut = 20;
[503]3692
[442]3693        ViewCell::NewMail();
[503]3694
[639]3695        cout << "visualization using " << (int)rays.size() << " samples" << endl;
3696        Debug << "visualization using " << (int)rays.size() << " samples" << endl;
[475]3697        Debug << "\nOutput view cells: " << endl;
[503]3698
[694]3699        const bool sortViewCells = true;
3700
[485]3701        // sort view cells to visualize the largest view cells
[694]3702        if (sortViewCells)
[587]3703                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
[639]3704       
[503]3705        int limit = min(leafOut, (int)mViewCells.size());
[483]3706
[639]3707        int raysOut = 0;
[587]3708
[485]3709        //-- some rays for output
[478]3710        for (int i = 0; i < limit; ++ i)
[442]3711        {
[478]3712                cout << "creating output for view cell " << i << " ... ";
[503]3713
[582]3714                ViewCell *vc;
[574]3715       
[694]3716                if (sortViewCells) // largest view cell pvs first
[582]3717                        vc = mViewCells[i];
[574]3718                else
[639]3719                        vc = mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
[442]3720
[639]3721                //bspLeaves[j]->Mail();
3722                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3723                Exporter *exporter = Exporter::GetExporter(s);
3724               
3725                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc) << endl;
[587]3726
[639]3727                if (1 || mExportRays)
[442]3728                {
[694]3729                        // output rays stored with the view cells during subdivision
[643]3730                        if (0)
[442]3731                        {
[639]3732                                VssRayContainer vcRays;
3733                VssRayContainer collectRays;
3734
3735                                raysOut = min((int)rays.size(), 100);
3736
3737                                // collect intial view cells
3738                                ViewCellContainer leaves;
3739                                mViewCellsTree->CollectLeaves(vc, leaves);
3740
3741                                ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3742       
3743                                for (vit = leaves.begin(); vit != vit_end; ++ vit)
[574]3744                                {
[639]3745                                        BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaf;
3746                               
3747                                        VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
[587]3748
[639]3749                                        for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
3750                                        {
3751                                                collectRays.push_back(*rit);
3752                                        }
[574]3753                                }
[639]3754
3755                                VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3756
3757                                for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3758                                {
3759                                        float p = RandomValue(0.0f, (float)collectRays.size());
3760                       
3761                                        if (p < raysOut)
3762                                                vcRays.push_back(*rit);
3763                                }
3764                                //-- export rays piercing this view cell
3765                                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[442]3766                        }
[651]3767               
[694]3768                        // associate new rays with output view cell
[643]3769                        if (1)
[639]3770                        {
3771                                VssRayContainer vcRays;
3772                                raysOut = min((int)rays.size(), mVisualizationSamples);
3773                                // check whether we can add the current ray to the output rays
3774                                for (int k = 0; k < raysOut; ++ k)
3775                                {
3776                                        VssRay *ray = rays[k];
3777                                        for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3778                                        {
3779                                                ViewCell *rayvc = ray->mViewCells[j];
3780       
3781                                                if (rayvc == vc)
3782                                                        vcRays.push_back(ray);
3783                                        }
3784                                }       
3785                               
3786                                //-- export rays piercing this view cell
3787                                exporter->ExportRays(vcRays, RgbColor(1, 1, 0));
3788                        }
3789
[442]3790                }
[639]3791               
[574]3792
[478]3793                exporter->SetWireframe();
[442]3794
[478]3795                Material m;//= RandomMaterial();
3796                m.mDiffuseColor = RgbColor(0, 1, 0);
3797                exporter->SetForcedMaterial(m);
[442]3798
[580]3799                ExportViewCellGeometry(exporter, vc);
[639]3800       
3801                exporter->SetFilled();
[503]3802
[639]3803
[574]3804                if (1)
3805                {
[639]3806                        ObjectPvsMap::const_iterator oit,
3807                                oit_end = vc->GetPvs().mEntries.end();
[483]3808
[580]3809
[639]3810                        exporter->SetFilled();
[580]3811
[639]3812                        Intersectable::NewMail();
[574]3813       
[639]3814                        // output PVS of view cell
3815                        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
3816                        {               
3817                                Intersectable *intersect = (*oit).first;
[442]3818
[639]3819                                if (!intersect->Mailed())
3820                                {
[643]3821                                        m = RandomMaterial();
3822                                        exporter->SetForcedMaterial(m);
[442]3823
[639]3824                                        exporter->ExportIntersectable(intersect);
3825                                        intersect->Mail();
3826                                }
[503]3827                        }
[442]3828                }
[639]3829                else
3830                {
[643]3831                        m.mDiffuseColor = RgbColor(1, 0, 0);
3832                        exporter->SetForcedMaterial(m);
3833
[639]3834                        exporter->ExportGeometry(objects);
3835                }
[503]3836
[478]3837                DEL_PTR(exporter);
3838                cout << "finished" << endl;
[442]3839        }
[475]3840
3841        Debug << endl;
[442]3842}
3843
3844
[697]3845int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const
3846{
3847        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
3848}
3849
3850
[469]3851int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3852                                                                                        const Vector3 &termination,
3853                                                                                        ViewCellContainer &viewcells)
[466]3854{
[469]3855        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]3856}
[482]3857
3858
[503]3859void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]3860                                                                                 ViewCell *vc) const
3861{
[564]3862        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[503]3863
[482]3864        float importance = 0;
[564]3865        static Material m;
3866
[482]3867        switch (mColorCode)
3868        {
[564]3869        case 0: // Random
3870                {
3871                        if (vcValid)
3872                        {
[598]3873                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3874                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3875                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
[564]3876                        }
3877                        else
3878                        {
3879                                m.mDiffuseColor.r = 0.0f;
3880                                m.mDiffuseColor.g = 1.0f;
3881                                m.mDiffuseColor.b = 0.0f;
3882                        }
[591]3883
3884                        exporter->SetForcedMaterial(m);
3885                        return;
[564]3886                }
[591]3887               
[482]3888        case 1: // pvs
3889                {
[503]3890                        importance = (float)vc->GetPvs().GetSize() /
[660]3891                                (float)mCurrentViewCellsStats.maxPvs;
[570]3892
[482]3893                }
3894                break;
3895        case 2: // merges
3896                {
[580]3897            int lSize = mViewCellsTree->GetSize(vc);
[660]3898                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]3899                }
3900                break;
3901        case 3: // merge tree differene
3902                {
[503]3903                        importance = (float)GetMaxTreeDiff(vc) /
[482]3904                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]3905
[482]3906                }
3907                break;
3908        default:
3909                break;
3910        }
3911
[564]3912        // special color code for invalid view cells
[482]3913        m.mDiffuseColor.r = importance;
3914        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[564]3915        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[547]3916
[482]3917        //Debug << "importance: " << importance << endl;
3918        exporter->SetForcedMaterial(m);
3919}
3920
3921
[580]3922void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3923                                                    ViewCell *vc,
[660]3924                                                                                                        const Plane3 *clipPlane) const
[482]3925{
[542]3926        if (vc->GetMesh())
[503]3927        {
3928                exporter->ExportMesh(vc->GetMesh());
[590]3929       
[503]3930                return;
3931        }
3932
[591]3933       
[660]3934        if (clipPlane)
[591]3935        {
3936                ViewCellContainer leaves;
3937                mViewCellsTree->CollectLeaves(vc, leaves);
3938                ViewCellContainer::const_iterator it, it_end = leaves.end();
3939
3940                for (it = leaves.begin(); it != it_end; ++ it)
3941                {
3942                        BspNodeGeometry geom;
3943
3944                        BspNodeGeometry front;
3945                        BspNodeGeometry back;
3946
3947                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3948                        mVspBspTree->ConstructGeometry(leaf, geom);
3949
[710]3950                        const float eps = 0.00000001f;
3951                        const int cf = geom.Side(*clipPlane, eps);
[682]3952
[710]3953                        if (cf == -1)
[682]3954                        {
3955                                exporter->ExportPolygons(geom.GetPolys());
3956                        }
[710]3957                        else if (cf == 0)
[684]3958                        {
[682]3959                                geom.SplitGeometry(front,
3960                                                                   back,
3961                                                                   *clipPlane,
3962                                                                   mViewSpaceBox,
[710]3963                                                                   eps);
[682]3964       
[694]3965                                //Debug << "geo size: " << geom.Size() << endl;
3966                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
[683]3967                                if (back.Valid())
3968                                {
[682]3969                                        exporter->ExportPolygons(back.GetPolys());
[708]3970                                }                       
[684]3971                        }
[591]3972                }
3973        }
3974        else
3975        {
3976                BspNodeGeometry geom;
3977                mVspBspTree->ConstructGeometry(vc, geom);
3978                       
[678]3979                exporter->ExportPolygons(geom.GetPolys());
[591]3980        }
[482]3981}
3982
3983
3984int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3985{
[580]3986        ViewCellContainer leaves;
3987        mViewCellsTree->CollectLeaves(vc, leaves);
[482]3988
3989        int maxDist = 0;
[580]3990       
[482]3991        // compute max height difference
[580]3992        for (int i = 0; i < (int)leaves.size(); ++ i)
3993                for (int j = 0; j < (int)leaves.size(); ++ j)
[482]3994        {
[580]3995                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
[482]3996
3997                if (i != j)
3998                {
[580]3999                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
[482]4000                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
4001                        if (dist > maxDist)
4002                                maxDist = dist;
4003                }
4004        }
[580]4005
[492]4006        return maxDist;
4007}
[482]4008
[492]4009
[569]4010ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
[492]4011{
[508]4012        if (!mVspBspTree)
4013                return NULL;
[572]4014
4015        if (!mViewSpaceBox.IsInside(point))
4016          return NULL;
4017
[508]4018        return mVspBspTree->GetViewCell(point);
[492]4019}
[503]4020
4021
4022void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
4023{
[726]4024        //if (vc->GetMesh()) delete vc->GetMesh();
[503]4025        BspNodeGeometry geom;
[590]4026
4027        mVspBspTree->ConstructGeometry(vc, geom);
[582]4028       
[503]4029        Mesh *mesh = new Mesh();
4030        geom.AddToMesh(*mesh);
4031        vc->SetMesh(mesh);
[726]4032        // put mesh into mesh container so we can savely delete it
[503]4033        mMeshContainer.push_back(mesh);
4034}
[508]4035
4036
[577]4037ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
4038                                                                                                  ObjectContainer *objects)
[508]4039{
4040        ViewCellsParser parser;
[564]4041
[577]4042        ViewCellsManager *vm = NULL;
[564]4043
[577]4044        if (parser.ParseFile(filename, &vm, objects))
4045        {
[590]4046                //vm->PrepareLoadedViewCells();
[577]4047                vm->ResetViewCells();
[564]4048
[577]4049                vm->mViewCellsFinished = true;
4050                vm->mMaxPvsSize = (int)objects->size();
[517]4051
[719]4052                // create the meshes and compute volumes
[577]4053                vm->FinalizeViewCells(true);
[564]4054
[685]4055                vm->mViewCellsTree->AssignRandomColors();
[577]4056                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
4057        }
4058        else
4059        {
4060                Debug << "failed loading view cells" << endl;
4061                DEL_PTR(vm);
4062        }
4063
4064        return vm;
[508]4065}
4066
4067
4068inline bool ilt(Intersectable *obj1, Intersectable *obj2)
4069{
4070        return obj1->mId < obj2->mId;
4071}
4072
4073
4074bool VspBspViewCellsManager::ExportViewCells(const string filename)
4075{
[564]4076        cout << "exporting view cells to xml ... ";
[508]4077        std::ofstream stream;
4078
[577]4079        // for output we need unique ids for each view cell
[590]4080        CreateUniqueViewCellIds();
[508]4081
4082        stream.open(filename.c_str());
4083        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
4084        stream << "<Visibility_Solution>" << endl;
[564]4085
[577]4086        //-- the view space bounding box
4087        stream << "<ViewSpaceBox"
4088                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
4089                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
4090
4091        //-- the type of the view cells hierarchy
4092        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
4093
[508]4094        //-- load the view cells itself, i.e., the ids and the pvs
4095        stream << "<ViewCells>" << endl;
[610]4096       
4097#if 0
4098       
[508]4099        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[610]4100               
[508]4101        for (it = mViewCells.begin(); it != it_end; ++ it)
4102                ExportViewCell(*it, stream);
[610]4103#else
4104        mViewCellsTree->Export(stream);
4105#endif
[564]4106
[508]4107        stream << "</ViewCells>" << endl;
[564]4108
[508]4109        //-- load the hierarchy
[590]4110        stream << "<Hierarchy>" << endl;
[508]4111        mVspBspTree->Export(stream);
[590]4112        stream << endl << "</Hierarchy>" << endl;
[564]4113
[508]4114        stream << "</Visibility_Solution>" << endl;
4115        stream.close();
4116
4117        cout << "finished" << endl;
4118
4119        return true;
[532]4120}
4121
4122
4123int VspBspViewCellsManager::CastBeam(Beam &beam)
4124{
[535]4125        return mVspBspTree->CastBeam(beam);
[532]4126}
[551]4127
4128
[587]4129void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
4130                                                                          const bool createMesh)
[551]4131{
4132        float area = 0;
4133        float volume = 0;
4134
[580]4135        ViewCellContainer leaves;
[582]4136        mViewCellsTree->CollectLeaves(viewCell, leaves);
[580]4137
4138        ViewCellContainer::const_iterator it, it_end = leaves.end();
4139
[693]4140    for (it = leaves.begin(); it != it_end; ++ it)
[551]4141        {
4142                BspNodeGeometry geom;
[580]4143                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
[551]4144                mVspBspTree->ConstructGeometry(leaf, geom);
4145
[719]4146                const float lVol = geom.GetVolume();
4147                const float lArea = geom.GetArea();
[693]4148
4149                //(*it)->SetVolume(vol);
4150                //(*it)->SetArea(area);
4151
4152                area += lArea;
4153                volume += lVol;
4154
4155        CreateMesh(*it);
[551]4156        }
4157
4158        viewCell->SetVolume(volume);
4159        viewCell->SetArea(area);
[563]4160}
[575]4161
4162
[693]4163void VspBspViewCellsManager::TestSubdivision()
4164{
4165        ViewCellContainer leaves;
4166        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
4167
4168        ViewCellContainer::const_iterator it, it_end = leaves.end();
4169
4170        const float vol = mViewSpaceBox.GetVolume();
4171        float subdivVol = 0;
4172        float newVol = 0;
4173
4174        for (it = leaves.begin(); it != it_end; ++ it)
4175        {
4176                BspNodeGeometry geom;
4177                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4178                mVspBspTree->ConstructGeometry(leaf, geom);
4179
4180                const float lVol = geom.GetVolume();
4181               
4182                newVol += lVol;
4183                subdivVol += (*it)->GetVolume();
[697]4184               
[704]4185                float thres = 0.9f;
[697]4186                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
4187                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]4188        }
4189       
4190        Debug << "exact volume: " << vol << endl;
4191        Debug << "subdivision volume: " << subdivVol << endl;
4192        Debug << "new volume: " << newVol << endl;
4193}
4194
4195
[577]4196void VspBspViewCellsManager::PrepareLoadedViewCells()
4197{
4198        // TODO: do I still need this here?
[590]4199        if (0)
[693]4200                mVspBspTree->RepairViewCellsLeafLists();
[577]4201}
[575]4202
[577]4203
[697]4204void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
4205{
4206        Exporter *exporter = Exporter::GetExporter("filter.x3d");
[580]4207
[704]4208        Vector3 bsize = mViewSpaceBox.Size();
4209        const Vector3 viewPoint(mViewSpaceBox.Center());
4210        const Vector3 width = Vector3(mFilterWidth);
4211       
4212        PrVs testPrVs;
4213       
[697]4214        if (exporter)
4215        {
4216                ViewCellContainer viewCells;
[704]4217       
4218        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
4219
4220                GetPrVS(viewPoint, testPrVs);
4221
[697]4222                exporter->SetWireframe();
4223
4224                exporter->SetForcedMaterial(RgbColor(1,1,1));
[704]4225                exporter->ExportBox(tbox);
[697]4226               
4227                exporter->SetFilled();
4228
[705]4229                exporter->SetForcedMaterial(RgbColor(0,1,0));
4230                ExportViewCellGeometry(exporter,  GetViewCell(viewPoint));
4231
4232                //exporter->ResetForcedMaterial();
4233                exporter->SetForcedMaterial(RgbColor(0,0,1));
[704]4234                ExportViewCellGeometry(exporter, testPrVs.mViewCell);
4235
4236        exporter->SetForcedMaterial(RgbColor(1,0,0));
[697]4237                exporter->ExportGeometry(objects);
4238
4239                delete exporter;
4240        }
4241}
4242
4243
[580]4244void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4245                                                                                                        vector<MergeCandidate> &candidates)
4246{       
4247        cout << "collecting merge candidates ... " << endl;
4248
4249        if (mUseRaysForMerge)
4250        {
4251                mVspBspTree->CollectMergeCandidates(rays, candidates);
4252        }
4253        else
4254        {
4255                vector<BspLeaf *> leaves;
4256                mVspBspTree->CollectLeaves(leaves);
[708]4257       
[580]4258                mVspBspTree->CollectMergeCandidates(leaves, candidates);
4259        }
4260
4261        cout << "fininshed collecting candidates" << endl;
4262}
4263
4264
[590]4265void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
4266{
4267        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
4268        for (it = mViewCells.begin(); it != it_end; ++ it)
4269        {
4270        }
4271}
[580]4272
4273//////////////////////////////////
[575]4274ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
4275{
4276        //TODO
4277        return NULL;// new VspBspViewCellsManager();
4278}
[580]4279
Note: See TracBrowser for help on using the repository browser.