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

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