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

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