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

Revision 884, 121.2 KB checked in by bittner, 18 years ago (diff)

Spatial visibility filter

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