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

Revision 1935, 163.4 KB checked in by mattausch, 17 years ago (diff)

started depth peeling

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