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

Revision 1718, 146.9 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 ViewCellsManager::UpdatePvsForEvaluation()
2631{
2632        ObjectPvs objPvs;
2633        UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), objPvs);
2634}
2635
2636void ViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
2637{
2638        // terminate traversal
2639        if (root->IsLeaf())
2640        {
2641                //cout << "updating leaf" << endl;
2642                // we assume that pvs is explicitly stored in leaves
2643                pvs = root->GetPvs();
2644                UpdateScalarPvsSize(root, pvs.EvalPvsCost(), pvs.GetSize());
2645                return;
2646        }
2647
2648        //cout << "recursivly updating pvs" << endl;
2649
2650        ////////////////
2651        //-- interior node => propagate pvs up the tree
2652
2653        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
2654
2655        // reset interior pvs
2656        interior->GetPvs().Clear();
2657        // reset recursive pvs
2658        pvs.Clear();
2659
2660        // pvss of child nodes
2661        vector<ObjectPvs> pvsList;
2662        pvsList.resize((int)interior->mChildren.size());
2663
2664        ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
2665       
2666        int i = 0;
2667
2668        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ i)
2669        {
2670                //////////////////
2671                //-- recursivly compute child pvss
2672                UpdatePvsForEvaluation(*vit, pvsList[i]/*objPvs*/);
2673        }
2674
2675#if 1
2676        Intersectable::NewMail();
2677
2678        //-- faster way of computing pvs:
2679        //-- construct merged pvs by adding
2680        //-- and only those of the next pvs which were not mailed.
2681        //-- note: sumpdf is not correct!!
2682
2683        vector<ObjectPvs>::iterator oit = pvsList.begin();
2684
2685        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
2686        {
2687            ObjectPvsMap::iterator pit, pit_end = (*oit).mEntries.end();
2688       
2689                for (pit = (*oit).mEntries.begin(); pit != pit_end; ++ pit)
2690                {
2691                        Intersectable *intersect = (*pit).first;
2692
2693                        if (!intersect->Mailed())
2694                        {
2695                                pvs.AddSample(intersect, (*pit).second.mSumPdf);
2696                                intersect->Mail();
2697                        }
2698                }
2699        }
2700
2701        // store pvs in this node
2702        if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
2703        {
2704                interior->SetPvs(pvs);
2705        }
2706       
2707        // set new pvs size
2708        UpdateScalarPvsSize(interior, pvs.EvalPvsCost(), pvs.GetSize());
2709       
2710#else
2711        // really merge cells: slow put sumPdf is correct
2712        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2713        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
2714#endif
2715}
2716
2717
2718
2719/*******************************************************************/
2720/*               BspViewCellsManager implementation                */
2721/*******************************************************************/
2722
2723
2724BspViewCellsManager::BspViewCellsManager(ViewCellsTree *vcTree, BspTree *bspTree):
2725ViewCellsManager(vcTree), mBspTree(bspTree)
2726{
2727        Environment::GetSingleton()->GetIntValue("BspTree.Construction.samples", mInitialSamples);
2728
2729        mBspTree->SetViewCellsManager(this);
2730        mBspTree->SetViewCellsTree(mViewCellsTree);
2731}
2732
2733
2734bool BspViewCellsManager::ViewCellsConstructed() const
2735{
2736        return mBspTree->GetRoot() != NULL;
2737}
2738
2739
2740ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2741{
2742        return new BspViewCell(mesh);
2743}
2744
2745
2746int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2747                                                                                          const VssRayContainer &rays)
2748{
2749        // if view cells were already constructed, we can finish
2750        if (ViewCellsConstructed())
2751                return 0;
2752
2753        int sampleContributions = 0;
2754
2755        // construct view cells using the collected samples
2756        RayContainer constructionRays;
2757        VssRayContainer savedRays;
2758
2759        // choose a a number of rays based on the ratio of cast rays / requested rays
2760        const int limit = min(mInitialSamples, (int)rays.size());
2761        VssRayContainer::const_iterator it, it_end = rays.end();
2762
2763        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
2764
2765        for (it = rays.begin(); it != it_end; ++ it)
2766        {
2767                if (Random(1.0f) < prop)
2768                        constructionRays.push_back(new Ray(*(*it)));
2769                else
2770                        savedRays.push_back(*it);
2771        }
2772
2773    if (!mUsePredefinedViewCells)
2774        {
2775                // no view cells loaded
2776                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
2777                // collect final view cells
2778                mBspTree->CollectViewCells(mViewCells);
2779        }
2780        else
2781        {       
2782                // use predefined view cells geometry =>
2783                // contruct bsp hierarchy over them
2784                mBspTree->Construct(mViewCells);
2785        }
2786
2787        // destroy rays created only for construction
2788        CLEAR_CONTAINER(constructionRays);
2789
2790        Debug << mBspTree->GetStatistics() << endl;
2791        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
2792
2793        // recast rest of the rays
2794        if (SAMPLE_AFTER_SUBDIVISION)
2795                ComputeSampleContributions(savedRays, true, false);
2796
2797        // real meshes are contructed at this stage
2798        if (0)
2799        {
2800                cout << "finalizing view cells ... ";
2801                FinalizeViewCells(true);
2802                cout << "finished" << endl;     
2803        }
2804
2805        return sampleContributions;
2806}
2807
2808
2809void BspViewCellsManager::CollectViewCells()
2810{       
2811        if (!ViewCellsTreeConstructed())
2812        {       // view cells tree constructed 
2813                mBspTree->CollectViewCells(mViewCells);
2814        }
2815        else
2816        {       // we can use the view cells tree hierarchy to get the right set
2817                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
2818        }
2819}
2820
2821
2822float BspViewCellsManager::GetProbability(ViewCell *viewCell)
2823{
2824        if (1)
2825                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
2826        else
2827                // compute view cell area as subsititute for probability
2828                return GetArea(viewCell) / GetAccVcArea();
2829}
2830
2831
2832
2833int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
2834                                                                                 const Vector3 &termination,
2835                                                                                 ViewCellContainer &viewcells)
2836{
2837        return mBspTree->CastLineSegment(origin, termination, viewcells);
2838}
2839
2840
2841void ViewCellsManager::ExportMergedViewCells(const ObjectContainer &objects)
2842{
2843        // save color code
2844        const int savedColorCode = mColorCode;
2845
2846        // export merged view cells
2847        mColorCode = 0; // use random colors
2848
2849        Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
2850
2851        cout << "exporting view cells after merge ... ";
2852
2853        if (exporter)
2854        {
2855                if (mExportGeometry)
2856                {
2857                        exporter->ExportGeometry(objects);
2858                }
2859
2860                exporter->SetFilled();
2861                ExportViewCellsForViz(exporter, NULL, GetClipPlane());
2862
2863                delete exporter;
2864        }
2865        cout << "finished" << endl;
2866
2867        // export merged view cells using pvs color coding
2868        mColorCode = 1;
2869
2870        exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
2871        cout << "exporting view cells after merge (pvs size) ... ";     
2872
2873        if (exporter)
2874        {
2875                if (mExportGeometry)
2876                {
2877                        exporter->ExportGeometry(objects);
2878                }
2879
2880                exporter->SetFilled();
2881                ExportViewCellsForViz(exporter, NULL, GetClipPlane());
2882
2883                delete exporter;
2884        }
2885        cout << "finished" << endl;
2886       
2887        mColorCode = savedColorCode;
2888}
2889
2890
2891int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
2892                                                                         const VssRayContainer &rays)
2893{
2894        if (!ViewCellsConstructed())
2895        {
2896                Debug << "view cells not constructed" << endl;
2897                return 0;
2898        }
2899       
2900        // view cells already finished before post processing step,
2901        // i.e., because they were loaded from disc
2902        if (mViewCellsFinished)
2903        {
2904                FinalizeViewCells(true);
2905                EvaluateViewCellsStats();
2906
2907                return 0;
2908        }
2909
2910        //////////////////
2911        //-- merge leaves of the view cell hierarchy   
2912       
2913        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
2914        long startTime = GetTime();
2915       
2916        VssRayContainer postProcessRays;
2917        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2918
2919        if (mMergeViewCells)
2920        {
2921                cout << "constructing visibility based merge tree" << endl;
2922                mViewCellsTree->ConstructMergeTree(rays, objects);
2923        }
2924        else
2925        {
2926                cout << "constructing spatial merge tree" << endl;
2927                ViewCell *root;
2928                // the spatial merge tree is difficult to build for
2929                // this type of construction, as view cells cover several
2930                // leaves => create dummy tree which is only 2 levels deep
2931                if (mUsePredefinedViewCells)
2932                {
2933                        root = ConstructDummyMergeTree(mBspTree->GetRoot());
2934                }
2935                else
2936                {
2937                        // create spatial merge hierarchy
2938                        root = ConstructSpatialMergeTree(mBspTree->GetRoot());
2939                }
2940               
2941                mViewCellsTree->SetRoot(root);
2942
2943                // recompute pvs in the whole hierarchy
2944                ObjectPvs pvs;
2945                UpdatePvsForEvaluation(root, pvs);
2946        }
2947
2948        cout << "finished" << endl;
2949        cout << "merged view cells in "
2950                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
2951
2952        Debug << "Postprocessing: Merged view cells in "
2953                << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
2954
2955       
2956        ////////////////////////
2957        //-- visualization and statistics after merge
2958
2959        if (1)
2960        {
2961                char mstats[100];
2962                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
2963                mViewCellsTree->ExportStats(mstats);
2964        }
2965
2966        // recompute view cells and stats
2967        ResetViewCells();
2968        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
2969
2970        //  visualization of the view cells
2971        if (1) ExportMergedViewCells(objects);
2972
2973        // compute final meshes and volume / area
2974        if (1) FinalizeViewCells(true);
2975       
2976        return 0;
2977}
2978
2979
2980BspViewCellsManager::~BspViewCellsManager()
2981{
2982}
2983
2984
2985int BspViewCellsManager::GetType() const
2986{
2987        return BSP;
2988}
2989
2990
2991void BspViewCellsManager::Visualize(const ObjectContainer &objects,
2992                                                                        const VssRayContainer &sampleRays)
2993{
2994        if (!ViewCellsConstructed())
2995                return;
2996       
2997        const int savedColorCode = mColorCode;
2998       
2999        if (1) // export final view cells
3000        {
3001                mColorCode = 1; // hack color code
3002                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
3003       
3004                cout << "exporting view cells after merge (pvs size) ... ";     
3005
3006                if (exporter)
3007                {
3008                        if (mExportGeometry)
3009                        {
3010                                exporter->ExportGeometry(objects);
3011                        }
3012
3013                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
3014                        delete exporter;
3015                }
3016                cout << "finished" << endl;
3017        }
3018
3019        // reset color code
3020        mColorCode = savedColorCode;
3021
3022
3023        //////////////////
3024        //-- visualization of the BSP splits
3025
3026        bool exportSplits = false;
3027        Environment::GetSingleton()->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
3028
3029        if (exportSplits)
3030        {
3031                cout << "exporting splits ... ";
3032                ExportSplits(objects);
3033                cout << "finished" << endl;
3034        }
3035
3036        int leafOut;
3037        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
3038        const int raysOut = 100;
3039        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
3040}
3041
3042
3043void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
3044{
3045        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3046
3047        if (exporter)
3048        {
3049                //exporter->SetFilled();
3050                if (mExportGeometry)
3051                {
3052                        exporter->ExportGeometry(objects);
3053                }
3054
3055                Material m;
3056                m.mDiffuseColor = RgbColor(1, 0, 0);
3057                exporter->SetForcedMaterial(m);
3058                exporter->SetWireframe();
3059
3060                exporter->ExportBspSplits(*mBspTree, true);
3061
3062                // NOTE: take forced material, else big scenes cannot be viewed
3063                m.mDiffuseColor = RgbColor(0, 1, 0);
3064                exporter->SetForcedMaterial(m);
3065                //exporter->ResetForcedMaterial();
3066
3067                delete exporter;
3068        }
3069}
3070
3071
3072void BspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
3073                                                                                                const int maxViewCells,
3074                                                                                                const bool sortViewCells,
3075                                                                                                const bool exportPvs,
3076                                                                                                const bool exportRays,
3077                                                                                                const int maxRays,
3078                                                                                                const string prefix,
3079                                                                                                VssRayContainer *visRays)
3080{
3081        if (sortViewCells)
3082        {       // sort view cells to visualize the largest view cells
3083                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
3084        }
3085
3086        //////////
3087        //-- some view cells for output
3088
3089        ViewCell::NewMail();
3090        const int limit = min(maxViewCells, (int)mViewCells.size());
3091       
3092        for (int i = 0; i < limit; ++ i)
3093        {
3094                const int idx = sortViewCells ? (int)RandomValue(0, (float)mViewCells.size() - 0.5f) : i;
3095                ViewCell *vc = mViewCells[idx];
3096
3097                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
3098                        continue;
3099
3100                vc->Mail();
3101
3102                ObjectPvs pvs;
3103                mViewCellsTree->GetPvs(vc, pvs);
3104
3105                char s[64]; sprintf(s, "%sviewcell-%04d.wrl", prefix.c_str(), i);
3106                Exporter *exporter = Exporter::GetExporter(s);
3107               
3108                cout << "view cell " << idx << ": pvs cost=" << (int)mViewCellsTree->GetPvsCost(vc) << endl;
3109
3110                if (exportRays)
3111                {
3112                        ////////////
3113                        //-- export rays piercing this view cell
3114
3115                        // use rays stored with the view cells
3116                        VssRayContainer vcRays, vcRays2, vcRays3;
3117            VssRayContainer collectRays;
3118
3119                        // collect initial view cells
3120                        ViewCellContainer leaves;
3121                        mViewCellsTree->CollectLeaves(vc, leaves);
3122
3123                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3124                for (vit = leaves.begin(); vit != vit_end; ++ vit)
3125                        {       
3126                                // prepare some rays for output
3127                                VssRayContainer::const_iterator rit, rit_end = (*vit)->GetOrCreateRays()->end();
3128                                for (rit = (*vit)->GetOrCreateRays()->begin(); rit != rit_end; ++ rit)
3129                                {
3130                                        collectRays.push_back(*rit);
3131                                }
3132                        }
3133
3134                        const int raysOut = min((int)collectRays.size(), maxRays);
3135
3136                        // prepare some rays for output
3137                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3138                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3139                        {
3140                                const float p = RandomValue(0.0f, (float)collectRays.size());
3141                                if (p < raysOut)
3142                                {
3143                                        if ((*rit)->mFlags & VssRay::BorderSample)
3144                                        {
3145                                                vcRays.push_back(*rit);
3146                                        }
3147                                        else if ((*rit)->mFlags & VssRay::ReverseSample)
3148                                                vcRays2.push_back(*rit);
3149                                        else
3150                                                vcRays3.push_back(*rit);
3151                                               
3152                                }
3153                        }
3154
3155                        exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
3156                        exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
3157                        exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
3158                }
3159               
3160                ////////////////
3161                //-- export view cell geometry
3162
3163                exporter->SetWireframe();
3164
3165                Material m;//= RandomMaterial();
3166                m.mDiffuseColor = RgbColor(0, 1, 0);
3167                exporter->SetForcedMaterial(m);
3168
3169                ExportViewCellGeometry(exporter, vc, NULL, NULL);
3170                exporter->SetFilled();
3171
3172                if (exportPvs)
3173                {
3174                        Intersectable::NewMail();
3175                        ObjectPvsMap::const_iterator oit, oit_end = pvs.mEntries.end();
3176                       
3177                        // output PVS of view cell
3178                        for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
3179                        {               
3180                                Intersectable *intersect = (*oit).first;
3181                               
3182                                if (!intersect->Mailed())
3183                                {
3184                                        intersect->Mail();
3185
3186                                        m = RandomMaterial();
3187                                        exporter->SetForcedMaterial(m);
3188                                        exporter->ExportIntersectable(intersect);
3189                                }
3190                        }
3191                        cout << endl;
3192                }
3193               
3194                DEL_PTR(exporter);
3195                cout << "finished" << endl;
3196        }
3197}
3198
3199
3200void BspViewCellsManager::TestSubdivision()
3201{
3202        ViewCellContainer leaves;
3203        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
3204
3205        ViewCellContainer::const_iterator it, it_end = leaves.end();
3206
3207        const float vol = mViewSpaceBox.GetVolume();
3208        float subdivVol = 0;
3209        float newVol = 0;
3210
3211        for (it = leaves.begin(); it != it_end; ++ it)
3212        {
3213                BspNodeGeometry geom;
3214                mBspTree->ConstructGeometry(*it, geom);
3215
3216                const float lVol = geom.GetVolume();
3217                newVol += lVol;
3218                subdivVol += (*it)->GetVolume();
3219
3220                const float thres = 0.9f;
3221                if ((lVol < ((*it)->GetVolume() * thres)) ||
3222                        (lVol * thres > ((*it)->GetVolume())))
3223                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
3224        }
3225       
3226        Debug << "exact volume: " << vol << endl;
3227        Debug << "subdivision volume: " << subdivVol << endl;
3228        Debug << "new volume: " << newVol << endl;
3229}
3230
3231
3232void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3233                                                                                                 ViewCell *vc,
3234                                                                                                 const AxisAlignedBox3 *sceneBox,
3235                                                                                                 const AxisAlignedPlane *clipPlane
3236                                                                                                 ) const
3237{
3238        if (clipPlane)
3239        {
3240                const Plane3 plane = clipPlane->GetPlane();
3241
3242                ViewCellContainer leaves;
3243                mViewCellsTree->CollectLeaves(vc, leaves);
3244                ViewCellContainer::const_iterator it, it_end = leaves.end();
3245
3246                for (it = leaves.begin(); it != it_end; ++ it)
3247                {
3248                        BspNodeGeometry geom;
3249                        BspNodeGeometry front;
3250                        BspNodeGeometry back;
3251
3252                        mBspTree->ConstructGeometry(*it, geom);
3253
3254                        const float eps = 0.0001f;
3255                        const int cf = geom.Side(plane, eps);
3256
3257                        if (cf == -1)
3258                        {
3259                                exporter->ExportPolygons(geom.GetPolys());
3260                        }
3261                        else if (cf == 0)
3262                        {
3263                                geom.SplitGeometry(front,
3264                                                                   back,
3265                                                                   plane,
3266                                                                   mViewSpaceBox,
3267                                                                   eps);
3268
3269                                if (back.Valid())
3270                                {
3271                                        exporter->ExportPolygons(back.GetPolys());
3272                                }                       
3273                        }
3274                }
3275        }
3276        else
3277        {
3278                // export mesh if available
3279                // TODO: some bug here?
3280                if (1 && vc->GetMesh())
3281                {
3282                        exporter->ExportMesh(vc->GetMesh());
3283                }
3284                else
3285                {
3286                        BspNodeGeometry geom;
3287                        mBspTree->ConstructGeometry(vc, geom);
3288                        exporter->ExportPolygons(geom.GetPolys());
3289                }
3290        }
3291}
3292
3293
3294void BspViewCellsManager::CreateMesh(ViewCell *vc)
3295{
3296        // note: should previous mesh be deleted (via mesh manager?)
3297        BspNodeGeometry geom;
3298        mBspTree->ConstructGeometry(vc, geom);
3299
3300        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
3301
3302        IncludeNodeGeomInMesh(geom, *mesh);
3303        vc->SetMesh(mesh);
3304}
3305
3306
3307void BspViewCellsManager::Finalize(ViewCell *viewCell,
3308                                                                   const bool createMesh)
3309{
3310        float area = 0;
3311        float volume = 0;
3312
3313        ViewCellContainer leaves;
3314        mViewCellsTree->CollectLeaves(viewCell, leaves);
3315
3316        ViewCellContainer::const_iterator it, it_end = leaves.end();
3317
3318    for (it = leaves.begin(); it != it_end; ++ it)
3319        {
3320                BspNodeGeometry geom;
3321
3322                mBspTree->ConstructGeometry(*it, geom);
3323
3324                const float lVol = geom.GetVolume();
3325                const float lArea = geom.GetArea();
3326
3327                area += lArea;
3328                volume += lVol;
3329       
3330                CreateMesh(*it);
3331        }
3332
3333        viewCell->SetVolume(volume);
3334        viewCell->SetArea(area);
3335}
3336
3337
3338ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
3339{
3340        if (!ViewCellsConstructed())
3341        {
3342                return NULL;
3343        }
3344        if (!mViewSpaceBox.IsInside(point))
3345        {
3346                return NULL;
3347        }
3348        return mBspTree->GetViewCell(point);
3349}
3350
3351
3352void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3353                                                                                                 vector<MergeCandidate> &candidates)
3354{
3355        cout << "collecting merge candidates ... " << endl;
3356
3357        if (mUseRaysForMerge)
3358        {
3359                mBspTree->CollectMergeCandidates(rays, candidates);
3360        }
3361        else
3362        {
3363                vector<BspLeaf *> leaves;
3364                mBspTree->CollectLeaves(leaves);
3365                mBspTree->CollectMergeCandidates(leaves, candidates);
3366        }
3367
3368        cout << "fininshed collecting candidates" << endl;
3369}
3370
3371
3372
3373bool BspViewCellsManager::ExportViewCells(const string filename,
3374                                                                                  const bool exportPvs,
3375                                                                                  const ObjectContainer &objects)
3376{
3377        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
3378        {
3379                return false;
3380        }
3381
3382        cout << "exporting view cells to xml ... ";
3383
3384        OUT_STREAM stream(filename.c_str());
3385
3386        // for output we need unique ids for each view cell
3387        CreateUniqueViewCellIds();
3388
3389        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3390        stream << "<VisibilitySolution>" << endl;
3391
3392        if (exportPvs)
3393        {
3394                //////////
3395                //-- export bounding boxes: they are used to identify the objects from the pvs and
3396                //-- assign them to the entities in the rendering engine
3397
3398                stream << "<BoundingBoxes>" << endl;
3399                ObjectContainer::const_iterator oit, oit_end = objects.end();
3400
3401                for (oit = objects.begin(); oit != oit_end; ++ oit)
3402                {
3403                        const AxisAlignedBox3 box = (*oit)->GetBox();
3404                       
3405                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
3406                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
3407                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
3408                }
3409
3410                stream << "</BoundingBoxes>" << endl;
3411        }
3412
3413        ///////////
3414        //-- export the view cells and the pvs
3415
3416        const int numViewCells = mCurrentViewCellsStats.viewCells;
3417        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
3418
3419        mViewCellsTree->Export(stream, exportPvs);
3420       
3421        stream << "</ViewCells>" << endl;
3422
3423        /////////////
3424        //-- export the view space hierarchy
3425        stream << "<ViewSpaceHierarchy type=\"bsp\""
3426                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3427                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
3428
3429        mBspTree->Export(stream);
3430
3431        // end tags
3432        stream << "</ViewSpaceHierarchy>" << endl;
3433        stream << "</VisibilitySolution>" << endl;
3434
3435        stream.close();
3436        cout << "finished" << endl;
3437
3438        return true;
3439}
3440
3441
3442ViewCell *BspViewCellsManager::ConstructDummyMergeTree(BspNode *root)
3443{
3444        ViewCellInterior *vcRoot = new ViewCellInterior();
3445               
3446        // evaluate merge cost for priority traversal
3447        const float mergeCost =  -(float)root->mTimeStamp;
3448        vcRoot->SetMergeCost(mergeCost);
3449
3450        float volume = 0;
3451        vector<BspLeaf *> leaves;
3452        mBspTree->CollectLeaves(leaves);
3453        vector<BspLeaf *>::const_iterator lit, lit_end = leaves.end();
3454        ViewCell::NewMail();
3455
3456        for (lit = leaves.begin(); lit != lit_end; ++ lit)
3457        {
3458                BspLeaf *leaf = *lit;
3459                ViewCell *vc = leaf->GetViewCell();
3460
3461                if (!vc->Mailed())
3462                {
3463                        vc->Mail();
3464                        vc->SetMergeCost(0.0f);
3465                        vcRoot->SetupChildLink(vc);
3466
3467                        volume += vc->GetVolume();
3468                        volume += vc->GetVolume();     
3469                        vcRoot->SetVolume(volume);
3470                }
3471        }
3472       
3473        return vcRoot;
3474}
3475
3476
3477ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
3478{
3479        // terminate recursion
3480        if (root->IsLeaf())
3481        {
3482                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
3483                leaf->GetViewCell()->SetMergeCost(0.0f);
3484                return leaf->GetViewCell();
3485        }
3486       
3487        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3488        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3489               
3490        // evaluate merge cost for priority traversal
3491        const float mergeCost = -(float)root->mTimeStamp;
3492        viewCellInterior->SetMergeCost(mergeCost);
3493
3494        float volume = 0;
3495       
3496        BspNode *front = interior->GetFront();
3497        BspNode *back = interior->GetBack();
3498
3499
3500        ////////////
3501        //-- recursivly compute child hierarchies
3502
3503        ViewCell *backVc = ConstructSpatialMergeTree(back);
3504        ViewCell *frontVc = ConstructSpatialMergeTree(front);
3505
3506        viewCellInterior->SetupChildLink(backVc);
3507        viewCellInterior->SetupChildLink(frontVc);
3508
3509        volume += backVc->GetVolume();
3510        volume += frontVc->GetVolume();
3511
3512        viewCellInterior->SetVolume(volume);
3513
3514        return viewCellInterior;
3515}
3516
3517
3518/************************************************************************/
3519/*                   KdViewCellsManager implementation                  */
3520/************************************************************************/
3521
3522
3523
3524KdViewCellsManager::KdViewCellsManager(ViewCellsTree *vcTree, KdTree *kdTree):
3525ViewCellsManager(vcTree), mKdTree(kdTree), mKdPvsDepth(100)
3526{
3527}
3528
3529
3530float KdViewCellsManager::GetProbability(ViewCell *viewCell)
3531{
3532        // compute view cell area / volume as subsititute for probability
3533        if (0)
3534                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
3535        else
3536                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
3537}
3538
3539
3540
3541
3542void KdViewCellsManager::CollectViewCells()
3543{
3544        //mKdTree->CollectViewCells(mViewCells); TODO
3545}
3546
3547
3548int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
3549                                                                  const VssRayContainer &rays)
3550{
3551        // if view cells already constructed
3552        if (ViewCellsConstructed())
3553                return 0;
3554
3555        mKdTree->Construct();
3556
3557        mTotalAreaValid = false;
3558        // create the view cells
3559        mKdTree->CreateAndCollectViewCells(mViewCells);
3560        // cast rays
3561        ComputeSampleContributions(rays, true, false);
3562
3563        EvaluateViewCellsStats();
3564        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
3565
3566        return 0;
3567}
3568
3569
3570bool KdViewCellsManager::ViewCellsConstructed() const
3571{
3572        return mKdTree->GetRoot() != NULL;
3573}
3574
3575
3576int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
3577                                                                        const VssRayContainer &rays)
3578{
3579        return 0;
3580}
3581
3582
3583void KdViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
3584                                                                                           const int maxViewCells,
3585                                                                                           const bool sortViewCells,
3586                                                                                           const bool exportPvs,
3587                                                                                           const bool exportRays,
3588                                                                                           const int maxRays,
3589                                                                                           const string prefix,
3590                                                                                           VssRayContainer *visRays)
3591{
3592        // TODO
3593}
3594
3595
3596void KdViewCellsManager::Visualize(const ObjectContainer &objects,
3597                                                                   const VssRayContainer &sampleRays)
3598{
3599        if (!ViewCellsConstructed())
3600                return;
3601
3602        // using view cells instead of the kd PVS of objects
3603        const bool useViewCells = true;
3604        bool exportRays = false;
3605
3606        int limit = min(mVisualizationSamples, (int)sampleRays.size());
3607        const int pvsOut = min((int)objects.size(), 10);
3608        VssRayContainer *rays = new VssRayContainer[pvsOut];
3609
3610        if (useViewCells)
3611        {
3612                const int leafOut = 10;
3613
3614                ViewCell::NewMail();
3615
3616                //-- some rays for output
3617                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
3618                Debug << "visualization using " << raysOut << " samples" << endl;
3619
3620                //-- some random view cells and rays for output
3621                vector<KdLeaf *> kdLeaves;
3622
3623                for (int i = 0; i < leafOut; ++ i)
3624                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
3625
3626                for (int i = 0; i < kdLeaves.size(); ++ i)
3627                {
3628                        KdLeaf *leaf = kdLeaves[i];
3629                        RayContainer vcRays;
3630
3631                        cout << "creating output for view cell " << i << " ... ";
3632#if 0
3633                        // check whether we can add the current ray to the output rays
3634                        for (int k = 0; k < raysOut; ++ k)
3635                        {
3636                                Ray *ray = sampleRays[k];
3637
3638                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
3639                                {
3640                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
3641
3642                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
3643                                        {
3644                                                vcRays.push_back(ray);
3645                                        }
3646                                }
3647                        }
3648#endif
3649                        Intersectable::NewMail();
3650
3651                        ViewCell *vc = leaf->mViewCell;
3652                        char str[64]; sprintf(str, "viewcell%04d.wrl", i);
3653
3654                        Exporter *exporter = Exporter::GetExporter(str);
3655                        exporter->SetFilled();
3656
3657                        exporter->SetWireframe();
3658                        //exporter->SetFilled();
3659
3660                        Material m;//= RandomMaterial();
3661                        m.mDiffuseColor = RgbColor(1, 1, 0);
3662                        exporter->SetForcedMaterial(m);
3663
3664                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
3665                        exporter->ExportBox(box);
3666
3667                        // export rays piercing this view cell
3668                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
3669
3670                        m.mDiffuseColor = RgbColor(1, 0, 0);
3671                        exporter->SetForcedMaterial(m);
3672
3673                        // exporter->SetWireframe();
3674                        exporter->SetFilled();
3675
3676                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
3677                        // -- output PVS of view cell
3678                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
3679                        {
3680                                Intersectable *intersect = (*it).first;
3681                                if (!intersect->Mailed())
3682                                {
3683                                        exporter->ExportIntersectable(intersect);
3684                                        intersect->Mail();
3685                                }
3686                        }
3687
3688                        DEL_PTR(exporter);
3689                        cout << "finished" << endl;
3690                }
3691
3692                DEL_PTR(rays);
3693        }
3694        else // using kd PVS of objects
3695        {
3696                for (int i = 0; i < limit; ++ i)
3697                {
3698                        VssRay *ray = sampleRays[i];
3699
3700                        // check whether we can add this to the rays
3701                        for (int j = 0; j < pvsOut; j++)
3702                        {
3703                                if (objects[j] == ray->mTerminationObject)
3704                                {
3705                                        rays[j].push_back(ray);
3706                                }
3707                        }
3708                }
3709
3710                if (exportRays)
3711                {
3712                        Exporter *exporter = NULL;
3713                        exporter = Exporter::GetExporter("sample-rays.x3d");
3714                        exporter->SetWireframe();
3715                        exporter->ExportKdTree(*mKdTree);
3716
3717                        for (i = 0; i < pvsOut; i++)
3718                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
3719
3720                        exporter->SetFilled();
3721                        delete exporter;
3722                }
3723
3724                for (int k=0; k < pvsOut; k++)
3725                {
3726                        Intersectable *object = objects[k];
3727                        char str[64]; sprintf(str, "viewcell%04d.wrl", i);
3728
3729                        Exporter *exporter = Exporter::GetExporter(str);
3730                        exporter->SetWireframe();
3731
3732                        KdPvsMap::iterator kit = object->mKdPvs.mEntries.begin();
3733                        Intersectable::NewMail();
3734
3735                        // avoid adding the object to the list
3736                        object->Mail();
3737                        ObjectContainer visibleObjects;
3738
3739                        for (; kit != object->mKdPvs.mEntries.end(); i++)
3740                        {
3741                                KdNode *node = (*kit).first;
3742                                exporter->ExportBox(mKdTree->GetBox(node));
3743
3744                                mKdTree->CollectObjects(node, visibleObjects);
3745                        }
3746
3747                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
3748                        exporter->SetFilled();
3749
3750                        for (int j = 0; j < visibleObjects.size(); j++)
3751                                exporter->ExportIntersectable(visibleObjects[j]);
3752
3753                        Material m;
3754                        m.mDiffuseColor = RgbColor(1, 0, 0);
3755                        exporter->SetForcedMaterial(m);
3756                        exporter->ExportIntersectable(object);
3757
3758                        delete exporter;
3759                }
3760        }
3761}
3762
3763
3764ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
3765{
3766        return new KdViewCell(mesh);
3767}
3768
3769
3770void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3771                                                                                                ViewCell *vc,
3772                                                                                                const AxisAlignedBox3 *sceneBox,
3773                                                                                                const AxisAlignedPlane *clipPlane
3774                                                                                                ) const
3775{
3776        ViewCellContainer leaves;
3777        mViewCellsTree->CollectLeaves(vc, leaves);
3778        ViewCellContainer::const_iterator it, it_end = leaves.end();
3779
3780        for (it = leaves.begin(); it != it_end; ++ it)
3781        {
3782                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
3783                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaves[0]));
3784        }
3785}
3786
3787
3788int KdViewCellsManager::GetType() const
3789{
3790        return ViewCellsManager::KD;
3791}
3792
3793
3794
3795KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
3796{
3797        KdNode *node = leaf;
3798
3799        while (node->mParent && node->mDepth > mKdPvsDepth)
3800                node = node->mParent;
3801
3802        return node;
3803}
3804
3805int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
3806                                                                                const Vector3 &termination,
3807                                                                                ViewCellContainer &viewcells)
3808{
3809        return mKdTree->CastLineSegment(origin, termination, viewcells);
3810}
3811
3812
3813void KdViewCellsManager::CreateMesh(ViewCell *vc)
3814{
3815        // TODO
3816}
3817
3818
3819
3820void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3821                                                                                                vector<MergeCandidate> &candidates)
3822{
3823        // TODO
3824}
3825
3826
3827
3828/**************************************************************************/
3829/*                   VspBspViewCellsManager implementation                */
3830/**************************************************************************/
3831
3832
3833VspBspViewCellsManager::VspBspViewCellsManager(ViewCellsTree *vcTree, VspBspTree *vspBspTree):
3834ViewCellsManager(vcTree), mVspBspTree(vspBspTree)
3835{
3836        Environment::GetSingleton()->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
3837        mVspBspTree->SetViewCellsManager(this);
3838        mVspBspTree->mViewCellsTree = mViewCellsTree;
3839}
3840
3841
3842VspBspViewCellsManager::~VspBspViewCellsManager()
3843{
3844}
3845
3846
3847float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
3848{
3849        if (0 && mVspBspTree->mUseAreaForPvs)
3850                return GetArea(viewCell) / GetAccVcArea();
3851        else
3852                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
3853}
3854
3855
3856void VspBspViewCellsManager::CollectViewCells()
3857{
3858        // view cells tree constructed?
3859        if (!ViewCellsTreeConstructed())
3860        {
3861                mVspBspTree->CollectViewCells(mViewCells, false);
3862        }
3863        else
3864        {       
3865                // we can use the view cells tree hierarchy to get the right set
3866                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
3867        }
3868}
3869
3870
3871void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3872                                                                                                        vector<MergeCandidate> &candidates)
3873{       
3874        cout << "collecting merge candidates ... " << endl;
3875
3876        if (mUseRaysForMerge)
3877        {
3878                mVspBspTree->CollectMergeCandidates(rays, candidates);
3879        }
3880        else
3881        {
3882                vector<BspLeaf *> leaves;
3883                mVspBspTree->CollectLeaves(leaves);
3884       
3885                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3886        }
3887
3888        cout << "fininshed collecting candidates" << endl;
3889}
3890
3891
3892bool VspBspViewCellsManager::ViewCellsConstructed() const
3893{
3894        return mVspBspTree->GetRoot() != NULL;
3895}
3896
3897
3898ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3899{
3900        return new BspViewCell(mesh);
3901}
3902
3903
3904int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
3905                                                                                                 const VssRayContainer &rays)
3906{
3907        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
3908
3909        // if view cells were already constructed
3910        if (ViewCellsConstructed())
3911        {
3912                return 0;
3913        }
3914
3915        int sampleContributions = 0;
3916        VssRayContainer sampleRays;
3917
3918        const int limit = min(mInitialSamples, (int)rays.size());
3919
3920        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
3921                  << ", actual rays: " << (int)rays.size() << endl;
3922
3923        VssRayContainer savedRays;
3924
3925        if (SAMPLE_AFTER_SUBDIVISION)
3926        {
3927                VssRayContainer constructionRays;
3928               
3929                GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
3930
3931                Debug << "rays used for initial construction: " << (int)constructionRays.size() << endl;
3932                Debug << "rays saved for later use: " << (int)savedRays.size() << endl;
3933       
3934                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
3935        }
3936        else
3937        {
3938                Debug << "rays used for initial construction: " << (int)rays.size() << endl;
3939                mVspBspTree->Construct(rays, &mViewSpaceBox);
3940        }
3941
3942        // collapse invalid regions
3943        cout << "collapsing invalid tree regions ... ";
3944        long startTime = GetTime();
3945
3946        const int collapsedLeaves = mVspBspTree->CollapseTree();
3947        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
3948                  << " seconds" << endl;
3949
3950    cout << "finished" << endl;
3951
3952        /////////////////
3953        //-- stats after construction
3954
3955        Debug << mVspBspTree->GetStatistics() << endl;
3956
3957        ResetViewCells();
3958        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
3959
3960
3961        //////////////////////
3962        //-- recast the rest of the rays
3963
3964        startTime = GetTime();
3965
3966        cout << "Computing remaining ray contributions ... ";
3967
3968        if (SAMPLE_AFTER_SUBDIVISION)
3969                ComputeSampleContributions(savedRays, true, false);
3970
3971        cout << "finished" << endl;
3972
3973        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
3974                  << " secs" << endl;
3975
3976        cout << "construction finished" << endl;
3977
3978        if (0)
3979        {       ////////
3980                //-- real meshes are contructed at this stage
3981                cout << "finalizing view cells ... ";
3982                FinalizeViewCells(true);
3983                cout << "finished" << endl;
3984        }
3985
3986        return sampleContributions;
3987}
3988
3989
3990void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
3991                                                                                        const ObjectContainer &objects)
3992{
3993    int vcSize = 0;
3994        int pvsSize = 0;
3995
3996        //-- merge view cells
3997        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
3998        long startTime = GetTime();
3999
4000
4001        if (mMergeViewCells)
4002        {
4003                // TODO: should be done BEFORE the ray casting
4004                // compute tree by merging the nodes based on cost heuristics
4005                mViewCellsTree->ConstructMergeTree(rays, objects);
4006        }
4007        else
4008        {
4009                // compute tree by merging the nodes of the spatial hierarchy
4010                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
4011                mViewCellsTree->SetRoot(root);
4012
4013                // compute pvs
4014                ObjectPvs pvs;
4015                UpdatePvsForEvaluation(root, pvs);
4016        }
4017
4018        if (1)
4019        {
4020                char mstats[100];
4021                ObjectPvs pvs;
4022
4023                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
4024                mViewCellsTree->ExportStats(mstats);
4025        }
4026
4027        cout << "merged view cells in "
4028                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
4029
4030        Debug << "Postprocessing: Merged view cells in "
4031                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
4032       
4033
4034        //////////////////
4035        //-- stats and visualizations
4036
4037        int savedColorCode = mColorCode;
4038       
4039        // get currently active view cell set
4040        ResetViewCells();
4041        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
4042       
4043        if (mShowVisualization) // export merged view cells
4044        {
4045                mColorCode = 0;
4046                Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
4047               
4048                cout << "exporting view cells after merge ... ";
4049
4050                if (exporter)
4051                {
4052                        if (0)
4053                                exporter->SetWireframe();
4054                        else
4055                                exporter->SetFilled();
4056
4057                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
4058
4059                        if (mExportGeometry)
4060                        {
4061                                Material m;
4062                                m.mDiffuseColor = RgbColor(0, 1, 0);
4063                                exporter->SetForcedMaterial(m);
4064                                exporter->SetFilled();
4065
4066                                exporter->ExportGeometry(objects);
4067                        }
4068
4069                        delete exporter;
4070                }
4071                cout << "finished" << endl;
4072        }
4073
4074        if (mShowVisualization)
4075        {
4076                // use pvs size for color coding
4077                mColorCode = 1;
4078                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
4079
4080                cout << "exporting view cells after merge (pvs size) ... ";     
4081
4082                if (exporter)
4083                {
4084                        exporter->SetFilled();
4085
4086                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
4087
4088                        if (mExportGeometry)
4089                        {
4090                                Material m;
4091                                m.mDiffuseColor = RgbColor(0, 1, 0);
4092                                exporter->SetForcedMaterial(m);
4093                                exporter->SetFilled();
4094
4095                                exporter->ExportGeometry(objects);
4096                        }
4097
4098                        delete exporter;
4099                }
4100                cout << "finished" << endl;
4101        }
4102
4103        mColorCode = savedColorCode;
4104}
4105
4106
4107void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
4108                                                                                         const ObjectContainer &objects)
4109{
4110        mRenderer->RenderScene();
4111
4112        SimulationStatistics ss;
4113        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
4114    Debug << "render time before refine\n\n" << ss << endl;
4115
4116        const long startTime = GetTime();
4117        cout << "Refining the merged view cells ... ";
4118
4119        // refining the merged view cells
4120        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
4121
4122        //-- stats and visualizations
4123        cout << "finished" << endl;
4124        cout << "refined " << refined << " view cells in "
4125                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
4126
4127        Debug << "Postprocessing: refined " << refined << " view cells in "
4128                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
4129}
4130
4131
4132int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
4133                                                                                const VssRayContainer &rays)
4134{
4135        if (!ViewCellsConstructed())
4136        {
4137                Debug << "postprocess error: no view cells constructed" << endl;
4138                return 0;
4139        }
4140
4141        // view cells already finished before post processing step
4142        // (i.e. because they were loaded)
4143        if (mViewCellsFinished)
4144        {
4145                FinalizeViewCells(true);
4146                EvaluateViewCellsStats();
4147
4148                return 0;
4149        }
4150
4151        // check if new view cells turned invalid
4152        int minPvs, maxPvs;
4153
4154        if (0)
4155        {
4156                minPvs = mMinPvsSize;
4157                maxPvs = mMaxPvsSize;
4158        }
4159        else
4160        {
4161                // problem matt: why did I start here from zero?
4162                minPvs = 0;
4163                maxPvs = mMaxPvsSize;
4164        }
4165
4166        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4167        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4168       
4169        SetValidity(minPvs, maxPvs);
4170
4171        // update valid view space according to valid view cells
4172        if (0) mVspBspTree->ValidateTree();
4173
4174        // area has to be recomputed
4175        mTotalAreaValid = false;
4176        VssRayContainer postProcessRays;
4177        GetRaySets(rays, mPostProcessSamples, postProcessRays);
4178
4179        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
4180
4181        // should maybe be done here to allow merge working
4182        // with area or volume and to correct the rendering statistics
4183        if (0) FinalizeViewCells(false);
4184               
4185        //////////
4186        //-- merge the individual view cells
4187        MergeViewCells(postProcessRays, objects);
4188       
4189        // refines the merged view cells
4190        if (0) RefineViewCells(postProcessRays, objects);
4191
4192
4193        ///////////
4194        //-- render simulation after merge + refine
4195
4196        cout << "\nview cells partition render time before compress" << endl << endl;;
4197        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
4198        SimulationStatistics ss;
4199        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
4200        cout << ss << endl;
4201       
4202
4203        ////////////
4204        //-- compression
4205//#if HAS_TO_BE_REDONE
4206        if (ViewCellsTreeConstructed() && mCompressViewCells)
4207        {
4208                int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
4209                Debug << "number of entries before compress: " << pvsEntries << endl;
4210
4211                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
4212
4213                pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
4214                Debug << "number of entries after compress: " << pvsEntries << endl;
4215        }
4216//#endif
4217
4218        // collapse sibling leaves that share the same view cell
4219        if (0) mVspBspTree->CollapseTree();
4220
4221        // recompute view cell list and statistics
4222        ResetViewCells();
4223
4224        // compute final meshes and volume / area
4225        if (1) FinalizeViewCells(true);
4226
4227        return 0;
4228}
4229
4230
4231int VspBspViewCellsManager::GetType() const
4232{
4233        return VSP_BSP;
4234}
4235
4236
4237ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
4238{
4239        // terminate recursion
4240        if (root->IsLeaf())
4241        {
4242                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
4243                leaf->GetViewCell()->SetMergeCost(0.0f);
4244                return leaf->GetViewCell();
4245        }
4246       
4247       
4248        BspInterior *interior = dynamic_cast<BspInterior *>(root);
4249        ViewCellInterior *viewCellInterior = new ViewCellInterior();
4250               
4251        // evaluate merge cost for priority traversal
4252        float mergeCost = 1.0f / (float)root->mTimeStamp;
4253        viewCellInterior->SetMergeCost(mergeCost);
4254
4255        float volume = 0;
4256       
4257        BspNode *front = interior->GetFront();
4258        BspNode *back = interior->GetBack();
4259
4260
4261        ObjectPvs frontPvs, backPvs;
4262
4263        //-- recursivly compute child hierarchies
4264        ViewCell *backVc = ConstructSpatialMergeTree(back);
4265        ViewCell *frontVc = ConstructSpatialMergeTree(front);
4266
4267
4268        viewCellInterior->SetupChildLink(backVc);
4269        viewCellInterior->SetupChildLink(frontVc);
4270
4271        volume += backVc->GetVolume();
4272        volume += frontVc->GetVolume();
4273
4274        viewCellInterior->SetVolume(volume);
4275
4276        return viewCellInterior;
4277}
4278
4279
4280bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
4281{
4282        if (!ViewCellsConstructed())
4283                return ViewCellsManager::GetViewPoint(viewPoint);
4284
4285        // TODO: set reasonable limit
4286        const int limit = 20;
4287
4288        for (int i = 0; i < limit; ++ i)
4289        {
4290                viewPoint = mViewSpaceBox.GetRandomPoint();
4291                if (mVspBspTree->ViewPointValid(viewPoint))
4292                {
4293                        return true;
4294                }
4295        }
4296
4297        Debug << "failed to find valid view point, taking " << viewPoint << endl;
4298        return false;
4299}
4300
4301
4302bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
4303{
4304        // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
4305        // validy update in preprocessor for all managers)
4306        return ViewCellsManager::ViewPointValid(viewPoint);
4307
4308        //      return mViewSpaceBox.IsInside(viewPoint) &&
4309        //                 mVspBspTree->ViewPointValid(viewPoint);
4310}
4311
4312
4313void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
4314                                                                           const VssRayContainer &sampleRays)
4315{
4316        if (!ViewCellsConstructed())
4317                return;
4318
4319        VssRayContainer visRays;
4320        GetRaySets(sampleRays, mVisualizationSamples, visRays);
4321       
4322        if (1)
4323        {       
4324                //////////////////
4325                //-- export final view cell partition
4326
4327                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
4328               
4329                if (exporter)
4330                {
4331                        cout << "exporting view cells after post process ... ";
4332                        if (0)
4333                        {       // export view space box
4334                                exporter->SetWireframe();
4335                                exporter->ExportBox(mViewSpaceBox);
4336                                exporter->SetFilled();
4337                        }
4338
4339                        Material m;
4340                        m.mDiffuseColor.r = 0.0f;
4341                        m.mDiffuseColor.g = 0.5f;
4342                        m.mDiffuseColor.b = 0.5f;
4343
4344            exporter->SetForcedMaterial(m);
4345
4346                        if (1 && mExportGeometry)
4347                        {
4348                                exporter->ExportGeometry(objects);
4349                        }
4350
4351                        if (0 && mExportRays)
4352                        {
4353                                exporter->ExportRays(visRays, RgbColor(1, 0, 0));
4354                        }
4355                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
4356
4357                        delete exporter;
4358                        cout << "finished" << endl;
4359                }
4360        }
4361
4362        ////////////////
4363        //-- visualization of the BSP splits
4364
4365        bool exportSplits = false;
4366        Environment::GetSingleton()->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
4367
4368        if (exportSplits)
4369        {
4370                cout << "exporting splits ... ";
4371                ExportSplits(objects, visRays);
4372                cout << "finished" << endl;
4373        }
4374
4375        ////////
4376        //-- export single view cells
4377       
4378        int leafOut;
4379        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
4380        const int raysOut = 100;
4381       
4382        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
4383}
4384
4385
4386void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
4387                                                                                  const VssRayContainer &rays)
4388{
4389        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
4390
4391        if (exporter)
4392        {
4393                Material m;
4394                m.mDiffuseColor = RgbColor(1, 0, 0);
4395                exporter->SetForcedMaterial(m);
4396                exporter->SetWireframe();
4397
4398                exporter->ExportBspSplits(*mVspBspTree, true);
4399
4400                // take forced material, else big scenes cannot be viewed
4401                m.mDiffuseColor = RgbColor(0, 1, 0);
4402                exporter->SetForcedMaterial(m);
4403                exporter->SetFilled();
4404
4405                exporter->ResetForcedMaterial();
4406
4407                // export rays
4408                if (mExportRays)
4409                {
4410                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
4411                }
4412
4413                if (mExportGeometry)
4414                {
4415                        exporter->ExportGeometry(objects);
4416                }
4417                delete exporter;
4418        }
4419}
4420
4421
4422void VspBspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
4423                                                                                                   const int maxViewCells,
4424                                                                                                   const bool sortViewCells,
4425                                                                                                   const bool exportPvs,
4426                                                                                                   const bool exportRays,
4427                                                                                                   const int maxRays,
4428                                                                                                   const string prefix,
4429                                                                                                   VssRayContainer *visRays)
4430{       
4431        if (sortViewCells)
4432        {
4433                // sort view cells to visualize the largest view cells
4434                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
4435        }
4436
4437        //////////
4438        //-- some view cells for output
4439
4440        ViewCell::NewMail();
4441        const int limit = min(maxViewCells, (int)mViewCells.size());
4442       
4443        for (int i = 0; i < limit; ++ i)
4444        {
4445                cout << "creating output for view cell " << i << " ... ";
4446
4447                ViewCell *vc = sortViewCells ? // largest view cell pvs first?
4448                        mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 0.5f)] : mViewCells[i];
4449
4450                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
4451                        continue;
4452
4453                vc->Mail();
4454
4455                ObjectPvs pvs;
4456                mViewCellsTree->GetPvs(vc, pvs);
4457
4458                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
4459                Exporter *exporter = Exporter::GetExporter(s);
4460               
4461                const float pvsCost = mViewCellsTree->GetPvsCost(vc);
4462                cout << "view cell " << vc->GetId() << ": pvs cost=" << pvsCost << endl;
4463
4464                if (exportRays)
4465                {
4466                        ////////////
4467                        //-- export rays piercing this view cell
4468
4469                        // take rays stored with the view cells during subdivision
4470                        VssRayContainer vcRays;
4471            VssRayContainer collectRays;
4472
4473                        // collect initial view cells
4474                        ViewCellContainer leaves;
4475                        mViewCellsTree->CollectLeaves(vc, leaves);
4476
4477                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
4478                for (vit = leaves.begin(); vit != vit_end; ++ vit)
4479                        {       
4480                                BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaves[0];
4481                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
4482
4483                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
4484                                {
4485                                        collectRays.push_back(*rit);
4486                                }
4487                        }
4488
4489                        const int raysOut = min((int)collectRays.size(), maxRays);
4490               
4491                        // prepare some rays for output
4492                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
4493                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
4494                        {
4495                                const float p = RandomValue(0.0f, (float)collectRays.size());
4496                       
4497                                if (p < raysOut)
4498                                {
4499                                        vcRays.push_back(*rit);
4500                                }
4501                        }
4502
4503                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
4504                }
4505               
4506                ////////////////
4507                //-- export view cell geometry
4508
4509                exporter->SetWireframe();
4510
4511                Material m;//= RandomMaterial();
4512                m.mDiffuseColor = RgbColor(0, 1, 0);
4513                exporter->SetForcedMaterial(m);
4514
4515                ExportViewCellGeometry(exporter, vc, NULL, NULL);
4516                exporter->SetFilled();
4517
4518                if (exportPvs)
4519                {
4520                        Intersectable::NewMail();
4521
4522                        ObjectPvsMap::const_iterator oit, oit_end = pvs.mEntries.end();
4523                        cout << endl;
4524                        // output PVS of view cell
4525                        for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
4526                        {               
4527                                Intersectable *intersect = (*oit).first;
4528                               
4529                                if (!intersect->Mailed())
4530                                {
4531                                        intersect->Mail();
4532
4533                                        m = RandomMaterial();
4534                                        exporter->SetForcedMaterial(m);
4535                                        exporter->ExportIntersectable(intersect);
4536                                }
4537                        }
4538                        cout << endl;
4539                }
4540               
4541                DEL_PTR(exporter);
4542                cout << "finished" << endl;
4543        }
4544}
4545
4546
4547void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
4548{
4549        Exporter *exporter = Exporter::GetExporter("filter.x3d");
4550
4551        Vector3 bsize = mViewSpaceBox.Size();
4552        const Vector3 viewPoint(mViewSpaceBox.Center());
4553        float w = Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
4554        const Vector3 width = Vector3(w);
4555       
4556        PrVs testPrVs;
4557       
4558        if (exporter)
4559        {
4560                ViewCellContainer viewCells;
4561       
4562        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
4563
4564                GetPrVS(viewPoint, testPrVs, GetFilterWidth());
4565
4566                exporter->SetWireframe();
4567
4568                exporter->SetForcedMaterial(RgbColor(1,1,1));
4569                exporter->ExportBox(tbox);
4570               
4571                exporter->SetFilled();
4572
4573                exporter->SetForcedMaterial(RgbColor(0,1,0));
4574                ExportViewCellGeometry(exporter, GetViewCell(viewPoint), NULL, NULL);
4575
4576                //exporter->ResetForcedMaterial();
4577                exporter->SetForcedMaterial(RgbColor(0,0,1));
4578                ExportViewCellGeometry(exporter, testPrVs.mViewCell, NULL, NULL);
4579
4580        exporter->SetForcedMaterial(RgbColor(1,0,0));
4581                exporter->ExportGeometry(objects);
4582
4583                delete exporter;
4584        }
4585}
4586
4587
4588int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
4589                                                                                                        ViewCellContainer &viewCells) const
4590{
4591        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
4592}
4593
4594
4595int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
4596                                                                                        const Vector3 &termination,
4597                                                                                        ViewCellContainer &viewcells)
4598{
4599        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
4600}
4601
4602
4603void VspBspViewCellsManager::VisualizeWithFromPointQueries()
4604{
4605        int numSamples;
4606       
4607        Environment::GetSingleton()->GetIntValue("RenderSampler.samples", numSamples);
4608        cout << "samples" << numSamples << endl;
4609
4610        vector<RenderCostSample> samples;
4611 
4612        if (!mPreprocessor->GetRenderer())
4613                return;
4614
4615        //start the view point queries
4616        long startTime = GetTime();
4617        cout << "starting sampling of render cost ... ";
4618       
4619        mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
4620
4621        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
4622
4623
4624        // for each sample:
4625        //    find view cells associated with the samples
4626        //    store the sample pvs with the pvs associated with the view cell
4627        //
4628        // for each view cell:
4629        //    compute difference point sampled pvs - view cell pvs
4630        //    export geometry with color coded pvs difference
4631       
4632    std::map<ViewCell *, ObjectPvs> sampleMap;
4633
4634        vector<RenderCostSample>::const_iterator rit, rit_end = samples.end();
4635
4636        for (rit = samples.begin(); rit != rit_end; ++ rit)
4637        {
4638                RenderCostSample sample = *rit;
4639       
4640                ViewCell *vc = GetViewCell(sample.mPosition);
4641
4642                std::map<ViewCell *, ObjectPvs>::iterator it = sampleMap.find(vc);
4643
4644                if (it == sampleMap.end())
4645                {
4646                        sampleMap[vc] = sample.mPvs;
4647                }
4648                else
4649                {
4650                        (*it).second.Merge(sample.mPvs);
4651                }
4652        }
4653
4654        // visualize the view cells
4655        std::map<ViewCell *, ObjectPvs>::const_iterator vit, vit_end = sampleMap.end();
4656
4657        Material m;//= RandomMaterial();
4658
4659        for (vit = sampleMap.begin(); vit != vit_end; ++ vit)
4660        {
4661                ViewCell *vc = (*vit).first;
4662               
4663                const int pvsVc = mViewCellsTree->GetPvsEntries(vc);
4664                const int pvsPtSamples = (*vit).second.GetSize();
4665
4666        m.mDiffuseColor.r = (float) (pvsVc - pvsPtSamples);
4667                m.mDiffuseColor.b = 1.0f;
4668                //exporter->SetForcedMaterial(m);
4669                //ExportViewCellGeometry(exporter, vc, mClipPlaneForViz);
4670
4671                /*      // counting the pvss
4672                for (rit = samples.begin(); rit != rit_end; ++ rit)
4673                {
4674                        RenderCostSample sample = *rit;
4675                        ViewCell *vc = GetViewCell(sample.mPosition);
4676
4677                        AxisAlignedBox3 box(sample.mPosition - Vector3(1, 1, 1), sample.mPosition + Vector3(1, 1, 1));
4678                        Mesh *hMesh = CreateMeshFromBox(box);
4679
4680                        DEL_PTR(hMesh);
4681                }
4682                */
4683        }
4684}
4685
4686
4687void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
4688                                                                                                        ViewCell *vc,
4689                                                                                                        const AxisAlignedBox3 *sceneBox,
4690                                                                                                        const AxisAlignedPlane *clipPlane
4691                                                                                                        ) const
4692{
4693        if (clipPlane)
4694        {
4695                const Plane3 plane = clipPlane->GetPlane();
4696
4697                ViewCellContainer leaves;
4698                mViewCellsTree->CollectLeaves(vc, leaves);
4699                ViewCellContainer::const_iterator it, it_end = leaves.end();
4700
4701                for (it = leaves.begin(); it != it_end; ++ it)
4702                {
4703                        BspNodeGeometry geom;
4704                        BspNodeGeometry front;
4705                        BspNodeGeometry back;
4706
4707                        mVspBspTree->ConstructGeometry(*it, geom);
4708
4709                        const float eps = 0.0001f;
4710                        const int cf = geom.Side(plane, eps);
4711
4712                        if (cf == -1)
4713                        {
4714                                exporter->ExportPolygons(geom.GetPolys());
4715                        }
4716                        else if (cf == 0)
4717                        {
4718                                geom.SplitGeometry(front,
4719                                                                   back,
4720                                                                   plane,
4721                                                                   mViewSpaceBox,
4722                                                                   eps);
4723
4724                                if (back.Valid())
4725                                {
4726                                        exporter->ExportPolygons(back.GetPolys());
4727                                }                       
4728                        }
4729                }
4730        }
4731        else
4732        {
4733                // export mesh if available
4734                // TODO: some bug here?
4735                if (1 && vc->GetMesh())
4736                {
4737                        exporter->ExportMesh(vc->GetMesh());
4738                }
4739                else
4740                {
4741                        BspNodeGeometry geom;
4742                        mVspBspTree->ConstructGeometry(vc, geom);
4743                        exporter->ExportPolygons(geom.GetPolys());
4744                }
4745        }
4746}
4747
4748
4749int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
4750{
4751        ViewCellContainer leaves;
4752        mViewCellsTree->CollectLeaves(vc, leaves);
4753
4754        int maxDist = 0;
4755       
4756        // compute max height difference
4757        for (int i = 0; i < (int)leaves.size(); ++ i)
4758        {
4759                for (int j = 0; j < (int)leaves.size(); ++ j)
4760                {
4761                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaves[0];
4762
4763                        if (i != j)
4764                        {
4765                                BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaves[0];
4766                                const int dist = mVspBspTree->TreeDistance(leaf, leaf2);
4767                               
4768                                if (dist > maxDist)
4769                                        maxDist = dist;
4770                        }
4771                }
4772        }
4773
4774        return maxDist;
4775}
4776
4777
4778ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
4779{
4780        if (!ViewCellsConstructed())
4781                return NULL;
4782
4783        if (!mViewSpaceBox.IsInside(point))
4784          return NULL;
4785
4786        return mVspBspTree->GetViewCell(point, active);
4787}
4788
4789
4790void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
4791{
4792        BspNodeGeometry geom;
4793        mVspBspTree->ConstructGeometry(vc, geom);
4794       
4795        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
4796        IncludeNodeGeomInMesh(geom, *mesh);
4797
4798        vc->SetMesh(mesh);
4799}
4800
4801
4802int VspBspViewCellsManager::CastBeam(Beam &beam)
4803{
4804        return mVspBspTree->CastBeam(beam);
4805}
4806
4807
4808void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
4809                                                                          const bool createMesh)
4810{
4811        float area = 0;
4812        float volume = 0;
4813
4814        ViewCellContainer leaves;
4815        mViewCellsTree->CollectLeaves(viewCell, leaves);
4816
4817        ViewCellContainer::const_iterator it, it_end = leaves.end();
4818
4819    for (it = leaves.begin(); it != it_end; ++ it)
4820        {
4821                BspNodeGeometry geom;
4822                mVspBspTree->ConstructGeometry(*it, geom);
4823
4824                const float lVol = geom.GetVolume();
4825                const float lArea = geom.GetArea();
4826
4827                area += lArea;
4828                volume += lVol;
4829
4830                if (createMesh)
4831                        CreateMesh(*it);
4832        }
4833
4834        viewCell->SetVolume(volume);
4835        viewCell->SetArea(area);
4836}
4837
4838
4839void VspBspViewCellsManager::TestSubdivision()
4840{
4841        ViewCellContainer leaves;
4842        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
4843
4844        ViewCellContainer::const_iterator it, it_end = leaves.end();
4845
4846        const float vol = mViewSpaceBox.GetVolume();
4847        float subdivVol = 0;
4848        float newVol = 0;
4849
4850        for (it = leaves.begin(); it != it_end; ++ it)
4851        {
4852                BspNodeGeometry geom;
4853                mVspBspTree->ConstructGeometry(*it, geom);
4854
4855                const float lVol = geom.GetVolume();
4856               
4857                newVol += lVol;
4858                subdivVol += (*it)->GetVolume();
4859               
4860                float thres = 0.9f;
4861                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
4862                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
4863        }
4864       
4865        Debug << "exact volume: " << vol << endl;
4866        Debug << "subdivision volume: " << subdivVol << endl;
4867        Debug << "new volume: " << newVol << endl;
4868}
4869
4870
4871void VspBspViewCellsManager::PrepareLoadedViewCells()
4872{
4873        // TODO: do I still need this here?
4874        if (0)
4875                mVspBspTree->RepairViewCellsLeafLists();
4876}
4877
4878
4879
4880/**************************************************************************/
4881/*                   VspOspViewCellsManager implementation                */
4882/**************************************************************************/
4883
4884
4885VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, HierarchyManager *hm)
4886: ViewCellsManager(vcTree), mHierarchyManager(hm)
4887{
4888        Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
4889
4890        mHierarchyManager->SetViewCellsManager(this);
4891        mHierarchyManager->SetViewCellsTree(mViewCellsTree);
4892}
4893
4894
4895VspOspViewCellsManager::~VspOspViewCellsManager()
4896{
4897}
4898
4899
4900float VspOspViewCellsManager::GetProbability(ViewCell *viewCell)
4901{
4902        return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
4903}
4904
4905
4906void VspOspViewCellsManager::CollectViewCells()
4907{
4908        // view cells tree constructed
4909        if (!ViewCellsTreeConstructed())
4910        {
4911                mHierarchyManager->GetVspTree()->CollectViewCells(mViewCells, false);
4912        }
4913        else
4914        {       // we can use the view cells tree hierarchy to get the right set
4915                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
4916        }
4917}
4918
4919
4920bool VspOspViewCellsManager::ViewCellsConstructed() const
4921{
4922        return mHierarchyManager->GetVspTree()->GetRoot() != NULL;
4923}
4924
4925
4926ViewCell *VspOspViewCellsManager::GenerateViewCell(Mesh *mesh) const
4927{
4928        return new VspViewCell(mesh);
4929}
4930
4931
4932int VspOspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
4933                                                                                                 const VssRayContainer &rays)
4934{
4935        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
4936
4937        // skip rest if view cells were already constructed
4938        if (ViewCellsConstructed())
4939                return 0;
4940
4941        int sampleContributions = 0;
4942        VssRayContainer sampleRays;
4943
4944        int limit = min (mInitialSamples, (int)rays.size());
4945
4946        VssRayContainer constructionRays;
4947        VssRayContainer savedRays;
4948
4949        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
4950                  << ", actual rays: " << (int)rays.size() << endl;
4951
4952        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
4953
4954        Debug << "initial rays used for construction: " << (int)constructionRays.size() << endl;
4955        Debug << "saved rays: " << (int)savedRays.size() << endl;
4956
4957        mHierarchyManager->Construct(constructionRays, objects, &mViewSpaceBox);
4958
4959#if TEST_EVALUATION
4960        VssRayContainer::const_iterator tit, tit_end = constructionRays.end();
4961        for (tit = constructionRays.begin(); tit != tit_end; ++ tit)
4962        {
4963                storedRays.push_back(new VssRay(*(*tit)));
4964        }
4965#endif
4966
4967        /////////////////////////
4968        //-- print satistics for subdivision and view cells
4969
4970        Debug << endl << endl << *mHierarchyManager << endl;
4971
4972        ResetViewCells();
4973        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
4974
4975        //////////////
4976        //-- recast rest of rays
4977       
4978        const long startTime = GetTime();
4979        cout << "Computing remaining ray contributions ... ";
4980
4981        if (SAMPLE_AFTER_SUBDIVISION)
4982                ComputeSampleContributions(savedRays, true, false);
4983
4984        Debug << "finished computing remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
4985                  << " secs" << endl;
4986
4987        if (0)
4988        {       // real meshes are constructed at this stage
4989                cout << "finalizing view cells ... ";
4990                FinalizeViewCells(true);
4991                cout << "finished" << endl;
4992        }
4993
4994        return sampleContributions;
4995}
4996
4997
4998int VspOspViewCellsManager::PostProcess(const ObjectContainer &objects,
4999                                                                                const VssRayContainer &rays)
5000{
5001        if (!ViewCellsConstructed())
5002        {
5003                Debug << "postprocess error: no view cells constructed" << endl;
5004                return 0;
5005        }
5006
5007        // if view cells were already constructed before post processing step
5008        // (e.g., because they were loaded), we are finished
5009        if (mViewCellsFinished)
5010        {
5011                FinalizeViewCells(true);
5012                EvaluateViewCellsStats();
5013
5014                return 0;
5015        }
5016
5017        // check if new view cells turned invalid
5018        int minPvs, maxPvs;
5019
5020        if (0)
5021        {
5022                minPvs = mMinPvsSize;
5023                maxPvs = mMaxPvsSize;
5024        }
5025        else
5026        {
5027                // problem matt: why did I start here from zero?
5028                minPvs = 0;
5029                maxPvs = mMaxPvsSize;
5030        }
5031
5032        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5033        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5034       
5035        SetValidity(minPvs, maxPvs);
5036
5037       
5038        // area is not up to date, has to be recomputed
5039        mTotalAreaValid = false;
5040        VssRayContainer postProcessRays;
5041        GetRaySets(rays, mPostProcessSamples, postProcessRays);
5042
5043        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
5044
5045
5046        // compute tree by merging the nodes of the spatial hierarchy
5047        ViewCell *root = ConstructSpatialMergeTree(mHierarchyManager->GetVspTree()->GetRoot());
5048        mViewCellsTree->SetRoot(root);
5049
5050        //////////////////////////
5051        //-- update pvs up to the root of the hierarchy
5052
5053        ObjectPvs pvs;
5054        UpdatePvsForEvaluation(root, pvs);
5055
5056
5057        //////////////////////
5058        //-- render simulation after merge + refine
5059
5060        cout << "\nview cells partition render time before compress" << endl << endl;
5061        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
5062        SimulationStatistics ss;
5063        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
5064        cout << ss << endl;
5065       
5066
5067        ///////////
5068        //-- compression
5069
5070        if (ViewCellsTreeConstructed() && mCompressViewCells)
5071        {
5072                int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
5073                Debug << "number of entries before compress: " << pvsEntries << endl;
5074
5075                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
5076
5077                pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
5078                Debug << "number of entries after compress: " << pvsEntries << endl;
5079        }
5080
5081        /////////////
5082        //-- some tasks still to do on the view cells:
5083        //-- Compute meshes from view cell geometry, evaluate volume and / or area
5084
5085        if (1) FinalizeViewCells(true);
5086
5087        return 0;
5088}
5089
5090
5091int VspOspViewCellsManager::GetType() const
5092{
5093        return VSP_OSP;
5094}
5095
5096
5097ViewCell *VspOspViewCellsManager::ConstructSpatialMergeTree(VspNode *root)
5098{
5099        // terminate recursion
5100        if (root->IsLeaf())
5101        {
5102                VspLeaf *leaf = dynamic_cast<VspLeaf *>(root);
5103                leaf->GetViewCell()->SetMergeCost(0.0f);
5104                return leaf->GetViewCell();
5105        }
5106       
5107        VspInterior *interior = dynamic_cast<VspInterior *>(root);
5108        ViewCellInterior *viewCellInterior = new ViewCellInterior();
5109               
5110        // evaluate merge cost for priority traversal
5111        const float mergeCost = -(float)root->mTimeStamp;
5112        viewCellInterior->SetMergeCost(mergeCost);
5113
5114        float volume = 0;
5115       
5116        VspNode *front = interior->GetFront();
5117        VspNode *back = interior->GetBack();
5118
5119        ObjectPvs frontPvs, backPvs;
5120
5121        /////////
5122        //-- recursivly compute child hierarchies
5123
5124        ViewCell *backVc = ConstructSpatialMergeTree(back);
5125        ViewCell *frontVc = ConstructSpatialMergeTree(front);
5126
5127        viewCellInterior->SetupChildLink(backVc);
5128        viewCellInterior->SetupChildLink(frontVc);
5129
5130        volume += backVc->GetVolume();
5131        volume += frontVc->GetVolume();
5132
5133        viewCellInterior->SetVolume(volume);
5134
5135        return viewCellInterior;
5136}
5137
5138
5139bool VspOspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
5140{
5141        if (!ViewCellsConstructed())
5142                return ViewCellsManager::GetViewPoint(viewPoint);
5143
5144        // TODO: set reasonable limit
5145        const int limit = 20;
5146
5147        for (int i = 0; i < limit; ++ i)
5148        {
5149                viewPoint = mViewSpaceBox.GetRandomPoint();
5150
5151                if (mHierarchyManager->GetVspTree()->ViewPointValid(viewPoint))
5152                {
5153                        return true;
5154                }
5155        }
5156
5157        Debug << "failed to find valid view point, taking " << viewPoint << endl;
5158        return false;
5159}
5160
5161
5162void VspOspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
5163                                                                                                        ViewCell *vc,
5164                                                                                                        const AxisAlignedBox3 *sceneBox,
5165                                                                                                        const AxisAlignedPlane *clipPlane
5166                                                                                                        ) const
5167{
5168        ViewCellContainer leaves;
5169        mViewCellsTree->CollectLeaves(vc, leaves);
5170        ViewCellContainer::const_iterator it, it_end = leaves.end();
5171
5172        Plane3 plane;
5173        if (clipPlane)
5174        {
5175                // arbitrary plane definition
5176                plane = clipPlane->GetPlane();
5177        }
5178
5179        for (it = leaves.begin(); it != it_end; ++ it)
5180        {
5181                VspViewCell *vspVc = dynamic_cast<VspViewCell *>(*it);
5182                VspLeaf *l = vspVc->mLeaves[0];
5183
5184                const AxisAlignedBox3 box =
5185                        mHierarchyManager->GetVspTree()->GetBoundingBox(vspVc->mLeaves[0]);
5186               
5187                if (sceneBox && !Overlap(*sceneBox, box))
5188                        continue;
5189
5190                if (clipPlane)
5191                {
5192                        if (box.Side(plane) == -1)
5193                        {
5194                                exporter->ExportBox(box);
5195                        }
5196                        else if (box.Side(plane) == 0)
5197                        {
5198                                // intersection
5199                                AxisAlignedBox3 fbox, bbox;
5200                                box.Split(clipPlane->mAxis, clipPlane->mPosition, fbox, bbox);
5201                                exporter->ExportBox(bbox);
5202                        }
5203                }
5204                else
5205                {
5206                        exporter->ExportBox(box);
5207                }
5208        }
5209}
5210
5211
5212bool VspOspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
5213{
5214  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
5215  // validy update in preprocessor for all managers)
5216  return ViewCellsManager::ViewPointValid(viewPoint);
5217
5218  //    return mViewSpaceBox.IsInside(viewPoint) &&
5219  //               mVspTree->ViewPointValid(viewPoint);
5220}
5221
5222
5223void VspOspViewCellsManager::Visualize(const ObjectContainer &objects,
5224                                                                           const VssRayContainer &sampleRays)
5225{
5226        if (!ViewCellsConstructed())
5227                return;
5228
5229        VssRayContainer visRays;
5230        GetRaySets(sampleRays, mVisualizationSamples, visRays);
5231
5232        ////////////
5233        //-- export final view cells
5234
5235        Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
5236
5237        if (exporter)
5238        {
5239                // hack color code (show pvs size)
5240                const int savedColorCode = mColorCode;
5241                mColorCode = 0;
5242
5243                const long starttime = GetTime();
5244                cout << "exporting final view cells (after initial construction + post process) ... ";
5245
5246                // matt: hack for clamping scene
5247                AxisAlignedBox3 bbox = mViewSpaceBox;
5248                bbox.Scale(Vector3(0.5, 1, 0.5));
5249
5250                if (CLAMP_TO_BOX)
5251                {       
5252                        exporter->SetWireframe();
5253                        exporter->ExportBox(bbox);
5254                        exporter->SetFilled();
5255                }
5256
5257                if (0 && mExportGeometry)
5258                {
5259                        exporter->ExportGeometry(objects, true, CLAMP_TO_BOX ? &bbox : NULL);
5260                }
5261
5262                if (1 && mExportRays)
5263                {       
5264                        exporter->ExportRays(visRays, RgbColor(0, 1, 0));
5265                }
5266
5267                mHierarchyManager->ExportObjectSpaceHierarchy(exporter,
5268                                objects, CLAMP_TO_BOX ? &bbox : NULL, false);
5269                ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, GetClipPlane());
5270
5271                delete exporter;
5272                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
5273                mColorCode = savedColorCode;
5274        }
5275
5276        // export final object partition
5277        exporter = Exporter::GetExporter("final_object_partition.wrl");
5278
5279        if (exporter)
5280        {
5281                const long starttime = GetTime();
5282
5283                // matt: hack for making visualization smaller in size
5284                AxisAlignedBox3 bbox = mHierarchyManager->GetObjectSpaceBox();
5285                bbox.Scale(Vector3(0.5, 1, 0.5));
5286
5287                cout << "exporting object space hierarchy ... ";
5288                mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects, CLAMP_TO_BOX ? &bbox : NULL);
5289
5290                delete exporter;
5291                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
5292        }
5293
5294       
5295        //  visualization of the view cells
5296        if (0) ExportMergedViewCells(objects);
5297
5298        // export some view cell
5299        int leafOut;
5300        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
5301        const int raysOut = 100;
5302
5303        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
5304}
5305
5306
5307void VspOspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
5308                                                                                                   const int maxViewCells,
5309                                                                                                   const bool sortViewCells,
5310                                                                                                   const bool exportPvs,
5311                                                                                                   const bool exportRays,
5312                                                                                                   const int maxRays,
5313                                                                                                   const string prefix,
5314                                                                                                   VssRayContainer *visRays)
5315{
5316        if (sortViewCells)
5317        {
5318                // sort view cells to visualize the view cells with highest render cost
5319                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
5320        }
5321
5322        ViewCell::NewMail();
5323        const int limit = min(maxViewCells, (int)mViewCells.size());
5324       
5325        cout << "\nExporting " << limit << " single view cells: " << endl;
5326       
5327        for (int i = 0; i < limit; ++ i)
5328        {
5329                cout << "creating output for view cell " << i << " ... ";
5330               
5331                // largest view cell pvs first of random view cell
5332                ViewCell *vc = sortViewCells ?
5333                        mViewCells[i] : mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
5334               
5335                if (vc->Mailed()) // already used
5336                        continue;
5337
5338                vc->Mail();
5339
5340                ObjectPvs pvs;
5341                mViewCellsTree->GetPvs(vc, pvs);
5342
5343                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
5344                Exporter *exporter = Exporter::GetExporter(s);
5345               
5346                cout << "view cell " << vc->GetId() << ": pvs cost=" << mViewCellsTree->GetPvsCost(vc) << endl;
5347
5348                if (exportPvs)
5349                {
5350                        Material m;
5351
5352                        Intersectable::NewMail();
5353                        ObjectPvsMap::const_iterator oit, oit_end = pvs.mEntries.end();
5354                       
5355                        // output PVS of view cell
5356                        for (oit = pvs.mEntries.begin(); oit != oit_end; ++ oit)
5357                        {               
5358                                Intersectable *intersect = (*oit).first;
5359                                if (!intersect->Mailed())
5360                                {
5361                                        m = RandomMaterial();
5362                                        exporter->SetForcedMaterial(m);
5363
5364                                        exporter->ExportIntersectable(intersect);
5365                                        intersect->Mail();
5366                                }
5367                        }
5368                }
5369
5370                if (exportRays)
5371                {
5372                        ////////////
5373                        //-- export the sample rays
5374
5375                        // output rays stored with the view cells during subdivision
5376                        VssRayContainer vcRays;
5377                        VssRayContainer collectRays;
5378
5379                        // collect intial view cells
5380                        ViewCellContainer leaves;
5381                        mViewCellsTree->CollectLeaves(vc, leaves);
5382
5383                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
5384
5385                        for (vit = leaves.begin(); vit != vit_end; ++ vit)
5386                        {
5387                                VspLeaf *vcLeaf = dynamic_cast<VspViewCell *>(*vit)->mLeaves[0];
5388                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
5389
5390                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
5391                                {
5392                                        collectRays.push_back(*rit);
5393                                }
5394                        }
5395
5396                        const int raysOut = min((int)collectRays.size(), maxRays);
5397
5398                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
5399
5400                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
5401                        {
5402                                const float p = RandomValue(0.0f, (float)collectRays.size());
5403
5404                                if (p < raysOut)
5405                                        vcRays.push_back(*rit);
5406                        }
5407
5408                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
5409                }
5410               
5411       
5412                /////////////////
5413                //-- export view cell geometry
5414
5415                exporter->SetWireframe();
5416
5417                Material m;
5418                m.mDiffuseColor = RgbColor(0, 1, 0);
5419                exporter->SetForcedMaterial(m);
5420
5421                ExportViewCellGeometry(exporter, vc, NULL, NULL);
5422                exporter->SetFilled();
5423
5424                DEL_PTR(exporter);
5425                cout << "finished" << endl;
5426        }
5427
5428        cout << endl;
5429}
5430
5431
5432int VspOspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
5433                                                                                                        ViewCellContainer &viewCells) const
5434{
5435        return mHierarchyManager->GetVspTree()->ComputeBoxIntersections(box, viewCells);
5436}
5437
5438
5439int VspOspViewCellsManager::CastLineSegment(const Vector3 &origin,
5440                                                                                        const Vector3 &termination,
5441                                                                                        ViewCellContainer &viewcells)
5442{
5443        return mHierarchyManager->GetVspTree()->CastLineSegment(origin, termination, viewcells);
5444}
5445
5446
5447bool VspOspViewCellsManager::ExportViewCells(const string filename,
5448                                                                                         const bool exportPvs,
5449                                                                                         const ObjectContainer &objects)
5450{
5451        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
5452                return false;
5453
5454        const long starttime = GetTime();
5455        cout << "exporting view cells to xml ... ";
5456       
5457        OUT_STREAM stream(filename.c_str());
5458
5459        // for output we need unique ids for each view cell
5460        CreateUniqueViewCellIds();
5461
5462        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
5463        stream << "<VisibilitySolution>" << endl;
5464
5465        if (exportPvs)
5466        {
5467        ///////////////
5468                //-- export bounding boxes
5469                //-- The bounding boxes are used to identify
5470                //-- the objects in the rendering engine
5471                mHierarchyManager->ExportBoundingBoxes(stream, objects);
5472        }
5473
5474        //////////////////////////
5475        //-- export the view cells and the pvs
5476
5477        const int numViewCells = mCurrentViewCellsStats.viewCells;
5478
5479        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
5480        mViewCellsTree->Export(stream, exportPvs);
5481        stream << "</ViewCells>" << endl;
5482
5483        //////////////////////
5484        //-- export the view space hierarchy
5485       
5486        stream << "<ViewSpaceHierarchy type=\"vsp\""
5487                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
5488                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
5489
5490        mHierarchyManager->GetVspTree()->Export(stream);
5491        stream << "</ViewSpaceHierarchy>" << endl;
5492
5493        ////////////////////// 
5494        //-- export the object space partition
5495       
5496        mHierarchyManager->ExportObjectSpaceHierarchy(stream);
5497       
5498        stream << "</VisibilitySolution>" << endl;
5499        stream.close();
5500       
5501        cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3 << " secs" << endl;
5502        return true;
5503}
5504
5505
5506
5507ViewCell *VspOspViewCellsManager::GetViewCell(const Vector3 &point,
5508                                                                                          const bool active) const
5509{
5510        if (!ViewCellsConstructed())
5511                return NULL;
5512
5513        if (!mViewSpaceBox.IsInside(point))
5514                return NULL;
5515
5516        return mHierarchyManager->GetVspTree()->GetViewCell(point, active);
5517}
5518
5519
5520void VspOspViewCellsManager::CreateMesh(ViewCell *vc)
5521{
5522        // matt: TODO
5523        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
5524
5525        ViewCellContainer leaves;
5526        mViewCellsTree->CollectLeaves(vc, leaves);
5527
5528        ViewCellContainer::const_iterator it, it_end = leaves.end();
5529
5530    for (it = leaves.begin(); it != it_end; ++ it)
5531        {
5532                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
5533                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
5534        IncludeBoxInMesh(box, *mesh);
5535        }
5536
5537        vc->SetMesh(mesh);
5538}
5539
5540
5541int VspOspViewCellsManager::CastBeam(Beam &beam)
5542{
5543        // matt: TODO
5544        return 0;
5545}
5546
5547
5548void VspOspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
5549{
5550        float area = 0;
5551        float volume = 0;
5552
5553        ViewCellContainer leaves;
5554        mViewCellsTree->CollectLeaves(viewCell, leaves);
5555
5556        ViewCellContainer::const_iterator it, it_end = leaves.end();
5557
5558    for (it = leaves.begin(); it != it_end; ++ it)
5559        {
5560                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
5561               
5562                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
5563
5564                const float lVol = box.GetVolume();
5565                const float lArea = box.SurfaceArea();
5566
5567                area += lArea;
5568                volume += lVol;
5569
5570        CreateMesh(*it);
5571        }
5572
5573        viewCell->SetVolume(volume);
5574        viewCell->SetArea(area);
5575}
5576       
5577
5578float VspOspViewCellsManager::ComputeSampleContribution(VssRay &ray,
5579                                                                                                                const bool addRays,
5580                                                                                                                const bool storeViewCells)
5581{
5582        ViewCellContainer viewcells;
5583
5584        ray.mPvsContribution = 0;
5585        ray.mRelativePvsContribution = 0.0f;
5586
5587        static Ray hray;
5588        hray.Init(ray);
5589        //hray.mFlags |= Ray::CULL_BACKFACES;
5590        //Ray hray(ray);
5591
5592        float tmin = 0, tmax = 1.0;
5593
5594        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
5595                return 0;
5596
5597        Vector3 origin = hray.Extrap(tmin);
5598        Vector3 termination = hray.Extrap(tmax);
5599
5600        ViewCell::NewMail();
5601
5602        // traverse the view space subdivision
5603        CastLineSegment(origin, termination, viewcells);
5604
5605        if (storeViewCells)
5606        {       
5607                // copy viewcells memory efficiently
5608                ray.mViewCells.reserve(viewcells.size());
5609                ray.mViewCells = viewcells;
5610        }
5611
5612        ViewCellContainer::const_iterator it = viewcells.begin();
5613
5614        for (; it != viewcells.end(); ++ it)
5615        {
5616                ViewCell *viewcell = *it;
5617
5618                if (viewcell->GetValid())
5619                {       // if ray not outside of view space
5620                        float contribution;
5621
5622                        if (ray.mTerminationObject)
5623                        {
5624                                // todo: maybe not correct for kd node pvs
5625                                Intersectable *obj = mHierarchyManager->GetIntersectable(ray, true);
5626
5627                                if (viewcell->GetPvs().GetSampleContribution(obj,
5628                                        ray.mPdf,
5629                                        contribution))
5630                                {
5631                                        ++ ray.mPvsContribution;
5632                                }
5633
5634                                ray.mRelativePvsContribution += contribution;
5635                        }
5636
5637                        ////////////////
5638                        //-- for directional sampling it is important to count only contributions
5639                        //-- made in one direction!
5640                        //-- the other contributions of this sample will be counted for the opposite ray!
5641#if SAMPLE_ORIGIN_OBJECTS
5642                        if (ray.mOriginObject &&
5643                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
5644                                ray.mPdf,
5645                                contribution))
5646                        {
5647                                ++ ray.mPvsContribution;
5648                                ray.mRelativePvsContribution += contribution;
5649                        }
5650#endif
5651                }
5652        }
5653
5654        if (!addRays)
5655        {
5656                return ray.mRelativePvsContribution;
5657        }
5658
5659        // sampled objects are stored in the pvs
5660        for (it = viewcells.begin(); it != viewcells.end(); ++ it)
5661        {
5662                ViewCell *viewCell = *it;
5663
5664                if (!viewCell->GetValid())
5665                        break;
5666
5667                AddSampleToPvs(
5668                        ray.mTerminationObject,
5669                        ray.mTermination,
5670                        viewCell,
5671                        ray.mPdf,
5672                        ray.mRelativePvsContribution);
5673
5674#if SAMPLE_ORIGIN_OBJECTS
5675
5676                AddSampleToPvs(
5677                        ray.mOriginObject,
5678                        ray.mOrigin,
5679                        viewCell,
5680                        ray.mPdf,
5681                        ray.mRelativePvsContribution);
5682#endif                 
5683        }
5684
5685       
5686
5687        return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
5688          (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
5689}
5690
5691
5692bool VspOspViewCellsManager::AddSampleToPvs(Intersectable *obj,
5693                                                                                        const Vector3 &hitPoint,
5694                                                                                        ViewCell *vc,
5695                                                                                        const float pdf,
5696                                                                                        float &contribution) const
5697{
5698        // The hierarchy manager decides about the type of sample cast
5699        return mHierarchyManager->AddSampleToPvs(obj, hitPoint, vc, pdf, contribution);
5700}
5701
5702
5703void VspOspViewCellsManager::PrepareLoadedViewCells()
5704{
5705        // TODO
5706}
5707
5708
5709ViewCellsManager *VspOspViewCellsManager::LoadViewCells(const string &filename,
5710                                                                                                                ObjectContainer *objects,
5711                                                                                                                const bool finalizeViewCells,
5712                                                                                                                BoundingBoxConverter *bconverter)
5713                                                                                                 
5714{
5715        ViewCellsManager *vm =
5716                ViewCellsManager::LoadViewCells(filename, objects, finalizeViewCells, bconverter);
5717#if 0
5718        // insert scene objects in tree
5719        mOspTree->InsertObjects(mOspTree->GetRoot(), *objects);
5720#endif
5721        return vm;
5722}
5723
5724
5725#if 1
5726
5727void VspOspViewCellsManager::EvalViewCellPartition()
5728{
5729        int samplesPerPass;
5730        int numSamples;
5731        int castSamples = 0;
5732        int oldSamples = 0;
5733        int samplesForStats;
5734        char statsPrefix[100];
5735        char suffix[100];
5736        int splitsStepSize;
5737
5738
5739        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
5740        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
5741        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
5742        Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
5743        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.stepSize", splitsStepSize);
5744       
5745        Debug << "step size: " << splitsStepSize << endl;
5746        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
5747        Debug << "view cell evaluation samples: " << numSamples << endl;
5748        Debug << "view cell stats prefix: " << statsPrefix << endl;
5749
5750        // should directional sampling be used?
5751        bool dirSamples =
5752                (mEvaluationSamplingType == SamplingStrategy::DIRECTION_BASED_DISTRIBUTION);
5753
5754        cout << "reseting pvs ... ";
5755               
5756        // reset pvs and start over from zero
5757        mViewCellsTree->ResetPvs();
5758       
5759        cout << "finished" << endl;
5760    cout << "Evaluating view cell partition ... " << endl;
5761
5762        while (castSamples < numSamples)
5763        {               
5764                ///////////////
5765                //-- we have to use uniform sampling strategy for construction rays
5766
5767                VssRayContainer evaluationSamples;
5768                const int samplingType = mEvaluationSamplingType;
5769
5770                long startTime = GetTime();
5771
5772                cout << "casting " << samplesPerPass << " samples ... ";
5773                Debug << "casting " << samplesPerPass << " samples ... ";
5774
5775                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
5776               
5777                castSamples += samplesPerPass;
5778
5779                Real timeDiff = TimeDiff(startTime, GetTime());
5780               
5781                cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
5782                cout << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
5783               
5784                Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
5785                Debug << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
5786
5787                startTime = GetTime();
5788
5789                ComputeSampleContributions(evaluationSamples, true, false);
5790
5791                timeDiff = TimeDiff(startTime, GetTime());
5792                cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
5793                Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
5794
5795                if ((castSamples >= samplesForStats + oldSamples) || (castSamples >= numSamples))
5796                {
5797                        oldSamples += samplesForStats;
5798
5799                        ///////////
5800                        //-- output stats
5801
5802                        sprintf(suffix, "-%09d-eval.log", castSamples);
5803                        const string filename = string(statsPrefix) + string(suffix);
5804
5805                        startTime = GetTime();
5806                        cout << "compute new statistics ... " << endl;
5807
5808                        ofstream ofstr(filename.c_str());
5809                        mHierarchyManager->EvaluateSubdivision2(ofstr, splitsStepSize);
5810
5811                        timeDiff = TimeDiff(startTime, GetTime());
5812                        cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
5813                        Debug << "statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
5814
5815                        // only for debugging purpose
5816                        if (1)
5817                        {
5818                                ViewCellContainer viewCells;
5819                                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), viewCells);
5820
5821                                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
5822                                int pvsSize = 0;
5823
5824                                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
5825                                {
5826                                        pvsSize += (*vit)->GetPvs().GetSize();
5827                                }
5828
5829                                cout << "debug entries: " << pvsSize << ", memcost: " << (float)pvsSize * ObjectPvs::GetEntrySize() << endl;
5830                        }
5831                }
5832
5833                disposeRays(evaluationSamples, NULL);
5834        }
5835       
5836}
5837#endif
5838}
Note: See TracBrowser for help on using the repository browser.