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

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