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

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