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

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