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

Revision 666, 86.4 KB checked in by mattausch, 18 years ago (diff)

debug version for testing subdivision quality

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