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

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