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

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