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

Revision 1966, 165.2 KB checked in by bittner, 18 years ago (diff)

samplign preprocessor updates, merge

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 1
34#define AVG_RAY_CONTRIBUTIONS 0
35#define CONTRIBUTION_RELATIVE_TO_PVS_SIZE 0
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 " << (int)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 = min((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  stat.avgRelPvsIncrease = 0.0f;
1999  stat.devRelPvsIncrease = 0.0f;
2000 
2001  if (mPerViewCellStat.size() != mViewCells.size()) {
2002        // reset the pvs size array after the first call to this routine
2003        mPerViewCellStat.resize(mViewCells.size());
2004        for (int i=0; i < mPerViewCellStat.size(); i++) {
2005          mPerViewCellStat[i].pvsSize = 0.0f;
2006          mPerViewCellStat[i].relPvsIncrease = 0.0f;
2007        }
2008  }
2009  int i;
2010  bool evaluateFilter;
2011  Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluateFilter", evaluateFilter);
2012
2013  for (i=0; it != mViewCells.end(); ++ it, i++)
2014        {
2015          ViewCell *viewcell = *it;
2016          if (viewcell->GetValid()) {
2017                const float pvsCost = mViewCellsTree->GetPvsCost(viewcell);
2018               
2019                if (pvsCost < stat.minPvs)
2020                  stat.minPvs = pvsCost;
2021                if (pvsCost > stat.maxPvs)
2022                  stat.maxPvs = pvsCost;
2023               
2024                stat.avgPvs += pvsCost;
2025
2026
2027                if (mPerViewCellStat[i].pvsSize > 0.0f)
2028                  mPerViewCellStat[i].relPvsIncrease = (pvsCost - mPerViewCellStat[i].pvsSize)/mPerViewCellStat[i].pvsSize;
2029               
2030                stat.avgRelPvsIncrease += mPerViewCellStat[i].relPvsIncrease;
2031               
2032                // update the pvs size
2033                mPerViewCellStat[i].pvsSize = pvsCost;
2034               
2035               
2036               
2037                if (evaluateFilter) {
2038                  ObjectPvs filteredPvs;
2039                  PvsFilterStatistics fstat = ApplyFilter2(viewcell,
2040                                                                                                   false,
2041                                                                                                   1.0f,
2042                                                                                                   filteredPvs);
2043                 
2044                  float filteredCost = filteredPvs.EvalPvsCost();
2045                  stat.avgFilteredPvs += filteredCost;
2046                  stat.avgFilterContribution += filteredCost - pvsCost;
2047                 
2048                  stat.avgFilterRadius += fstat.mAvgFilterRadius;
2049                  int sum = fstat.mGlobalFilterCount + fstat.mLocalFilterCount;
2050                  if (sum) {
2051                        stat.avgFilterRatio += fstat.mLocalFilterCount /
2052                          (float) sum;
2053                  }
2054                 
2055                } else {
2056                  stat.avgFilteredPvs += pvsCost;
2057                  stat.avgFilterContribution += 0;
2058                }
2059               
2060                ++ stat.viewcells;
2061          }
2062        }
2063
2064 
2065 
2066  if (stat.viewcells) {
2067        stat.avgPvs/=stat.viewcells;
2068        stat.avgFilteredPvs/=stat.viewcells;
2069        stat.avgFilterContribution/=stat.viewcells;
2070        stat.avgFilterRadius/=stat.viewcells;
2071        stat.avgFilterRatio/=stat.viewcells;
2072        stat.avgRelPvsIncrease/=stat.viewcells;
2073
2074        // evaluate std deviation of relPvsIncrease
2075        float sum=0.0f;
2076        for (i=0; i < stat.viewcells; i++) {
2077          sum += sqr(mPerViewCellStat[i].relPvsIncrease - stat.avgRelPvsIncrease);
2078        }
2079        stat.devRelPvsIncrease = sqrt(sum/stat.viewcells);
2080  }
2081 
2082}
2083
2084
2085void ViewCellsManager::PrintPvsStatistics(ostream &s)
2086{
2087  s<<"############# Viewcell PVS STAT ##################\n";
2088  PvsStatistics pvsStat;
2089  GetPvsStatistics(pvsStat);
2090  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
2091  s<<"#AVG_FILTERED_PVS\n"<<pvsStat.avgFilteredPvs<<endl;
2092  s<<"#AVG_FILTER_CONTRIBUTION\n"<<pvsStat.avgFilterContribution<<endl;
2093  s<<"#AVG_FILTER_RADIUS\n"<<pvsStat.avgFilterRadius<<endl;
2094  s<<"#AVG_FILTER_RATIO\n"<<pvsStat.avgFilterRatio<<endl;
2095  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
2096  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
2097  s<<"#AVG_REL_PVS_INCREASE\n"<<pvsStat.avgRelPvsIncrease<<endl;
2098  s<<"#DEV_REL_PVS_INCREASE\n"<<pvsStat.devRelPvsIncrease<<endl;
2099}
2100
2101
2102int ViewCellsManager::CastBeam(Beam &beam)
2103{
2104        return 0;
2105}
2106
2107
2108ViewCellContainer &ViewCellsManager::GetViewCells()
2109{
2110        return mViewCells;
2111}
2112
2113
2114void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
2115{
2116        mViewSpaceBox = box;
2117       
2118        // hack: create clip plane relative to new view space box
2119        CreateClipPlane();
2120        // the total area of the view space has changed
2121        mTotalAreaValid = false;
2122}
2123
2124
2125void ViewCellsManager::CreateClipPlane()
2126{
2127        int axis = 0;
2128        float pos;
2129        bool orientation;
2130        Vector3 absPos;
2131
2132        Environment::GetSingleton()->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
2133        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
2134
2135        if (axis < 0)
2136        {
2137                axis = -axis;
2138                orientation = false;
2139                absPos = mViewSpaceBox.Max() -  mViewSpaceBox.Size() * pos;
2140        }
2141        else
2142        {
2143                orientation = true;
2144                absPos = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
2145        }
2146
2147        mClipPlaneForViz = AxisAlignedPlane(axis, absPos[axis]);
2148        mClipPlaneForViz.mOrientation = orientation;
2149}
2150
2151
2152AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
2153{
2154        return mViewSpaceBox;
2155}
2156
2157
2158void ViewCellsManager::ResetViewCells()
2159{
2160        // recollect view cells
2161        mViewCells.clear();
2162        CollectViewCells();
2163       
2164        // stats are computed once more
2165        EvaluateViewCellsStats();
2166
2167        // has to be recomputed
2168        mTotalAreaValid = false;
2169}
2170
2171
2172int ViewCellsManager::GetMaxPvsSize() const
2173{
2174        return mMaxPvsSize;
2175}
2176
2177
2178int ViewCellsManager::GetMinPvsSize() const
2179{
2180        return mMinPvsSize;
2181}
2182
2183
2184
2185float ViewCellsManager::GetMaxPvsRatio() const
2186{
2187        return mMaxPvsRatio;
2188}
2189
2190
2191inline static void AddSampleToPvs(ObjectPvs &pvs,
2192                                                                  Intersectable *obj,
2193                                                                  const float pdf)
2194{
2195#if PVS_ADD_DIRTY
2196        pvs.AddSampleDirtyCheck(obj, pdf);
2197
2198        if (pvs.RequiresResort())
2199        {
2200                pvs.SimpleSort();
2201        }
2202#else
2203        pvs.AddSample(obj, pdf);
2204#endif
2205}
2206
2207
2208void ViewCellsManager::ComputeViewCellContribution(ViewCell *viewCell,
2209                                                                                                   VssRay &ray,
2210                                                                                                   Intersectable *obj,
2211                                                                                                   const Vector3 &pt,
2212                                                                                                   const bool addRays)
2213{
2214  // check if we are outside of view space
2215        if (!obj || !viewCell->GetValid())
2216                return;
2217       
2218        // if ray not outside of view space
2219        float relContribution = 0.0f;
2220        float absContribution = 0.0f;
2221       
2222        if (obj)
2223          {
2224                // todo: maybe not correct for kd node pvs
2225                if (addRays) {
2226                  float pdf = viewCell->GetPvs().AddSampleDirtyCheck(obj, ray.mPdf);
2227                  if (pdf == ray.mPdf) {
2228                        absContribution = 1.0f;
2229                        if (viewCell->GetPvs().RequiresResort())
2230                          viewCell->GetPvs().SimpleSort();
2231                  }
2232                          } else {
2233                                if (viewCell->GetPvs().GetSampleContribution(
2234                                                                                                                         obj,
2235                                                                                                                         ray.mPdf,
2236                                                                                                                         relContribution))
2237                                  absContribution = 1.0f;
2238                          }
2239                // $$ clear the relative contribution as it is currently not correct anyway
2240                relContribution = 0.0f;
2241               
2242                if (absContribution == 1.0f) {
2243                  ++ ray.mPvsContribution;
2244                  relContribution = 1.0f;
2245                 
2246                 
2247#if CONTRIBUTION_RELATIVE_TO_PVS_SIZE
2248                  relContribution /= viewcell->GetPvs().GetSize();
2249#endif
2250                 
2251#if DIST_WEIGHTED_CONTRIBUTION
2252                  // recalculate the contribution - weight the 1.0f contribution by the sqr distance to the
2253                  // object-> a new contribution in the proximity of the viewcell has a larger weight!
2254                  relContribution /= SqrDistance(GetViewCellBox(viewcell).Center(),
2255                                                                                 ray.mTermination);
2256                 
2257#endif
2258                }
2259               
2260#if SUM_RAY_CONTRIBUTIONS || AVG_RAY_CONTRIBUTIONS
2261                ray.mRelativePvsContribution += relContribution;
2262#else
2263                // recalculate relative contribution - use max of Rel Contribution
2264                if (ray.mRelativePvsContribution < relContribution)
2265                  ray.mRelativePvsContribution = relContribution;
2266#endif
2267          }
2268       
2269}
2270
2271
2272float
2273ViewCellsManager::ComputeSampleContribution(VssRay &ray,
2274                                                                                        const bool addRays,
2275                                                                                        const bool storeViewCells)
2276{
2277        ray.mPvsContribution = 0;
2278        ray.mRelativePvsContribution = 0.0f;
2279
2280        if (!ray.mTerminationObject)
2281                return 0.0f;
2282
2283        ViewCellContainer viewCells;
2284
2285        static Ray hray;
2286        hray.Init(ray);
2287
2288        float tmin = 0, tmax = 1.0;
2289
2290        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax)) {
2291          //      cerr<<"ray outside view space box\n";
2292          return 0;
2293        }
2294
2295        Vector3 origin = hray.Extrap(tmin);
2296        Vector3 termination = hray.Extrap(tmax);
2297
2298        ViewCell::NewMail();
2299
2300        // traverse the view space subdivision
2301        CastLineSegment(origin, termination, viewCells);
2302
2303       
2304        if (storeViewCells)
2305        {       
2306          // copy viewcells memory efficiently
2307#if VSS_STORE_VIEWCELLS
2308          ray.mViewCells.reserve(viewCells.size());
2309          ray.mViewCells = viewCells;
2310#else
2311          cerr<<"Vss store viewcells not supported."<<endl;
2312          exit(1);
2313#endif
2314        }
2315
2316        // optain pvs entry (can be different from hit object)
2317        Intersectable *terminationObj = GetIntersectable(ray, true);
2318
2319        ViewCellContainer::const_iterator it = viewCells.begin();
2320
2321        for (; it != viewCells.end(); ++ it)
2322        {
2323                ComputeViewCellContribution(*it,
2324                                                                        ray,
2325                                                                        terminationObj,
2326                                                                        ray.mTermination,
2327                                                                        addRays);
2328        }
2329
2330#if AVG_RAY_CONTRIBUTIONS
2331        ray.mRelativePvsContribution /= (float)viewCells.size();
2332#endif
2333 
2334#if USE_RAY_LENGTH_AS_CONTRIBUTION
2335        float c = 0.0f;
2336        if (terminationObj)
2337          c = ray.Length();
2338        ray.mRelativePvsContribution = ray.mPvsContribution = c;
2339        return c;
2340#else
2341        return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
2342          (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
2343#endif
2344}
2345
2346
2347void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
2348                                                                  const int maxSize,
2349                                                                  VssRayContainer &usedRays,
2350                                                                  VssRayContainer *savedRays) const
2351{
2352        const int limit = min(maxSize, (int)sourceRays.size());
2353        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
2354
2355        VssRayContainer::const_iterator it, it_end = sourceRays.end();
2356        for (it = sourceRays.begin(); it != it_end; ++ it)
2357        {
2358                if (Random(1.0f) < prop)
2359                        usedRays.push_back(*it);
2360                else if (savedRays)
2361                        savedRays->push_back(*it);
2362        }
2363}
2364
2365
2366float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
2367{
2368        return (float)mViewCellsTree->GetPvsCost(viewCell);
2369}
2370
2371
2372float ViewCellsManager::GetAccVcArea()
2373{
2374        // if already computed
2375        if (mTotalAreaValid)
2376        {
2377                return mTotalArea;
2378        }
2379
2380        mTotalArea = 0;
2381        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2382
2383        for (it = mViewCells.begin(); it != it_end; ++ it)
2384        {
2385                //Debug << "area: " << GetArea(*it);
2386        mTotalArea += GetArea(*it);
2387        }
2388
2389        mTotalAreaValid = true;
2390
2391        return mTotalArea;
2392}
2393
2394
2395void ViewCellsManager::PrintStatistics(ostream &s) const
2396{
2397        s << mCurrentViewCellsStats << endl;
2398}
2399
2400
2401void ViewCellsManager::CreateUniqueViewCellIds()
2402{
2403        if (ViewCellsTreeConstructed())
2404        {
2405                mViewCellsTree->CreateUniqueViewCellsIds();
2406        }
2407        else // no view cells tree, handle view cells "myself"
2408        {
2409                int i = 0;
2410                ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2411                for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
2412                {
2413                        if ((*vit)->GetId() != OUT_OF_BOUNDS_ID)
2414                        {
2415                                mViewCells[i]->SetId(i ++);
2416                        }
2417                }
2418        }
2419}
2420
2421
2422void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter,
2423                                                                                         const AxisAlignedBox3 *sceneBox,
2424                                                                                         const bool colorCode,
2425                                                                                         const AxisAlignedPlane *clipPlane
2426                                                                                         ) const
2427{
2428        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2429
2430        for (it = mViewCells.begin(); it != it_end; ++ it)
2431        {
2432                if (!mOnlyValidViewCells || (*it)->GetValid())
2433                {
2434                        ExportColor(exporter, *it, colorCode); 
2435                        ExportViewCellGeometry(exporter, *it, sceneBox, clipPlane);
2436                }
2437        }
2438}
2439
2440
2441void ViewCellsManager::CreateViewCellMeshes()
2442{
2443        // convert to meshes
2444        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2445
2446        for (it = mViewCells.begin(); it != it_end; ++ it)
2447        {
2448                if (!(*it)->GetMesh())
2449                {
2450                        CreateMesh(*it);
2451                }
2452        }
2453}
2454
2455
2456bool ViewCellsManager::ExportViewCells(const string filename,
2457                                                                           const bool exportPvs,
2458                                                                           const ObjectContainer &objects)
2459{
2460        return false;
2461}
2462
2463
2464void ViewCellsManager::CollectViewCells(const int n)
2465{
2466        mNumActiveViewCells = n;
2467        mViewCells.clear();
2468        // implemented in subclasses
2469        CollectViewCells();
2470}
2471
2472
2473void ViewCellsManager::SetViewCellActive(ViewCell *vc) const
2474{
2475        ViewCellContainer leaves;
2476        // sets the pointers to the currently active view cells
2477        mViewCellsTree->CollectLeaves(vc, leaves);
2478
2479        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2480        for (lit = leaves.begin(); lit != lit_end; ++ lit)
2481        {
2482                dynamic_cast<ViewCellLeaf *>(*lit)->SetActiveViewCell(vc);
2483        }
2484}
2485
2486
2487void ViewCellsManager::SetViewCellsActive()
2488{
2489        // collect leaf view cells and set the pointers to
2490        // the currently active view cells
2491        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2492
2493        for (it = mViewCells.begin(); it != it_end; ++ it)
2494        {
2495                SetViewCellActive(*it);
2496        }
2497}
2498
2499
2500int ViewCellsManager::GetMaxFilterSize() const
2501{
2502        return mMaxFilterSize; 
2503}
2504
2505
2506static const bool USE_ASCII = true;
2507
2508
2509bool ViewCellsManager::ExportBoundingBoxes(const string filename,
2510                                                                                   const ObjectContainer &objects) const
2511{
2512        ObjectContainer::const_iterator it, it_end = objects.end();
2513       
2514        if (USE_ASCII)
2515        {
2516                ofstream boxesOut(filename.c_str());
2517                if (!boxesOut.is_open())
2518                        return false;
2519
2520                for (it = objects.begin(); it != it_end; ++ it)
2521                {
2522                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
2523                        const AxisAlignedBox3 box = mi->GetBox();
2524
2525                        boxesOut << mi->GetId() << " "
2526                                         << box.Min().x << " "
2527                                         << box.Min().y << " "
2528                                         << box.Min().z << " "
2529                                         << box.Max().x << " "
2530                                         << box.Max().y << " "
2531                     << box.Max().z << endl;   
2532                }
2533
2534                boxesOut.close();
2535        }
2536        else
2537        {
2538                ofstream boxesOut(filename.c_str(), ios::binary);
2539
2540                if (!boxesOut.is_open())
2541                        return false;
2542
2543                for (it = objects.begin(); it != it_end; ++ it)
2544                {       
2545                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
2546                        const AxisAlignedBox3 box = mi->GetBox();
2547                        Vector3 bmin = box.Min();
2548                        Vector3 bmax = box.Max();
2549                        int id = mi->GetId();
2550
2551                        boxesOut.write(reinterpret_cast<char *>(&id), sizeof(int));
2552                        boxesOut.write(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
2553                        boxesOut.write(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
2554                }
2555               
2556                boxesOut.close();
2557        }
2558
2559        return true;
2560}
2561
2562
2563bool ViewCellsManager::LoadBoundingBoxes(const string filename,
2564                                                                                 IndexedBoundingBoxContainer &boxes) const
2565{
2566        Vector3 bmin, bmax;
2567        int id;
2568
2569        if (USE_ASCII)
2570        {
2571                ifstream boxesIn(filename.c_str());
2572               
2573                if (!boxesIn.is_open())
2574                {
2575                        cout << "failed to open file " << filename << endl;
2576                        return false;
2577                }
2578
2579                string buf;
2580                while (!(getline(boxesIn, buf)).eof())
2581                {
2582                        sscanf(buf.c_str(), "%d %f %f %f %f %f %f",
2583                                   &id, &bmin.x, &bmin.y, &bmin.z,
2584                                   &bmax.x, &bmax.y, &bmax.z);
2585               
2586                        AxisAlignedBox3 box(bmin, bmax);
2587                        //      MeshInstance *mi = new MeshInstance();
2588                        // HACK: set bounding box to new box
2589                        //mi->mBox = box;
2590
2591                        boxes.push_back(IndexedBoundingBox(id, box));
2592                }
2593
2594                boxesIn.close();
2595        }
2596        else
2597        {
2598                ifstream boxesIn(filename.c_str(), ios::binary);
2599
2600                if (!boxesIn.is_open())
2601                        return false;
2602
2603                while (1)
2604                {
2605                        boxesIn.read(reinterpret_cast<char *>(&id), sizeof(Vector3));
2606                        boxesIn.read(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
2607                        boxesIn.read(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
2608                       
2609                        if (boxesIn.eof())
2610                                break;
2611
2612                       
2613                        AxisAlignedBox3 box(bmin, bmax);
2614                        MeshInstance *mi = new MeshInstance(NULL);
2615
2616                        // HACK: set bounding box to new box
2617                        //mi->mBox = box;
2618                        //boxes.push_back(mi);
2619                        boxes.push_back(IndexedBoundingBox(id, box));
2620                }
2621
2622                boxesIn.close();
2623        }
2624
2625        return true;
2626}
2627
2628
2629float ViewCellsManager::GetFilterWidth()
2630{
2631        return mFilterWidth;
2632}
2633
2634
2635float ViewCellsManager::GetAbsFilterWidth()
2636{
2637        return Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
2638}
2639
2640
2641void ViewCellsManager::UpdateScalarPvsSize(ViewCell *vc,
2642                                                                                   const float pvsCost,
2643                                                                                   const int entriesInPvs) const
2644{
2645        vc->mPvsCost = pvsCost;
2646        vc->mEntriesInPvs = entriesInPvs;
2647
2648        vc->mPvsSizeValid = true;
2649}
2650
2651
2652void
2653ViewCellsManager::ApplyFilter(ViewCell *viewCell,
2654                                                          KdTree *kdTree,
2655                                                          const float viewSpaceFilterSize,
2656                                                          const float spatialFilterSize,
2657                                                          ObjectPvs &pvs
2658                                                          )
2659{
2660  // extend the pvs of the viewcell by pvs of its neighbors
2661  // and apply spatial filter by including all neighbors of the objects
2662  // in the pvs
2663
2664  // get all viewcells intersecting the viewSpaceFilterBox
2665  // and compute the pvs union
2666 
2667  //Vector3 center = viewCell->GetBox().Center();
2668  //  Vector3 center = m->mBox.Center();
2669
2670        //  AxisAlignedBox3 box(center - Vector3(viewSpaceFilterSize/2),
2671        //                                        center + Vector3(viewSpaceFilterSize/2));
2672        if (!ViewCellsConstructed())
2673                return;
2674
2675        if (viewSpaceFilterSize >= 0.0f) {
2676
2677                const bool usePrVS = false;
2678
2679                if (!usePrVS) {
2680                        AxisAlignedBox3 box = GetViewCellBox(viewCell);
2681                        box.Enlarge(Vector3(viewSpaceFilterSize/2));
2682
2683                        ViewCellContainer viewCells;
2684                        ComputeBoxIntersections(box, viewCells);
2685
2686                        //  cout<<"box="<<box<<endl;
2687                        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
2688
2689                        for (; it != it_end; ++ it)
2690                        {
2691                                ObjectPvs interPvs;
2692                                //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
2693                                ObjectPvs::Merge(interPvs, pvs, (*it)->GetPvs());
2694
2695                                pvs = interPvs;
2696                        }
2697                } else
2698                {
2699                        PrVs prvs;
2700                        AxisAlignedBox3 box = GetViewCellBox(viewCell);
2701
2702                        //  mViewCellsManager->SetMaxFilterSize(1);
2703                        GetPrVS(box.Center(), prvs, viewSpaceFilterSize);
2704                        pvs = prvs.mViewCell->GetPvs();
2705                        DeleteLocalMergeTree(prvs.mViewCell);
2706                }
2707        }
2708        else
2709        {
2710                pvs = viewCell->GetPvs();
2711        }
2712
2713        if (spatialFilterSize >=0.0f)
2714                ApplySpatialFilter(kdTree, spatialFilterSize, pvs);
2715
2716}
2717
2718
2719
2720void
2721ViewCellsManager::ApplyFilter(KdTree *kdTree,
2722                                                          const float relViewSpaceFilterSize,
2723                                                          const float relSpatialFilterSize
2724                                                          )
2725{
2726
2727        if (!ViewCellsConstructed())
2728                return;
2729
2730        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2731
2732        ObjectPvs *newPvs;
2733        newPvs = new ObjectPvs[mViewCells.size()];
2734
2735        float viewSpaceFilterSize = Magnitude(mViewSpaceBox.Size())*relViewSpaceFilterSize;
2736        float spatialFilterSize = Magnitude(kdTree->GetBox().Size())*relSpatialFilterSize;
2737       
2738        int i;
2739        for (i=0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
2740          ApplyFilter(*it,
2741                                  kdTree,
2742                                  viewSpaceFilterSize,
2743                                  spatialFilterSize,
2744                                  newPvs[i]
2745                                  );
2746        }
2747       
2748        // now replace all pvss
2749        for (i = 0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
2750         
2751          ObjectPvs &pvs = (*it)->GetPvs();
2752          pvs.Clear();
2753          pvs = newPvs[i];
2754          newPvs[i].Clear();
2755        }
2756
2757        delete [] newPvs;
2758}
2759
2760
2761void
2762ViewCellsManager::ApplySpatialFilter(
2763                                                                         KdTree *kdTree,
2764                                                                         const float spatialFilterSize,
2765                                                                         ObjectPvs &pvs
2766                                                                         )
2767{
2768  // now compute a new Pvs by including also objects intersecting the
2769  // extended boxes of visible objects
2770  Intersectable::NewMail();
2771
2772  ObjectPvsIterator pit = pvs.GetIterator();
2773
2774  while (pit.HasMoreEntries())
2775  {             
2776          ObjectPvsEntry entry = pit.Next();
2777 
2778          Intersectable *object = entry.mObject;
2779      object->Mail();
2780  }
2781
2782  ObjectPvs nPvs;
2783  int nPvsSize = 0;
2784 
2785  ObjectPvsIterator pit2 = pvs.GetIterator();
2786
2787  while (pit2.HasMoreEntries())
2788  {             
2789          // now go through the pvs again
2790          ObjectPvsEntry entry = pit2.Next();
2791          Intersectable *object = entry.mObject;
2792
2793          //    Vector3 center = object->GetBox().Center();
2794          //    AxisAlignedBox3 box(center - Vector3(spatialFilterSize/2),
2795          //                                            center + Vector3(spatialFilterSize/2));
2796
2797          AxisAlignedBox3 box = object->GetBox();
2798          box.Enlarge(Vector3(spatialFilterSize/2));
2799
2800          ObjectContainer objects;
2801
2802          // $$ warning collect objects takes only unmailed ones!
2803          kdTree->CollectObjects(box, objects);
2804          //    cout<<"collected objects="<<objects.size()<<endl;
2805          ObjectContainer::const_iterator noi = objects.begin();
2806          for (; noi != objects.end(); ++ noi)
2807          {
2808                  Intersectable *o = *noi;
2809                 
2810                  // $$ JB warning: pdfs are not correct at this point!   
2811                  nPvs.AddSample(o, Limits::Small);
2812                  nPvsSize ++;
2813          }
2814  }
2815
2816  // cout<<"nPvs size = "<<nPvsSize<<endl;
2817  pvs.MergeInPlace(nPvs);
2818}
2819
2820
2821void ViewCellsManager::MergeViewCellsRecursivly(ObjectPvs &pvs,
2822                                                                                                const ViewCellContainer &viewCells) const
2823{
2824        MergeViewCellsRecursivly(pvs, viewCells, 0, (int)viewCells.size() - 1);
2825}
2826
2827
2828void ViewCellsManager::MergeViewCellsRecursivly(ObjectPvs &pvs,
2829                                                                                                const ViewCellContainer &viewCells,
2830                                                                                                const int leftIdx,
2831                                                                                                const int rightIdx) const
2832{
2833        if (leftIdx == rightIdx)
2834        {
2835                pvs = viewCells[leftIdx]->GetPvs();
2836        }
2837        else
2838        {
2839                const int midSplit = (leftIdx + rightIdx) / 2;
2840       
2841                ObjectPvs leftPvs, rightPvs;
2842                MergeViewCellsRecursivly(leftPvs, viewCells, leftIdx, midSplit);
2843                MergeViewCellsRecursivly(rightPvs, viewCells, midSplit, rightIdx);
2844
2845        ObjectPvs::Merge(pvs, leftPvs, rightPvs);
2846        }
2847}
2848
2849
2850PvsFilterStatistics
2851ViewCellsManager::ApplyFilter2(ViewCell *viewCell,
2852                                                           const bool useViewSpaceFilter,
2853                                                           const float filterSize,
2854                                                           ObjectPvs &pvs,
2855                                                           vector<AxisAlignedBox3> *filteredBoxes
2856                                                           )
2857{
2858  //cout<<"y";
2859  PvsFilterStatistics stats;
2860
2861  AxisAlignedBox3 vbox = GetViewCellBox(viewCell);
2862  Vector3 center = vbox.Center();
2863  // copy the PVS
2864  Intersectable::NewMail();
2865  ObjectPvs basePvs = viewCell->GetPvs();
2866  ObjectPvsIterator pit = basePvs.GetIterator();
2867
2868  pvs.Reserve(viewCell->GetFilteredPvsSize());
2869
2870  if (!mUseKdPvs)
2871  {
2872          // first mark all objects from this pvs
2873          while (pit.HasMoreEntries()) 
2874          {
2875                  ObjectPvsEntry entry = pit.Next();
2876                  Intersectable *object = entry.mObject;
2877                  object->Mail();
2878          }
2879  }
2880 
2881  int pvsSize = 0;
2882  int nPvsSize = 0;
2883  float samples = (float)basePvs.GetSamples();
2884 
2885  Debug<<"f #s="<<samples<<"  pvs size = "<<basePvs.GetSize();
2886  //  cout<<"Filter size = "<<filterSize<<endl;
2887  //  cout<<"vbox = "<<vbox<<endl;
2888  //  cout<<"center = "<<center<<endl;
2889
2890
2891   // Minimal number of local samples to take into account
2892   // the local sampling density.
2893   // The size of the filter is a minimum of the conservative
2894   // local sampling density estimate (#rays intersecting teh viewcell and
2895   // the object)
2896   // and gobal estimate for the view cell
2897   // (total #rays intersecting the viewcell)
2898  int minLocalSamples = 2;
2899 
2900  float viewCellRadius = 0.5f*Magnitude(vbox.Diagonal());
2901 
2902  // now compute the filter box around the current viewCell
2903 
2904  if (useViewSpaceFilter) {
2905        //      float radius = Max(viewCellRadius/100.0f, avgRadius - viewCellRadius);
2906        float radius = viewCellRadius/100.0f;
2907        vbox.Enlarge(radius);
2908        cout<<"vbox = "<<vbox<<endl;
2909        ViewCellContainer viewCells;
2910        ComputeBoxIntersections(vbox, viewCells);
2911       
2912        ViewCellContainer::const_iterator it = viewCells.begin(),
2913          it_end = viewCells.end();
2914        int i = 0;
2915        for (i=0; it != it_end; ++ it, ++ i)
2916          if ((*it) != viewCell) {
2917                //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
2918                basePvs.MergeInPlace((*it)->GetPvs());
2919          }
2920       
2921        // update samples and globalC
2922        samples = (float)pvs.GetSamples();
2923        //      cout<<"neighboring viewcells = "<<i-1<<endl;
2924        //      cout<<"Samples' = "<<samples<<endl;
2925  }
2926 
2927  // Minimal number of samples so that filtering takes place
2928#define MIN_SAMPLES  50
2929 
2930  if (samples > MIN_SAMPLES) {
2931        float globalC = 2.0f*filterSize/sqrt(samples);
2932       
2933        pit = basePvs.GetIterator();
2934       
2935        ObjectContainer objects;
2936       
2937        while (pit.HasMoreEntries()) {         
2938          ObjectPvsEntry entry = pit.Next();
2939         
2940          Intersectable *object = entry.mObject;
2941          // compute filter size based on the distance and the numebr of samples
2942          AxisAlignedBox3 box = object->GetBox();
2943         
2944          float distance = Distance(center, box.Center());
2945          float globalRadius = distance*globalC;
2946         
2947          int objectSamples = (int)entry.mData.mSumPdf;
2948          float localRadius = MAX_FLOAT;
2949         
2950          localRadius = filterSize*0.5f*Magnitude(box.Diagonal())/
2951                sqrt((float)objectSamples);
2952         
2953          //      cout<<"os="<<objectSamples<<" lr="<<localRadius<<" gr="<<globalRadius<<endl;
2954         
2955          // now compute the filter size
2956          float radius;
2957         
2958#if 0
2959          if (objectSamples <= 1) {
2960                if (localRadius > globalRadius) {
2961                  radius = 0.5flRadius;
2962                  stats.mLocalFilterCount++;
2963                } else {
2964                  radius = globalRadius;
2965                  stats.mGlobalFilterCount++;
2966                }
2967          } else {
2968                radius = localRadius;
2969                stats.mLocalFilterCount++;
2970          }
2971#else
2972          radius = 0.5f*globalRadius + 0.5f*localRadius;
2973
2974          if (localRadius > globalRadius)
2975                stats.mLocalFilterCount++;
2976          else
2977                stats.mGlobalFilterCount++;
2978#endif
2979         
2980          stats.mAvgFilterRadius += radius;
2981         
2982          // cout<<"box = "<<box<<endl;
2983          //    cout<<"distance = "<<distance<<endl;
2984          //    cout<<"radiues = "<<radius<<endl;
2985         
2986          box.Enlarge(Vector3(radius));
2987
2988          if (filteredBoxes)
2989                filteredBoxes->push_back(box);
2990
2991          objects.clear();
2992          // $$ warning collect objects takes only unmailed ones!
2993          CollectObjects(box, objects);
2994          //    cout<<"collected objects="<<objects.size()<<endl;
2995          ObjectContainer::const_iterator noi = objects.begin();
2996          for (; noi != objects.end(); ++ noi) {
2997                Intersectable *o = *noi;
2998                // $$ JB warning: pdfs are not correct at this point!     
2999                pvs.AddSampleDirty(o, Limits::Small);
3000          }
3001        }
3002        stats.mAvgFilterRadius /= (stats.mLocalFilterCount + stats.mGlobalFilterCount);
3003  }
3004 
3005  Debug<<" nPvs size = "<<pvs.GetSize()<<endl;
3006 
3007  if (!mUseKdPvs)
3008  {
3009          // copy the base pvs to the new pvs
3010          pit = basePvs.GetIterator();
3011          while (pit.HasMoreEntries())
3012          {             
3013                  ObjectPvsEntry entry = pit.Next();
3014                  pvs.AddSampleDirty(entry.mObject, entry.mData.mSumPdf);
3015          }
3016  }
3017 
3018  pvs.SimpleSort();
3019  viewCell->SetFilteredPvsSize(pvs.GetSize());
3020 
3021  Intersectable::NewMail();
3022  return stats;
3023}
3024
3025
3026
3027void ViewCellsManager::ExportColor(Exporter *exporter,
3028                                                                   ViewCell *vc,
3029                                                                   bool colorCode) const
3030{
3031        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3032
3033        float importance = 0;
3034        static Material m;
3035        //cout << "color code: " << colorCode << endl;
3036        switch (mColorCode)
3037        {
3038        case 0: // Random
3039                {
3040                        if (vcValid)
3041                        {
3042                                m.mDiffuseColor.r = 0.2f + RandomValue(0.0f, 0.8f);
3043                                m.mDiffuseColor.g = 0.2f + RandomValue(0.0f, 0.8f);
3044                                m.mDiffuseColor.b = 0.2f + RandomValue(0.0f, 0.8f);
3045                        }
3046                        else
3047                        {
3048                                m.mDiffuseColor.r = 0.0f;
3049                                m.mDiffuseColor.g = 1.0f;
3050                                m.mDiffuseColor.b = 0.0f;
3051                        }
3052
3053                        exporter->SetForcedMaterial(m);
3054                        return;
3055                }
3056               
3057        case 1: // pvs
3058                {
3059                        if (mCurrentViewCellsStats.maxPvs)
3060                        {
3061                                importance = (float)mViewCellsTree->GetPvsCost(vc) /
3062                                                         (float)mCurrentViewCellsStats.maxPvs;
3063                        }
3064                }
3065                break;
3066        case 2: // merges
3067                {
3068            const int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
3069                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
3070                }
3071                break;
3072#if 0
3073        case 3: // merge tree differene
3074                {
3075                        importance = (float)GetMaxTreeDiff(vc) /
3076                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3077
3078                }
3079                break;
3080#endif
3081        default:
3082                break;
3083        }
3084
3085        // special color code for invalid view cells
3086        m.mDiffuseColor.r = importance;
3087        m.mDiffuseColor.b = 1.0f;//vcValid ? 0.0f : 1.0f;
3088        m.mDiffuseColor.g = 1.0f - importance;
3089
3090        //Debug << "importance: " << importance << endl;
3091        exporter->SetForcedMaterial(m);
3092}
3093
3094
3095void ViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3096                                                                                          vector<MergeCandidate> &candidates)
3097{
3098        // implemented in subclasses
3099}
3100
3101
3102void ViewCellsManager::UpdatePvsForEvaluation()
3103{
3104        ObjectPvs objPvs;
3105        UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), objPvs);
3106}
3107
3108void ViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
3109{
3110        // terminate traversal
3111        if (root->IsLeaf())
3112        {
3113                //cout << "updating leaf" << endl;
3114                // we assume that pvs is explicitly stored in leaves
3115                pvs = root->GetPvs();
3116                UpdateScalarPvsSize(root, pvs.EvalPvsCost(), pvs.GetSize());
3117                return;
3118        }
3119
3120        ////////////////
3121        //-- interior node => propagate pvs up the tree
3122
3123        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
3124
3125        // reset interior pvs
3126        interior->GetPvs().Clear();
3127        // reset recursive pvs
3128        pvs.Clear();
3129
3130        // pvss of child nodes
3131        vector<ObjectPvs> pvsList;
3132        pvsList.resize((int)interior->mChildren.size());
3133
3134        ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
3135       
3136        int i = 0;
3137
3138        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ i)
3139        {
3140                //////////////////
3141                //-- recursivly compute child pvss
3142                UpdatePvsForEvaluation(*vit, pvsList[i]/*objPvs*/);
3143        }
3144
3145#if 1
3146        Intersectable::NewMail();
3147
3148        //-- faster way of computing pvs:
3149        //-- construct merged pvs by adding
3150        //-- and only those of the next pvs which were not mailed.
3151        //-- note: sumpdf is not correct!!
3152
3153        vector<ObjectPvs>::iterator oit = pvsList.begin();
3154
3155        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
3156        {
3157                ObjectPvsIterator pit = (*oit).GetIterator();
3158               
3159                // first mark all object from this pvs
3160                while (pit.HasMoreEntries())
3161                {               
3162                        ObjectPvsEntry entry = pit.Next();
3163
3164                        Intersectable *intersect = entry.mObject;
3165
3166                        if (!intersect->Mailed())
3167                        {
3168                                pvs.AddSample(intersect, entry.mData.mSumPdf);
3169                                intersect->Mail();
3170                        }
3171                }
3172        }
3173
3174        // store pvs in this node
3175        if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
3176        {
3177                interior->SetPvs(pvs);
3178        }
3179       
3180        // set new pvs size
3181        UpdateScalarPvsSize(interior, pvs.EvalPvsCost(), pvs.GetSize());
3182       
3183#else
3184        // really merge cells: slow put sumPdf is correct
3185        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
3186        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
3187#endif
3188}
3189
3190
3191
3192/*******************************************************************/
3193/*               BspViewCellsManager implementation                */
3194/*******************************************************************/
3195
3196
3197BspViewCellsManager::BspViewCellsManager(ViewCellsTree *vcTree, BspTree *bspTree):
3198ViewCellsManager(vcTree), mBspTree(bspTree)
3199{
3200        Environment::GetSingleton()->GetIntValue("BspTree.Construction.samples", mInitialSamples);
3201
3202        mBspTree->SetViewCellsManager(this);
3203        mBspTree->SetViewCellsTree(mViewCellsTree);
3204}
3205
3206
3207bool BspViewCellsManager::ViewCellsConstructed() const
3208{
3209        return mBspTree->GetRoot() != NULL;
3210}
3211
3212
3213ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3214{
3215        return new BspViewCell(mesh);
3216}
3217
3218
3219int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
3220                                                                                          const VssRayContainer &rays)
3221{
3222        // if view cells were already constructed, we can finish
3223        if (ViewCellsConstructed())
3224                return 0;
3225
3226        int sampleContributions = 0;
3227
3228        // construct view cells using the collected samples
3229        RayContainer constructionRays;
3230        VssRayContainer savedRays;
3231
3232        // choose a a number of rays based on the ratio of cast rays / requested rays
3233        const int limit = min(mInitialSamples, (int)rays.size());
3234        VssRayContainer::const_iterator it, it_end = rays.end();
3235
3236        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
3237
3238        for (it = rays.begin(); it != it_end; ++ it)
3239        {
3240                if (Random(1.0f) < prop)
3241                        constructionRays.push_back(new Ray(*(*it)));
3242                else
3243                        savedRays.push_back(*it);
3244        }
3245
3246    if (!mUsePredefinedViewCells)
3247        {
3248                // no view cells loaded
3249                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
3250                // collect final view cells
3251                mBspTree->CollectViewCells(mViewCells);
3252        }
3253        else
3254        {       
3255                // use predefined view cells geometry =>
3256                // contruct bsp hierarchy over them
3257                mBspTree->Construct(mViewCells);
3258        }
3259
3260        // destroy rays created only for construction
3261        CLEAR_CONTAINER(constructionRays);
3262
3263        Debug << mBspTree->GetStatistics() << endl;
3264        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
3265
3266        // recast rest of the rays
3267        if (SAMPLE_AFTER_SUBDIVISION)
3268                ComputeSampleContributions(savedRays, true, false);
3269
3270        // real meshes are contructed at this stage
3271        if (0)
3272        {
3273                cout << "finalizing view cells ... ";
3274                FinalizeViewCells(true);
3275                cout << "finished" << endl;     
3276        }
3277
3278        return sampleContributions;
3279}
3280
3281
3282void BspViewCellsManager::CollectViewCells()
3283{       
3284        if (!ViewCellsTreeConstructed())
3285        {       // view cells tree constructed 
3286                mBspTree->CollectViewCells(mViewCells);
3287        }
3288        else
3289        {       // we can use the view cells tree hierarchy to get the right set
3290                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
3291        }
3292}
3293
3294
3295float BspViewCellsManager::GetProbability(ViewCell *viewCell)
3296{
3297        if (1)
3298                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
3299        else
3300                // compute view cell area as subsititute for probability
3301                return GetArea(viewCell) / GetAccVcArea();
3302}
3303
3304
3305
3306int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
3307                                                                                 const Vector3 &termination,
3308                                                                                 ViewCellContainer &viewcells)
3309{
3310        return mBspTree->CastLineSegment(origin, termination, viewcells);
3311}
3312
3313
3314void ViewCellsManager::ExportMergedViewCells(const ObjectContainer &objects)
3315{
3316        // save color code
3317        const int savedColorCode = mColorCode;
3318
3319        Exporter *exporter;
3320
3321#if 0
3322        // export merged view cells
3323        mColorCode = 0; // use random colors
3324
3325        exporter = Exporter::GetExporter("merged_view_cells.wrl");
3326
3327        cout << "exporting view cells after merge ... ";
3328
3329        if (exporter)
3330        {
3331                if (mExportGeometry)
3332                {
3333                        exporter->ExportGeometry(objects);
3334                }
3335
3336                exporter->SetFilled();
3337                ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
3338
3339                delete exporter;
3340        }
3341        cout << "finished" << endl;
3342#endif
3343
3344        // export merged view cells using pvs color coding
3345        exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
3346        cout << "exporting view cells after merge (pvs size) ... ";     
3347
3348        if (exporter)
3349        {
3350                if (mExportGeometry)
3351                {
3352                        exporter->ExportGeometry(objects);
3353                }
3354
3355                exporter->SetFilled();
3356                mColorCode = 1;
3357
3358                ExportViewCellsForViz(exporter, NULL,  mColorCode, GetClipPlane());
3359
3360                delete exporter;
3361        }
3362        cout << "finished" << endl;
3363       
3364        mColorCode = savedColorCode;
3365}
3366
3367
3368int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
3369                                                                         const VssRayContainer &rays)
3370{
3371        if (!ViewCellsConstructed())
3372        {
3373                Debug << "view cells not constructed" << endl;
3374                return 0;
3375        }
3376       
3377        // view cells already finished before post processing step,
3378        // i.e., because they were loaded from disc
3379        if (mViewCellsFinished)
3380        {
3381                FinalizeViewCells(true);
3382                EvaluateViewCellsStats();
3383
3384                return 0;
3385        }
3386
3387        //////////////////
3388        //-- merge leaves of the view cell hierarchy   
3389       
3390        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
3391        long startTime = GetTime();
3392       
3393        VssRayContainer postProcessRays;
3394        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3395
3396        if (mMergeViewCells)
3397        {
3398                cout << "constructing visibility based merge tree" << endl;
3399                mViewCellsTree->ConstructMergeTree(rays, objects);
3400        }
3401        else
3402        {
3403                cout << "constructing spatial merge tree" << endl;
3404                ViewCell *root;
3405                // the spatial merge tree is difficult to build for
3406                // this type of construction, as view cells cover several
3407                // leaves => create dummy tree which is only 2 levels deep
3408                if (mUsePredefinedViewCells)
3409                {
3410                        root = ConstructDummyMergeTree(mBspTree->GetRoot());
3411                }
3412                else
3413                {
3414                        // create spatial merge hierarchy
3415                        root = ConstructSpatialMergeTree(mBspTree->GetRoot());
3416                }
3417               
3418                mViewCellsTree->SetRoot(root);
3419
3420                // recompute pvs in the whole hierarchy
3421                ObjectPvs pvs;
3422                UpdatePvsForEvaluation(root, pvs);
3423        }
3424
3425        cout << "finished" << endl;
3426        cout << "merged view cells in "
3427                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
3428
3429        Debug << "Postprocessing: Merged view cells in "
3430                << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
3431
3432       
3433        ////////////////////////
3434        //-- visualization and statistics after merge
3435
3436        if (1)
3437        {
3438                char mstats[100];
3439                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
3440                mViewCellsTree->ExportStats(mstats);
3441        }
3442
3443        // recompute view cells and stats
3444        ResetViewCells();
3445        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
3446
3447        //  visualization of the view cells
3448        if (1) ExportMergedViewCells(objects);
3449
3450        // compute final meshes and volume / area
3451        if (1) FinalizeViewCells(true);
3452       
3453        return 0;
3454}
3455
3456
3457BspViewCellsManager::~BspViewCellsManager()
3458{
3459}
3460
3461
3462int BspViewCellsManager::GetType() const
3463{
3464        return BSP;
3465}
3466
3467
3468void BspViewCellsManager::Visualize(const ObjectContainer &objects,
3469                                                                        const VssRayContainer &sampleRays)
3470{
3471        if (!ViewCellsConstructed())
3472                return;
3473       
3474        const int savedColorCode = mColorCode;
3475       
3476        if (1) // export final view cells
3477        {
3478                mColorCode = 1; // hack color code
3479                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
3480       
3481                cout << "exporting view cells after merge (pvs size) ... ";     
3482
3483                if (exporter)
3484                {
3485                        if (mExportGeometry)
3486                        {
3487                                exporter->ExportGeometry(objects);
3488                        }
3489
3490                        ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
3491                        delete exporter;
3492                }
3493                cout << "finished" << endl;
3494        }
3495
3496        // reset color code
3497        mColorCode = savedColorCode;
3498
3499
3500        //////////////////
3501        //-- visualization of the BSP splits
3502
3503        bool exportSplits = false;
3504        Environment::GetSingleton()->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
3505
3506        if (exportSplits)
3507        {
3508                cout << "exporting splits ... ";
3509                ExportSplits(objects);
3510                cout << "finished" << endl;
3511        }
3512
3513        int leafOut;
3514        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
3515        const int raysOut = 100;
3516        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
3517}
3518
3519
3520void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
3521{
3522        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3523
3524        if (exporter)
3525        {
3526                //exporter->SetFilled();
3527                if (mExportGeometry)
3528                {
3529                        exporter->ExportGeometry(objects);
3530                }
3531
3532                Material m;
3533                m.mDiffuseColor = RgbColor(1, 0, 0);
3534                exporter->SetForcedMaterial(m);
3535                exporter->SetWireframe();
3536
3537                exporter->ExportBspSplits(*mBspTree, true);
3538
3539                // NOTE: take forced material, else big scenes cannot be viewed
3540                m.mDiffuseColor = RgbColor(0, 1, 0);
3541                exporter->SetForcedMaterial(m);
3542                //exporter->ResetForcedMaterial();
3543
3544                delete exporter;
3545        }
3546}
3547
3548
3549void BspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
3550                                                                                                const int maxViewCells,
3551                                                                                                const bool sortViewCells,
3552                                                                                                const bool exportPvs,
3553                                                                                                const bool exportRays,
3554                                                                                                const int maxRays,
3555                                                                                                const string prefix,
3556                                                                                                VssRayContainer *visRays)
3557{
3558        if (sortViewCells)
3559        {       // sort view cells to visualize the largest view cells
3560                sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
3561        }
3562
3563        //////////
3564        //-- some view cells for output
3565
3566        ViewCell::NewMail();
3567        const int limit = min(maxViewCells, (int)mViewCells.size());
3568       
3569        for (int i = 0; i < limit; ++ i)
3570        {
3571                const int idx = sortViewCells ? (int)RandomValue(0, (float)mViewCells.size() - 0.5f) : i;
3572                ViewCell *vc = mViewCells[idx];
3573
3574                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
3575                        continue;
3576
3577                vc->Mail();
3578
3579                ObjectPvs pvs;
3580                mViewCellsTree->GetPvs(vc, pvs);
3581
3582                char s[64]; sprintf(s, "%sviewcell-%04d.wrl", prefix.c_str(), i);
3583                Exporter *exporter = Exporter::GetExporter(s);
3584               
3585                cout << "view cell " << idx << ": pvs cost=" << (int)mViewCellsTree->GetPvsCost(vc) << endl;
3586
3587                if (exportRays)
3588                {
3589                        ////////////
3590                        //-- export rays piercing this view cell
3591
3592                        // use rays stored with the view cells
3593                        VssRayContainer vcRays, vcRays2, vcRays3;
3594            VssRayContainer collectRays;
3595
3596                        // collect initial view cells
3597                        ViewCellContainer leaves;
3598                        mViewCellsTree->CollectLeaves(vc, leaves);
3599
3600                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3601                for (vit = leaves.begin(); vit != vit_end; ++ vit)
3602                        {       
3603                                // prepare some rays for output
3604                                VssRayContainer::const_iterator rit, rit_end = (*vit)->GetOrCreateRays()->end();
3605                                for (rit = (*vit)->GetOrCreateRays()->begin(); rit != rit_end; ++ rit)
3606                                {
3607                                        collectRays.push_back(*rit);
3608                                }
3609                        }
3610
3611                        const int raysOut = min((int)collectRays.size(), maxRays);
3612
3613                        // prepare some rays for output
3614                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3615                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3616                        {
3617                                const float p = RandomValue(0.0f, (float)collectRays.size());
3618                                if (p < raysOut)
3619                                {
3620                                        if ((*rit)->mFlags & VssRay::BorderSample)
3621                                        {
3622                                                vcRays.push_back(*rit);
3623                                        }
3624                                        else if ((*rit)->mFlags & VssRay::ReverseSample)
3625                                        {
3626                                                vcRays2.push_back(*rit);
3627                                        }
3628                                        else
3629                                        {
3630                                                vcRays3.push_back(*rit);
3631                                        }       
3632                                }
3633                        }
3634
3635                        exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
3636                        exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
3637                        exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
3638                }
3639               
3640                ////////////////
3641                //-- export view cell geometry
3642
3643                exporter->SetWireframe();
3644
3645                Material m;//= RandomMaterial();
3646                m.mDiffuseColor = RgbColor(0, 1, 0);
3647                exporter->SetForcedMaterial(m);
3648
3649                ExportViewCellGeometry(exporter, vc, NULL, NULL);
3650                exporter->SetFilled();
3651
3652                if (exportPvs)
3653                {
3654                        Intersectable::NewMail();
3655                        ObjectPvsIterator pit = pvs.GetIterator();
3656
3657                        while (pit.HasMoreEntries())
3658                        {               
3659                                ObjectPvsEntry entry = pit.Next();
3660
3661                // output PVS of view cell
3662                                Intersectable *intersect = entry.mObject;
3663                               
3664                                if (!intersect->Mailed())
3665                                {
3666                                        intersect->Mail();
3667
3668                                        m = RandomMaterial();
3669                                        exporter->SetForcedMaterial(m);
3670                                        exporter->ExportIntersectable(intersect);
3671                                }
3672                        }
3673                        cout << endl;
3674                }
3675               
3676                DEL_PTR(exporter);
3677                cout << "finished" << endl;
3678        }
3679}
3680
3681
3682void BspViewCellsManager::TestSubdivision()
3683{
3684        ViewCellContainer leaves;
3685        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
3686
3687        ViewCellContainer::const_iterator it, it_end = leaves.end();
3688
3689        const float vol = mViewSpaceBox.GetVolume();
3690        float subdivVol = 0;
3691        float newVol = 0;
3692
3693        for (it = leaves.begin(); it != it_end; ++ it)
3694        {
3695                BspNodeGeometry geom;
3696                mBspTree->ConstructGeometry(*it, geom);
3697
3698                const float lVol = geom.GetVolume();
3699                newVol += lVol;
3700                subdivVol += (*it)->GetVolume();
3701
3702                const float thres = 0.9f;
3703                if ((lVol < ((*it)->GetVolume() * thres)) ||
3704                        (lVol * thres > ((*it)->GetVolume())))
3705                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
3706        }
3707       
3708        Debug << "exact volume: " << vol << endl;
3709        Debug << "subdivision volume: " << subdivVol << endl;
3710        Debug << "new volume: " << newVol << endl;
3711}
3712
3713
3714void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3715                                                                                                 ViewCell *vc,
3716                                                                                                 const AxisAlignedBox3 *sceneBox,
3717                                                                                                 const AxisAlignedPlane *clipPlane
3718                                                                                                 ) const
3719{
3720        if (clipPlane)
3721        {
3722                const Plane3 plane = clipPlane->GetPlane();
3723
3724                ViewCellContainer leaves;
3725                mViewCellsTree->CollectLeaves(vc, leaves);
3726                ViewCellContainer::const_iterator it, it_end = leaves.end();
3727
3728                for (it = leaves.begin(); it != it_end; ++ it)
3729                {
3730                        BspNodeGeometry geom;
3731                        BspNodeGeometry front;
3732                        BspNodeGeometry back;
3733
3734                        mBspTree->ConstructGeometry(*it, geom);
3735
3736                        const float eps = 0.0001f;
3737                        const int cf = geom.Side(plane, eps);
3738
3739                        if (cf == -1)
3740                        {
3741                                exporter->ExportPolygons(geom.GetPolys());
3742                        }
3743                        else if (cf == 0)
3744                        {
3745                                geom.SplitGeometry(front,
3746                                                                   back,
3747                                                                   plane,
3748                                                                   mViewSpaceBox,
3749                                                                   eps);
3750
3751                                if (back.Valid())
3752                                {
3753                                        exporter->ExportPolygons(back.GetPolys());
3754                                }                       
3755                        }
3756                }
3757        }
3758        else
3759        {
3760                // export mesh if available
3761                // TODO: some bug here?
3762                if (1 && vc->GetMesh())
3763                {
3764                        exporter->ExportMesh(vc->GetMesh());
3765                }
3766                else
3767                {
3768                        BspNodeGeometry geom;
3769                        mBspTree->ConstructGeometry(vc, geom);
3770                        exporter->ExportPolygons(geom.GetPolys());
3771                }
3772        }
3773}
3774
3775
3776void BspViewCellsManager::CreateMesh(ViewCell *vc)
3777{
3778        // note: should previous mesh be deleted (via mesh manager?)
3779        BspNodeGeometry geom;
3780        mBspTree->ConstructGeometry(vc, geom);
3781
3782        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
3783
3784        IncludeNodeGeomInMesh(geom, *mesh);
3785        vc->SetMesh(mesh);
3786}
3787
3788
3789void BspViewCellsManager::Finalize(ViewCell *viewCell,
3790                                                                   const bool createMesh)
3791{
3792        float area = 0;
3793        float volume = 0;
3794
3795        ViewCellContainer leaves;
3796        mViewCellsTree->CollectLeaves(viewCell, leaves);
3797
3798        ViewCellContainer::const_iterator it, it_end = leaves.end();
3799
3800    for (it = leaves.begin(); it != it_end; ++ it)
3801        {
3802                BspNodeGeometry geom;
3803
3804                mBspTree->ConstructGeometry(*it, geom);
3805
3806                const float lVol = geom.GetVolume();
3807                const float lArea = geom.GetArea();
3808
3809                area += lArea;
3810                volume += lVol;
3811       
3812                CreateMesh(*it);
3813        }
3814
3815        viewCell->SetVolume(volume);
3816        viewCell->SetArea(area);
3817}
3818
3819
3820ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
3821{
3822        if (!ViewCellsConstructed())
3823        {
3824                return NULL;
3825        }
3826        if (!mViewSpaceBox.IsInside(point))
3827        {
3828                return NULL;
3829        }
3830        return mBspTree->GetViewCell(point);
3831}
3832
3833
3834void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3835                                                                                                 vector<MergeCandidate> &candidates)
3836{
3837        cout << "collecting merge candidates ... " << endl;
3838
3839        if (mUseRaysForMerge)
3840        {
3841                mBspTree->CollectMergeCandidates(rays, candidates);
3842        }
3843        else
3844        {
3845                vector<BspLeaf *> leaves;
3846                mBspTree->CollectLeaves(leaves);
3847                mBspTree->CollectMergeCandidates(leaves, candidates);
3848        }
3849
3850        cout << "fininshed collecting candidates" << endl;
3851}
3852
3853
3854
3855bool BspViewCellsManager::ExportViewCells(const string filename,
3856                                                                                  const bool exportPvs,
3857                                                                                  const ObjectContainer &objects)
3858{
3859        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
3860        {
3861                return false;
3862        }
3863
3864        cout << "exporting view cells to xml ... ";
3865
3866        OUT_STREAM stream(filename.c_str());
3867
3868        // for output we need unique ids for each view cell
3869        CreateUniqueViewCellIds();
3870
3871        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3872        stream << "<VisibilitySolution>" << endl;
3873
3874        if (exportPvs)
3875        {
3876                //////////
3877                //-- export bounding boxes: they are used to identify the objects from the pvs and
3878                //-- assign them to the entities in the rendering engine
3879
3880                stream << "<BoundingBoxes>" << endl;
3881                ObjectContainer::const_iterator oit, oit_end = objects.end();
3882
3883                for (oit = objects.begin(); oit != oit_end; ++ oit)
3884                {
3885                        const AxisAlignedBox3 box = (*oit)->GetBox();
3886                       
3887                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
3888                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
3889                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
3890                }
3891
3892                stream << "</BoundingBoxes>" << endl;
3893        }
3894
3895        ///////////
3896        //-- export the view cells and the pvs
3897
3898        const int numViewCells = mCurrentViewCellsStats.viewCells;
3899        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
3900
3901        mViewCellsTree->Export(stream, exportPvs);
3902       
3903        stream << "</ViewCells>" << endl;
3904
3905        /////////////
3906        //-- export the view space hierarchy
3907        stream << "<ViewSpaceHierarchy type=\"bsp\""
3908                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3909                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
3910
3911        mBspTree->Export(stream);
3912
3913        // end tags
3914        stream << "</ViewSpaceHierarchy>" << endl;
3915        stream << "</VisibilitySolution>" << endl;
3916
3917        stream.close();
3918        cout << "finished" << endl;
3919
3920        return true;
3921}
3922
3923
3924ViewCell *BspViewCellsManager::ConstructDummyMergeTree(BspNode *root)
3925{
3926        ViewCellInterior *vcRoot = new ViewCellInterior();
3927               
3928        // evaluate merge cost for priority traversal
3929        const float mergeCost =  -(float)root->mTimeStamp;
3930        vcRoot->SetMergeCost(mergeCost);
3931
3932        float volume = 0;
3933        vector<BspLeaf *> leaves;
3934        mBspTree->CollectLeaves(leaves);
3935        vector<BspLeaf *>::const_iterator lit, lit_end = leaves.end();
3936        ViewCell::NewMail();
3937
3938        for (lit = leaves.begin(); lit != lit_end; ++ lit)
3939        {
3940                BspLeaf *leaf = *lit;
3941                ViewCell *vc = leaf->GetViewCell();
3942
3943                if (!vc->Mailed())
3944                {
3945                        vc->Mail();
3946                        vc->SetMergeCost(0.0f);
3947                        vcRoot->SetupChildLink(vc);
3948
3949                        volume += vc->GetVolume();
3950                        volume += vc->GetVolume();     
3951                        vcRoot->SetVolume(volume);
3952                }
3953        }
3954       
3955        return vcRoot;
3956}
3957
3958
3959ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
3960{
3961        // terminate recursion
3962        if (root->IsLeaf())
3963        {
3964                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
3965                leaf->GetViewCell()->SetMergeCost(0.0f);
3966                return leaf->GetViewCell();
3967        }
3968       
3969        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3970        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3971               
3972        // evaluate merge cost for priority traversal
3973        const float mergeCost = -(float)root->mTimeStamp;
3974        viewCellInterior->SetMergeCost(mergeCost);
3975
3976        float volume = 0;
3977       
3978        BspNode *front = interior->GetFront();
3979        BspNode *back = interior->GetBack();
3980
3981
3982        ////////////
3983        //-- recursivly compute child hierarchies
3984
3985        ViewCell *backVc = ConstructSpatialMergeTree(back);
3986        ViewCell *frontVc = ConstructSpatialMergeTree(front);
3987
3988        viewCellInterior->SetupChildLink(backVc);
3989        viewCellInterior->SetupChildLink(frontVc);
3990
3991        volume += backVc->GetVolume();
3992        volume += frontVc->GetVolume();
3993
3994        viewCellInterior->SetVolume(volume);
3995
3996        return viewCellInterior;
3997}
3998
3999
4000/************************************************************************/
4001/*                   KdViewCellsManager implementation                  */
4002/************************************************************************/
4003
4004
4005
4006KdViewCellsManager::KdViewCellsManager(ViewCellsTree *vcTree, KdTree *kdTree):
4007ViewCellsManager(vcTree), mKdTree(kdTree), mKdPvsDepth(100)
4008{
4009}
4010
4011
4012float KdViewCellsManager::GetProbability(ViewCell *viewCell)
4013{
4014        // compute view cell area / volume as subsititute for probability
4015        if (0)
4016                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
4017        else
4018                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
4019}
4020
4021
4022
4023
4024void KdViewCellsManager::CollectViewCells()
4025{
4026        //mKdTree->CollectViewCells(mViewCells); TODO
4027}
4028
4029
4030int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
4031                                                                  const VssRayContainer &rays)
4032{
4033        // if view cells already constructed
4034        if (ViewCellsConstructed())
4035                return 0;
4036
4037        mKdTree->Construct();
4038
4039        mTotalAreaValid = false;
4040        // create the view cells
4041        mKdTree->CreateAndCollectViewCells(mViewCells);
4042        // cast rays
4043        ComputeSampleContributions(rays, true, false);
4044
4045        EvaluateViewCellsStats();
4046        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
4047
4048        return 0;
4049}
4050
4051
4052bool KdViewCellsManager::ViewCellsConstructed() const
4053{
4054        return mKdTree->GetRoot() != NULL;
4055}
4056
4057
4058int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
4059                                                                        const VssRayContainer &rays)
4060{
4061        return 0;
4062}
4063
4064
4065void KdViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
4066                                                                                           const int maxViewCells,
4067                                                                                           const bool sortViewCells,
4068                                                                                           const bool exportPvs,
4069                                                                                           const bool exportRays,
4070                                                                                           const int maxRays,
4071                                                                                           const string prefix,
4072                                                                                           VssRayContainer *visRays)
4073{
4074        // TODO
4075}
4076
4077
4078void KdViewCellsManager::Visualize(const ObjectContainer &objects,
4079                                                                   const VssRayContainer &sampleRays)
4080{
4081        if (!ViewCellsConstructed())
4082                return;
4083
4084        // using view cells instead of the kd PVS of objects
4085        const bool useViewCells = true;
4086        bool exportRays = false;
4087
4088        int limit = min(mVisualizationSamples, (int)sampleRays.size());
4089        const int pvsOut = min((int)objects.size(), 10);
4090        VssRayContainer *rays = new VssRayContainer[pvsOut];
4091
4092        if (useViewCells)
4093        {
4094                const int leafOut = 10;
4095
4096                ViewCell::NewMail();
4097
4098                //-- some rays for output
4099                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
4100                Debug << "visualization using " << raysOut << " samples" << endl;
4101
4102                //-- some random view cells and rays for output
4103                vector<KdLeaf *> kdLeaves;
4104
4105                for (int i = 0; i < leafOut; ++ i)
4106                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
4107
4108                for (int i = 0; i < kdLeaves.size(); ++ i)
4109                {
4110                        KdLeaf *leaf = kdLeaves[i];
4111                        RayContainer vcRays;
4112
4113                        cout << "creating output for view cell " << i << " ... ";
4114#if 0
4115                        // check whether we can add the current ray to the output rays
4116                        for (int k = 0; k < raysOut; ++ k)
4117                        {
4118                                Ray *ray = sampleRays[k];
4119
4120                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
4121                                {
4122                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
4123
4124                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
4125                                        {
4126                                                vcRays.push_back(ray);
4127                                        }
4128                                }
4129                        }
4130#endif
4131                        Intersectable::NewMail();
4132
4133                        ViewCell *vc = leaf->mViewCell;
4134                        char str[64]; sprintf(str, "viewcell%04d.wrl", i);
4135
4136                        Exporter *exporter = Exporter::GetExporter(str);
4137                        exporter->SetFilled();
4138
4139                        exporter->SetWireframe();
4140                        //exporter->SetFilled();
4141
4142                        Material m;//= RandomMaterial();
4143                        m.mDiffuseColor = RgbColor(1, 1, 0);
4144                        exporter->SetForcedMaterial(m);
4145
4146                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
4147                        exporter->ExportBox(box);
4148
4149                        // export rays piercing this view cell
4150                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
4151
4152                        m.mDiffuseColor = RgbColor(1, 0, 0);
4153                        exporter->SetForcedMaterial(m);
4154
4155                        // exporter->SetWireframe();
4156                        exporter->SetFilled();
4157
4158                        ObjectPvsIterator pit = vc->GetPvs().GetIterator();
4159                       
4160                        while (pit.HasMoreEntries())
4161                        {               
4162                                ObjectPvsEntry entry = pit.Next();
4163                               
4164                                //-- output PVS of view cell
4165                                Intersectable *intersect = entry.mObject;
4166                                if (!intersect->Mailed())
4167                                {
4168                                        exporter->ExportIntersectable(intersect);
4169                                        intersect->Mail();
4170                                }
4171                        }
4172
4173                        DEL_PTR(exporter);
4174                        cout << "finished" << endl;
4175                }
4176
4177                DEL_PTR(rays);
4178        }
4179        else // using kd PVS of objects
4180        {
4181                for (int i = 0; i < limit; ++ i)
4182                {
4183                        VssRay *ray = sampleRays[i];
4184
4185                        // check whether we can add this to the rays
4186                        for (int j = 0; j < pvsOut; j++)
4187                        {
4188                                if (objects[j] == ray->mTerminationObject)
4189                                {
4190                                        rays[j].push_back(ray);
4191                                }
4192                        }
4193                }
4194
4195                if (exportRays)
4196                {
4197                        Exporter *exporter = NULL;
4198                        exporter = Exporter::GetExporter("sample-rays.x3d");
4199                        exporter->SetWireframe();
4200                        exporter->ExportKdTree(*mKdTree);
4201
4202                        for (int i = 0; i < pvsOut; i++)
4203                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
4204
4205                        exporter->SetFilled();
4206                        delete exporter;
4207                }
4208
4209                for (int k=0; k < pvsOut; k++)
4210                {
4211                        Intersectable *object = objects[k];
4212                        char str[64]; sprintf(str, "viewcell%04d.wrl", k);
4213
4214                        Exporter *exporter = Exporter::GetExporter(str);
4215                        exporter->SetWireframe();
4216
4217                        // matt: no kd pvs
4218                        /*
4219                        KdPvsMap::iterator kit = object->mKdPvs.mEntries.begin();
4220                        Intersectable::NewMail();
4221
4222                        // avoid adding the object to the list
4223                        object->Mail();
4224                        ObjectContainer visibleObjects;
4225
4226                        for (; kit != object->mKdPvs.mEntries.end(); i++)
4227                        {
4228                                KdNode *node = (*kit).first;
4229                                exporter->ExportBox(mKdTree->GetBox(node));
4230
4231                                mKdTree->CollectObjects(node, visibleObjects);
4232                        }
4233
4234                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
4235                        exporter->SetFilled();
4236
4237                        for (int j = 0; j < visibleObjects.size(); j++)
4238                                exporter->ExportIntersectable(visibleObjects[j]);
4239
4240                        Material m;
4241                        m.mDiffuseColor = RgbColor(1, 0, 0);
4242                        exporter->SetForcedMaterial(m);
4243                        exporter->ExportIntersectable(object);
4244*/
4245                        delete exporter;
4246                }
4247        }
4248}
4249
4250
4251ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
4252{
4253        return new KdViewCell(mesh);
4254}
4255
4256
4257void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
4258                                                                                                ViewCell *vc,
4259                                                                                                const AxisAlignedBox3 *sceneBox,
4260                                                                                                const AxisAlignedPlane *clipPlane
4261                                                                                                ) const
4262{
4263        ViewCellContainer leaves;
4264        mViewCellsTree->CollectLeaves(vc, leaves);
4265        ViewCellContainer::const_iterator it, it_end = leaves.end();
4266
4267        for (it = leaves.begin(); it != it_end; ++ it)
4268        {
4269                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
4270                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaves[0]));
4271        }
4272}
4273
4274
4275int KdViewCellsManager::GetType() const
4276{
4277        return ViewCellsManager::KD;
4278}
4279
4280
4281
4282KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
4283{
4284        KdNode *node = leaf;
4285
4286        while (node->mParent && node->mDepth > mKdPvsDepth)
4287                node = node->mParent;
4288
4289        return node;
4290}
4291
4292int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
4293                                                                                const Vector3 &termination,
4294                                                                                ViewCellContainer &viewcells)
4295{
4296        return mKdTree->CastLineSegment(origin, termination, viewcells);
4297}
4298
4299
4300void KdViewCellsManager::CreateMesh(ViewCell *vc)
4301{
4302        // TODO
4303}
4304
4305
4306
4307void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4308                                                                                                vector<MergeCandidate> &candidates)
4309{
4310        // TODO
4311}
4312
4313
4314
4315/**************************************************************************/
4316/*                   VspBspViewCellsManager implementation                */
4317/**************************************************************************/
4318
4319
4320VspBspViewCellsManager::VspBspViewCellsManager(ViewCellsTree *vcTree, VspBspTree *vspBspTree):
4321ViewCellsManager(vcTree), mVspBspTree(vspBspTree)
4322{
4323        Environment::GetSingleton()->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
4324        mVspBspTree->SetViewCellsManager(this);
4325        mVspBspTree->mViewCellsTree = mViewCellsTree;
4326}
4327
4328
4329VspBspViewCellsManager::~VspBspViewCellsManager()
4330{
4331}
4332
4333
4334float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
4335{
4336        if (0 && mVspBspTree->mUseAreaForPvs)
4337                return GetArea(viewCell) / GetAccVcArea();
4338        else
4339                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
4340}
4341
4342
4343void VspBspViewCellsManager::CollectViewCells()
4344{
4345        // view cells tree constructed?
4346        if (!ViewCellsTreeConstructed())
4347        {
4348                mVspBspTree->CollectViewCells(mViewCells, false);
4349        }
4350        else
4351        {       
4352                // we can use the view cells tree hierarchy to get the right set
4353                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
4354        }
4355}
4356
4357
4358void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4359                                                                                                        vector<MergeCandidate> &candidates)
4360{       
4361        cout << "collecting merge candidates ... " << endl;
4362
4363        if (mUseRaysForMerge)
4364        {
4365                mVspBspTree->CollectMergeCandidates(rays, candidates);
4366        }
4367        else
4368        {
4369                vector<BspLeaf *> leaves;
4370                mVspBspTree->CollectLeaves(leaves);
4371       
4372                mVspBspTree->CollectMergeCandidates(leaves, candidates);
4373        }
4374
4375        cout << "fininshed collecting candidates" << endl;
4376}
4377
4378
4379bool VspBspViewCellsManager::ViewCellsConstructed() const
4380{
4381        return mVspBspTree->GetRoot() != NULL;
4382}
4383
4384
4385ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
4386{
4387        return new BspViewCell(mesh);
4388}
4389
4390
4391int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
4392                                                                                                 const VssRayContainer &rays)
4393{
4394        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
4395
4396        // if view cells were already constructed
4397        if (ViewCellsConstructed())
4398        {
4399                return 0;
4400        }
4401
4402        int sampleContributions = 0;
4403        VssRayContainer sampleRays;
4404
4405        const int limit = min(mInitialSamples, (int)rays.size());
4406
4407        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
4408                  << ", actual rays: " << (int)rays.size() << endl;
4409
4410        VssRayContainer savedRays;
4411
4412        if (SAMPLE_AFTER_SUBDIVISION)
4413        {
4414                VssRayContainer constructionRays;
4415               
4416                GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
4417
4418                Debug << "rays used for initial construction: " << (int)constructionRays.size() << endl;
4419                Debug << "rays saved for later use: " << (int)savedRays.size() << endl;
4420       
4421                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
4422        }
4423        else
4424        {
4425                Debug << "rays used for initial construction: " << (int)rays.size() << endl;
4426                mVspBspTree->Construct(rays, &mViewSpaceBox);
4427        }
4428
4429        // collapse invalid regions
4430        cout << "collapsing invalid tree regions ... ";
4431        long startTime = GetTime();
4432
4433        const int collapsedLeaves = mVspBspTree->CollapseTree();
4434        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
4435                  << " seconds" << endl;
4436
4437    cout << "finished" << endl;
4438
4439        /////////////////
4440        //-- stats after construction
4441
4442        Debug << mVspBspTree->GetStatistics() << endl;
4443
4444        ResetViewCells();
4445        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
4446
4447
4448        //////////////////////
4449        //-- recast the rest of the rays
4450
4451        startTime = GetTime();
4452
4453        cout << "Computing remaining ray contributions ... ";
4454
4455        if (SAMPLE_AFTER_SUBDIVISION)
4456                ComputeSampleContributions(savedRays, true, false);
4457
4458        cout << "finished" << endl;
4459
4460        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
4461                  << " secs" << endl;
4462
4463        cout << "construction finished" << endl;
4464
4465        if (0)
4466        {       ////////
4467                //-- real meshes are contructed at this stage
4468
4469                cout << "finalizing view cells ... ";
4470                FinalizeViewCells(true);
4471                cout << "finished" << endl;
4472        }
4473
4474        return sampleContributions;
4475}
4476
4477
4478void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
4479                                                                                        const ObjectContainer &objects)
4480{
4481    int vcSize = 0;
4482        int pvsSize = 0;
4483
4484        //-- merge view cells
4485        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
4486        long startTime = GetTime();
4487
4488
4489        if (mMergeViewCells)
4490        {
4491                // TODO: should be done BEFORE the ray casting
4492                // compute tree by merging the nodes based on cost heuristics
4493                mViewCellsTree->ConstructMergeTree(rays, objects);
4494        }
4495        else
4496        {
4497                // compute tree by merging the nodes of the spatial hierarchy
4498                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
4499                mViewCellsTree->SetRoot(root);
4500
4501                // compute pvs
4502                ObjectPvs pvs;
4503                UpdatePvsForEvaluation(root, pvs);
4504        }
4505
4506        if (1)
4507        {
4508                char mstats[100];
4509                ObjectPvs pvs;
4510
4511                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
4512                mViewCellsTree->ExportStats(mstats);
4513        }
4514
4515        cout << "merged view cells in "
4516                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
4517
4518        Debug << "Postprocessing: Merged view cells in "
4519                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
4520       
4521
4522        //////////////////
4523        //-- stats and visualizations
4524
4525        int savedColorCode = mColorCode;
4526       
4527        // get currently active view cell set
4528        ResetViewCells();
4529        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
4530       
4531        if (mShowVisualization) // export merged view cells
4532        {
4533                mColorCode = 0;
4534                Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
4535               
4536                cout << "exporting view cells after merge ... ";
4537
4538                if (exporter)
4539                {
4540                        if (0)
4541                                exporter->SetWireframe();
4542                        else
4543                                exporter->SetFilled();
4544
4545                        ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
4546
4547                        if (mExportGeometry)
4548                        {
4549                                Material m;
4550                                m.mDiffuseColor = RgbColor(0, 1, 0);
4551                                exporter->SetForcedMaterial(m);
4552                                exporter->SetFilled();
4553
4554                                exporter->ExportGeometry(objects);
4555                        }
4556
4557                        delete exporter;
4558                }
4559                cout << "finished" << endl;
4560        }
4561
4562        if (mShowVisualization)
4563        {
4564                // use pvs size for color coding
4565                mColorCode = 1;
4566                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
4567
4568                cout << "exporting view cells after merge (pvs size) ... ";     
4569
4570                if (exporter)
4571                {
4572                        exporter->SetFilled();
4573
4574                        ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
4575
4576                        if (mExportGeometry)
4577                        {
4578                                Material m;
4579                                m.mDiffuseColor = RgbColor(0, 1, 0);
4580                                exporter->SetForcedMaterial(m);
4581                                exporter->SetFilled();
4582
4583                                exporter->ExportGeometry(objects);
4584                        }
4585
4586                        delete exporter;
4587                }
4588                cout << "finished" << endl;
4589        }
4590
4591        mColorCode = savedColorCode;
4592}
4593
4594
4595void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
4596                                                                                         const ObjectContainer &objects)
4597{
4598        mRenderer->RenderScene();
4599
4600        SimulationStatistics ss;
4601        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
4602    Debug << "render time before refine\n\n" << ss << endl;
4603
4604        const long startTime = GetTime();
4605        cout << "Refining the merged view cells ... ";
4606
4607        // refining the merged view cells
4608        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
4609
4610        //-- stats and visualizations
4611        cout << "finished" << endl;
4612        cout << "refined " << refined << " view cells in "
4613                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
4614
4615        Debug << "Postprocessing: refined " << refined << " view cells in "
4616                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
4617}
4618
4619
4620int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
4621                                                                                const VssRayContainer &rays)
4622{
4623        if (!ViewCellsConstructed())
4624        {
4625                Debug << "postprocess error: no view cells constructed" << endl;
4626                return 0;
4627        }
4628
4629        // view cells already finished before post processing step
4630        // (i.e. because they were loaded)
4631        if (mViewCellsFinished)
4632        {
4633                FinalizeViewCells(true);
4634                EvaluateViewCellsStats();
4635
4636                return 0;
4637        }
4638
4639        // check if new view cells turned invalid
4640        int minPvs, maxPvs;
4641
4642        if (0)
4643        {
4644                minPvs = mMinPvsSize;
4645                maxPvs = mMaxPvsSize;
4646        }
4647        else
4648        {
4649                // problem matt: why did I start here from zero?
4650                minPvs = 0;
4651                maxPvs = mMaxPvsSize;
4652        }
4653
4654        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4655        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4656       
4657        SetValidity(minPvs, maxPvs);
4658
4659        // update valid view space according to valid view cells
4660        if (0) mVspBspTree->ValidateTree();
4661
4662        // area has to be recomputed
4663        mTotalAreaValid = false;
4664        VssRayContainer postProcessRays;
4665        GetRaySets(rays, mPostProcessSamples, postProcessRays);
4666
4667        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
4668
4669        //////////
4670        //-- merge neighbouring view cells
4671        MergeViewCells(postProcessRays, objects);
4672       
4673        // refines the merged view cells
4674        if (0) RefineViewCells(postProcessRays, objects);
4675
4676
4677        ///////////
4678        //-- render simulation after merge + refine
4679
4680        cout << "\nview cells partition render time before compress" << endl << endl;;
4681        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
4682        SimulationStatistics ss;
4683        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
4684        cout << ss << endl;
4685       
4686        if (0) CompressViewCells();
4687       
4688        // collapse sibling leaves that share the same view cell
4689        if (0) mVspBspTree->CollapseTree();
4690
4691        // recompute view cell list and statistics
4692        ResetViewCells();
4693
4694        // compute final meshes and volume / area
4695        if (1) FinalizeViewCells(true);
4696
4697        return 0;
4698}
4699
4700
4701int VspBspViewCellsManager::GetType() const
4702{
4703        return VSP_BSP;
4704}
4705
4706
4707ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
4708{
4709        // terminate recursion
4710        if (root->IsLeaf())
4711        {
4712                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
4713                leaf->GetViewCell()->SetMergeCost(0.0f);
4714                return leaf->GetViewCell();
4715        }
4716       
4717       
4718        BspInterior *interior = dynamic_cast<BspInterior *>(root);
4719        ViewCellInterior *viewCellInterior = new ViewCellInterior();
4720               
4721        // evaluate merge cost for priority traversal
4722        float mergeCost = 1.0f / (float)root->mTimeStamp;
4723        viewCellInterior->SetMergeCost(mergeCost);
4724
4725        float volume = 0;
4726       
4727        BspNode *front = interior->GetFront();
4728        BspNode *back = interior->GetBack();
4729
4730
4731        ObjectPvs frontPvs, backPvs;
4732
4733        //-- recursivly compute child hierarchies
4734        ViewCell *backVc = ConstructSpatialMergeTree(back);
4735        ViewCell *frontVc = ConstructSpatialMergeTree(front);
4736
4737
4738        viewCellInterior->SetupChildLink(backVc);
4739        viewCellInterior->SetupChildLink(frontVc);
4740
4741        volume += backVc->GetVolume();
4742        volume += frontVc->GetVolume();
4743
4744        viewCellInterior->SetVolume(volume);
4745
4746        return viewCellInterior;
4747}
4748
4749
4750bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
4751{
4752        if (!ViewCellsConstructed())
4753                return ViewCellsManager::GetViewPoint(viewPoint);
4754
4755        // TODO: set reasonable limit
4756        const int limit = 20;
4757
4758        for (int i = 0; i < limit; ++ i)
4759        {
4760                viewPoint = mViewSpaceBox.GetRandomPoint();
4761                if (mVspBspTree->ViewPointValid(viewPoint))
4762                {
4763                        return true;
4764                }
4765        }
4766
4767        Debug << "failed to find valid view point, taking " << viewPoint << endl;
4768        return false;
4769}
4770
4771
4772bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
4773{
4774        // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
4775        // validy update in preprocessor for all managers)
4776        return ViewCellsManager::ViewPointValid(viewPoint);
4777
4778        //      return mViewSpaceBox.IsInside(viewPoint) &&
4779        //                 mVspBspTree->ViewPointValid(viewPoint);
4780}
4781
4782
4783void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
4784                                                                           const VssRayContainer &sampleRays)
4785{
4786        if (!ViewCellsConstructed())
4787                return;
4788
4789        VssRayContainer visRays;
4790        GetRaySets(sampleRays, mVisualizationSamples, visRays);
4791       
4792        if (1)
4793        {       
4794                //////////////////
4795                //-- export final view cell partition
4796
4797                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
4798               
4799                if (exporter)
4800                {
4801                        cout << "exporting view cells after post process ... ";
4802                        if (0)
4803                        {       // export view space box
4804                                exporter->SetWireframe();
4805                                exporter->ExportBox(mViewSpaceBox);
4806                                exporter->SetFilled();
4807                        }
4808
4809                        Material m;
4810                        m.mDiffuseColor.r = 0.0f;
4811                        m.mDiffuseColor.g = 0.5f;
4812                        m.mDiffuseColor.b = 0.5f;
4813
4814            exporter->SetForcedMaterial(m);
4815
4816                        if (1 && mExportGeometry)
4817                        {
4818                                exporter->ExportGeometry(objects);
4819                        }
4820
4821                        if (0 && mExportRays)
4822                        {
4823                                exporter->ExportRays(visRays, RgbColor(1, 0, 0));
4824                        }
4825                        ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
4826
4827                        delete exporter;
4828                        cout << "finished" << endl;
4829                }
4830        }
4831
4832        ////////////////
4833        //-- visualization of the BSP splits
4834
4835        bool exportSplits = false;
4836        Environment::GetSingleton()->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
4837
4838        if (exportSplits)
4839        {
4840                cout << "exporting splits ... ";
4841                ExportSplits(objects, visRays);
4842                cout << "finished" << endl;
4843        }
4844
4845        ////////
4846        //-- export single view cells
4847       
4848        int leafOut;
4849        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
4850        const int raysOut = 100;
4851       
4852        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
4853}
4854
4855
4856void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
4857                                                                                  const VssRayContainer &rays)
4858{
4859        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
4860
4861        if (exporter)
4862        {
4863                Material m;
4864                m.mDiffuseColor = RgbColor(1, 0, 0);
4865                exporter->SetForcedMaterial(m);
4866                exporter->SetWireframe();
4867
4868                exporter->ExportBspSplits(*mVspBspTree, true);
4869
4870                // take forced material, else big scenes cannot be viewed
4871                m.mDiffuseColor = RgbColor(0, 1, 0);
4872                exporter->SetForcedMaterial(m);
4873                exporter->SetFilled();
4874
4875                exporter->ResetForcedMaterial();
4876
4877                // export rays
4878                if (mExportRays)
4879                {
4880                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
4881                }
4882
4883                if (mExportGeometry)
4884                {
4885                        exporter->ExportGeometry(objects);
4886                }
4887                delete exporter;
4888        }
4889}
4890
4891
4892void VspBspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
4893                                                                                                   const int maxViewCells,
4894                                                                                                   const bool sortViewCells,
4895                                                                                                   const bool exportPvs,
4896                                                                                                   const bool exportRays,
4897                                                                                                   const int maxRays,
4898                                                                                                   const string prefix,
4899                                                                                                   VssRayContainer *visRays)
4900{       
4901        if (sortViewCells)
4902        {
4903                // sort view cells to visualize the largest view cells
4904                sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
4905        }
4906
4907        //////////
4908        //-- some view cells for output
4909
4910        ViewCell::NewMail();
4911        const int limit = min(maxViewCells, (int)mViewCells.size());
4912       
4913        for (int i = 0; i < limit; ++ i)
4914        {
4915                cout << "creating output for view cell " << i << " ... ";
4916
4917                ViewCell *vc = sortViewCells ? // largest view cell pvs first?
4918                        mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 0.5f)] : mViewCells[i];
4919
4920                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
4921                        continue;
4922
4923                vc->Mail();
4924
4925                ObjectPvs pvs;
4926                mViewCellsTree->GetPvs(vc, pvs);
4927
4928                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
4929                Exporter *exporter = Exporter::GetExporter(s);
4930               
4931                const float pvsCost = mViewCellsTree->GetPvsCost(vc);
4932                cout << "view cell " << vc->GetId() << ": pvs cost=" << pvsCost << endl;
4933
4934                if (exportRays)
4935                {
4936                        ////////////
4937                        //-- export rays piercing this view cell
4938
4939                        // take rays stored with the view cells during subdivision
4940                        VssRayContainer vcRays;
4941            VssRayContainer collectRays;
4942
4943                        // collect initial view cells
4944                        ViewCellContainer leaves;
4945                        mViewCellsTree->CollectLeaves(vc, leaves);
4946
4947                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
4948                for (vit = leaves.begin(); vit != vit_end; ++ vit)
4949                        {       
4950                                BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaves[0];
4951                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
4952
4953                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
4954                                {
4955                                        collectRays.push_back(*rit);
4956                                }
4957                        }
4958
4959                        const int raysOut = min((int)collectRays.size(), maxRays);
4960               
4961                        // prepare some rays for output
4962                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
4963                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
4964                        {
4965                                const float p = RandomValue(0.0f, (float)collectRays.size());
4966                       
4967                                if (p < raysOut)
4968                                {
4969                                        vcRays.push_back(*rit);
4970                                }
4971                        }
4972
4973                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
4974                }
4975               
4976                ////////////////
4977                //-- export view cell geometry
4978
4979                exporter->SetWireframe();
4980
4981                Material m;//= RandomMaterial();
4982                m.mDiffuseColor = RgbColor(0, 1, 0);
4983                exporter->SetForcedMaterial(m);
4984
4985                ExportViewCellGeometry(exporter, vc, NULL, NULL);
4986                exporter->SetFilled();
4987
4988                if (exportPvs)
4989                {
4990                        Intersectable::NewMail();
4991
4992                        ObjectPvsIterator pit = pvs.GetIterator();
4993
4994                        cout << endl;
4995
4996                        // output PVS of view cell
4997                        while (pit.HasMoreEntries())
4998                        {
4999                                ObjectPvsEntry entry = pit.Next();             
5000                                Intersectable *intersect = entry.mObject;
5001                               
5002                                if (!intersect->Mailed())
5003                                {
5004                                        intersect->Mail();
5005
5006                                        m = RandomMaterial();
5007                                        exporter->SetForcedMaterial(m);
5008                                        exporter->ExportIntersectable(intersect);
5009                                }
5010                        }
5011                        cout << endl;
5012                }
5013               
5014                DEL_PTR(exporter);
5015                cout << "finished" << endl;
5016        }
5017}
5018
5019
5020void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
5021{
5022        Exporter *exporter = Exporter::GetExporter("filter.x3d");
5023
5024        Vector3 bsize = mViewSpaceBox.Size();
5025        const Vector3 viewPoint(mViewSpaceBox.Center());
5026        float w = Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
5027        const Vector3 width = Vector3(w);
5028       
5029        PrVs testPrVs;
5030       
5031        if (exporter)
5032        {
5033                ViewCellContainer viewCells;
5034       
5035        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
5036
5037                GetPrVS(viewPoint, testPrVs, GetFilterWidth());
5038
5039                exporter->SetWireframe();
5040
5041                exporter->SetForcedMaterial(RgbColor(1,1,1));
5042                exporter->ExportBox(tbox);
5043               
5044                exporter->SetFilled();
5045
5046                exporter->SetForcedMaterial(RgbColor(0,1,0));
5047                ExportViewCellGeometry(exporter, GetViewCell(viewPoint), NULL, NULL);
5048
5049                //exporter->ResetForcedMaterial();
5050                exporter->SetForcedMaterial(RgbColor(0,0,1));
5051                ExportViewCellGeometry(exporter, testPrVs.mViewCell, NULL, NULL);
5052
5053        exporter->SetForcedMaterial(RgbColor(1,0,0));
5054                exporter->ExportGeometry(objects);
5055
5056                delete exporter;
5057        }
5058}
5059
5060
5061int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
5062                                                                                                        ViewCellContainer &viewCells) const
5063{
5064        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
5065}
5066
5067
5068int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
5069                                                                                        const Vector3 &termination,
5070                                                                                        ViewCellContainer &viewcells)
5071{
5072        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
5073}
5074
5075
5076void VspBspViewCellsManager::VisualizeWithFromPointQueries()
5077{
5078        int numSamples;
5079       
5080        Environment::GetSingleton()->GetIntValue("RenderSampler.samples", numSamples);
5081        cout << "samples" << numSamples << endl;
5082
5083        vector<RenderCostSample> samples;
5084 
5085        if (!mPreprocessor->GetRenderer())
5086                return;
5087
5088        //start the view point queries
5089        long startTime = GetTime();
5090        cout << "starting sampling of render cost ... ";
5091       
5092        mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
5093
5094        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
5095
5096
5097        // for each sample:
5098        //    find view cells associated with the samples
5099        //    store the sample pvs with the pvs associated with the view cell
5100        //
5101        // for each view cell:
5102        //    compute difference point sampled pvs - view cell pvs
5103        //    export geometry with color coded pvs difference
5104       
5105    std::map<ViewCell *, ObjectPvs> sampleMap;
5106
5107        vector<RenderCostSample>::const_iterator rit, rit_end = samples.end();
5108
5109        for (rit = samples.begin(); rit != rit_end; ++ rit)
5110        {
5111                RenderCostSample sample = *rit;
5112       
5113                ViewCell *vc = GetViewCell(sample.mPosition);
5114
5115                std::map<ViewCell *, ObjectPvs>::iterator it = sampleMap.find(vc);
5116
5117                if (it == sampleMap.end())
5118                {
5119                        sampleMap[vc] = sample.mPvs;
5120                }
5121                else
5122                {
5123                        (*it).second.MergeInPlace(sample.mPvs);
5124                }
5125        }
5126
5127        // visualize the view cells
5128        std::map<ViewCell *, ObjectPvs>::const_iterator vit, vit_end = sampleMap.end();
5129
5130        Material m;//= RandomMaterial();
5131
5132        for (vit = sampleMap.begin(); vit != vit_end; ++ vit)
5133        {
5134                ViewCell *vc = (*vit).first;
5135               
5136                const int pvsVc = mViewCellsTree->GetPvsEntries(vc);
5137                const int pvsPtSamples = (*vit).second.GetSize();
5138
5139        m.mDiffuseColor.r = (float) (pvsVc - pvsPtSamples);
5140                m.mDiffuseColor.b = 1.0f;
5141                //exporter->SetForcedMaterial(m);
5142                //ExportViewCellGeometry(exporter, vc, mClipPlaneForViz);
5143
5144                /*      // counting the pvss
5145                for (rit = samples.begin(); rit != rit_end; ++ rit)
5146                {
5147                        RenderCostSample sample = *rit;
5148                        ViewCell *vc = GetViewCell(sample.mPosition);
5149
5150                        AxisAlignedBox3 box(sample.mPosition - Vector3(1, 1, 1), sample.mPosition + Vector3(1, 1, 1));
5151                        Mesh *hMesh = CreateMeshFromBox(box);
5152
5153                        DEL_PTR(hMesh);
5154                }
5155                */
5156        }
5157}
5158
5159
5160void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
5161                                                                                                        ViewCell *vc,
5162                                                                                                        const AxisAlignedBox3 *sceneBox,
5163                                                                                                        const AxisAlignedPlane *clipPlane
5164                                                                                                        ) const
5165{
5166        if (clipPlane)
5167        {
5168                const Plane3 plane = clipPlane->GetPlane();
5169
5170                ViewCellContainer leaves;
5171                mViewCellsTree->CollectLeaves(vc, leaves);
5172                ViewCellContainer::const_iterator it, it_end = leaves.end();
5173
5174                for (it = leaves.begin(); it != it_end; ++ it)
5175                {
5176                        BspNodeGeometry geom;
5177                        BspNodeGeometry front;
5178                        BspNodeGeometry back;
5179
5180                        mVspBspTree->ConstructGeometry(*it, geom);
5181
5182                        const float eps = 0.0001f;
5183                        const int cf = geom.Side(plane, eps);
5184
5185                        if (cf == -1)
5186                        {
5187                                exporter->ExportPolygons(geom.GetPolys());
5188                        }
5189                        else if (cf == 0)
5190                        {
5191                                geom.SplitGeometry(front,
5192                                                                   back,
5193                                                                   plane,
5194                                                                   mViewSpaceBox,
5195                                                                   eps);
5196
5197                                if (back.Valid())
5198                                {
5199                                        exporter->ExportPolygons(back.GetPolys());
5200                                }                       
5201                        }
5202                }
5203        }
5204        else
5205        {
5206                // export mesh if available
5207                // TODO: some bug here?
5208                if (1 && vc->GetMesh())
5209                {
5210                        exporter->ExportMesh(vc->GetMesh());
5211                }
5212                else
5213                {
5214                        BspNodeGeometry geom;
5215                        mVspBspTree->ConstructGeometry(vc, geom);
5216                        exporter->ExportPolygons(geom.GetPolys());
5217                }
5218        }
5219}
5220
5221
5222int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
5223{
5224        ViewCellContainer leaves;
5225        mViewCellsTree->CollectLeaves(vc, leaves);
5226
5227        int maxDist = 0;
5228       
5229        // compute max height difference
5230        for (int i = 0; i < (int)leaves.size(); ++ i)
5231        {
5232                for (int j = 0; j < (int)leaves.size(); ++ j)
5233                {
5234                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaves[0];
5235
5236                        if (i != j)
5237                        {
5238                                BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaves[0];
5239                                const int dist = mVspBspTree->TreeDistance(leaf, leaf2);
5240                               
5241                                if (dist > maxDist)
5242                                        maxDist = dist;
5243                        }
5244                }
5245        }
5246
5247        return maxDist;
5248}
5249
5250
5251ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
5252{
5253        if (!ViewCellsConstructed())
5254                return NULL;
5255
5256        if (!mViewSpaceBox.IsInside(point))
5257          return NULL;
5258
5259        return mVspBspTree->GetViewCell(point, active);
5260}
5261
5262
5263void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
5264{
5265        BspNodeGeometry geom;
5266        mVspBspTree->ConstructGeometry(vc, geom);
5267       
5268        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
5269        IncludeNodeGeomInMesh(geom, *mesh);
5270
5271        vc->SetMesh(mesh);
5272}
5273
5274
5275int VspBspViewCellsManager::CastBeam(Beam &beam)
5276{
5277        return mVspBspTree->CastBeam(beam);
5278}
5279
5280
5281void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
5282                                                                          const bool createMesh)
5283{
5284        float area = 0;
5285        float volume = 0;
5286
5287        ViewCellContainer leaves;
5288        mViewCellsTree->CollectLeaves(viewCell, leaves);
5289
5290        ViewCellContainer::const_iterator it, it_end = leaves.end();
5291
5292    for (it = leaves.begin(); it != it_end; ++ it)
5293        {
5294                BspNodeGeometry geom;
5295                mVspBspTree->ConstructGeometry(*it, geom);
5296
5297                const float lVol = geom.GetVolume();
5298                const float lArea = geom.GetArea();
5299
5300                area += lArea;
5301                volume += lVol;
5302
5303                if (createMesh)
5304                        CreateMesh(*it);
5305        }
5306
5307        viewCell->SetVolume(volume);
5308        viewCell->SetArea(area);
5309}
5310
5311
5312void VspBspViewCellsManager::TestSubdivision()
5313{
5314        ViewCellContainer leaves;
5315        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
5316
5317        ViewCellContainer::const_iterator it, it_end = leaves.end();
5318
5319        const float vol = mViewSpaceBox.GetVolume();
5320        float subdivVol = 0;
5321        float newVol = 0;
5322
5323        for (it = leaves.begin(); it != it_end; ++ it)
5324        {
5325                BspNodeGeometry geom;
5326                mVspBspTree->ConstructGeometry(*it, geom);
5327
5328                const float lVol = geom.GetVolume();
5329               
5330                newVol += lVol;
5331                subdivVol += (*it)->GetVolume();
5332               
5333                float thres = 0.9f;
5334                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
5335                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
5336        }
5337       
5338        Debug << "exact volume: " << vol << endl;
5339        Debug << "subdivision volume: " << subdivVol << endl;
5340        Debug << "new volume: " << newVol << endl;
5341}
5342
5343
5344void VspBspViewCellsManager::PrepareLoadedViewCells()
5345{
5346        // TODO: do I still need this here?
5347        if (0)
5348                mVspBspTree->RepairViewCellsLeafLists();
5349}
5350
5351
5352
5353/************************************************************************/
5354/*                 VspOspViewCellsManager implementation                */
5355/************************************************************************/
5356
5357
5358VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree,
5359                                                                                           const string &hierarchyType)
5360: ViewCellsManager(vcTree)
5361{
5362        Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
5363
5364        Environment::GetSingleton()->GetBoolValue("ViewCells.compressObjects", mCompressObjects);
5365
5366        Debug << "compressing objects: " << mCompressObjects << endl;
5367        cout << "compressing objects: " << mCompressObjects << endl;
5368
5369        mHierarchyManager = CreateHierarchyManager(hierarchyType);
5370        mHierarchyManager->SetViewCellsManager(this);
5371        mHierarchyManager->SetViewCellsTree(mViewCellsTree);
5372}
5373
5374
5375VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, HierarchyManager *hm)
5376: ViewCellsManager(vcTree), mHierarchyManager(hm)
5377{
5378        Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
5379        Environment::GetSingleton()->GetBoolValue("ViewCells.compressObjects", mCompressObjects);
5380
5381        Debug << "compressing objects: " << mCompressObjects << endl;
5382        cout << "compressing objects: " << mCompressObjects << endl;
5383
5384        mHierarchyManager->SetViewCellsManager(this);
5385        mHierarchyManager->SetViewCellsTree(mViewCellsTree);
5386}
5387
5388
5389Intersectable *
5390VspOspViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
5391{
5392        if (mUseKdPvs)
5393        {
5394                return ViewCellsManager::GetIntersectable(ray, isTermination);
5395        }
5396        else
5397        {
5398                return mHierarchyManager->GetIntersectable(ray, isTermination);
5399        }
5400}
5401
5402
5403HierarchyManager *VspOspViewCellsManager::CreateHierarchyManager(const string &hierarchyType)
5404{
5405        HierarchyManager *hierarchyManager;
5406
5407        if (strcmp(hierarchyType.c_str(), "osp") == 0)
5408        {
5409                Debug << "hierarchy manager: osp" << endl;
5410                hierarchyManager = new HierarchyManager(HierarchyManager::KD_BASED_OBJ_SUBDIV);
5411        }
5412        else if (strcmp(hierarchyType.c_str(), "bvh") == 0)
5413        {
5414                Debug << "hierarchy manager: bvh" << endl;
5415                hierarchyManager = new HierarchyManager(HierarchyManager::BV_BASED_OBJ_SUBDIV);
5416        }
5417        else // only view space partition
5418        {
5419                Debug << "hierarchy manager: obj" << endl;
5420                hierarchyManager = new HierarchyManager(HierarchyManager::NO_OBJ_SUBDIV);
5421        }
5422
5423        return hierarchyManager;
5424}
5425
5426
5427VspOspViewCellsManager::~VspOspViewCellsManager()
5428{
5429        DEL_PTR(mHierarchyManager);
5430}
5431
5432
5433float VspOspViewCellsManager::GetProbability(ViewCell *viewCell)
5434{
5435        return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
5436}
5437
5438
5439void VspOspViewCellsManager::CollectViewCells()
5440{
5441        // view cells tree constructed
5442        if (!ViewCellsTreeConstructed())
5443        {
5444                mHierarchyManager->GetVspTree()->CollectViewCells(mViewCells, false);
5445        }
5446        else
5447        {       // we can use the view cells tree hierarchy to get the right set
5448                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
5449        }
5450}
5451
5452
5453bool VspOspViewCellsManager::ViewCellsConstructed() const
5454{
5455        return mHierarchyManager->GetVspTree()->GetRoot() != NULL;
5456}
5457
5458
5459ViewCell *VspOspViewCellsManager::GenerateViewCell(Mesh *mesh) const
5460{
5461        return new VspViewCell(mesh);
5462}
5463
5464
5465int VspOspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
5466                                                                                                 const VssRayContainer &rays)
5467{
5468        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
5469
5470        // skip rest if view cells were already constructed
5471        if (ViewCellsConstructed())
5472                return 0;
5473
5474        int sampleContributions = 0;
5475        VssRayContainer sampleRays;
5476
5477        int limit = min (mInitialSamples, (int)rays.size());
5478
5479        VssRayContainer constructionRays;
5480        VssRayContainer savedRays;
5481
5482        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
5483                  << ", actual rays: " << (int)rays.size() << endl;
5484
5485        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
5486
5487        Debug << "initial rays used for construction: " << (int)constructionRays.size() << endl;
5488        Debug << "saved rays: " << (int)savedRays.size() << endl;
5489
5490        mHierarchyManager->Construct(constructionRays, objects, &mViewSpaceBox);
5491
5492#if TEST_EVALUATION
5493        VssRayContainer::const_iterator tit, tit_end = constructionRays.end();
5494        for (tit = constructionRays.begin(); tit != tit_end; ++ tit)
5495        {
5496                storedRays.push_back(new VssRay(*(*tit)));
5497        }
5498#endif
5499
5500        /////////////////////////
5501        //-- print satistics for subdivision and view cells
5502
5503        Debug << endl << endl << *mHierarchyManager << endl;
5504
5505        ResetViewCells();
5506        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
5507
5508        //////////////
5509        //-- recast rest of rays
5510       
5511        const long startTime = GetTime();
5512        cout << "Computing remaining ray contributions ... ";
5513
5514        if (SAMPLE_AFTER_SUBDIVISION)
5515                ComputeSampleContributions(savedRays, true, false);
5516
5517        Debug << "finished computing remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
5518                  << " secs" << endl;
5519
5520        if (0)
5521        {       
5522                // real meshes are constructed at this stage
5523                cout << "finalizing view cells ... ";
5524        FinalizeViewCells(true);
5525                cout << "finished" << endl;
5526        }
5527
5528        return sampleContributions;
5529}
5530
5531
5532int VspOspViewCellsManager::PostProcess(const ObjectContainer &objects,
5533                                                                                const VssRayContainer &rays)
5534{
5535        if (!ViewCellsConstructed())
5536        {
5537                Debug << "post process error: no view cells constructed" << endl;
5538                return 0;
5539        }
5540
5541        // if view cells were already constructed before post processing step
5542        // (e.g., because they were loaded), we are finished
5543        if (mViewCellsFinished)
5544        {
5545                FinalizeViewCells(true);
5546                EvaluateViewCellsStats();
5547
5548                return 0;
5549        }
5550
5551        // check if new view cells turned invalid
5552        int minPvs, maxPvs;
5553
5554        if (0)
5555        {
5556                minPvs = mMinPvsSize;
5557                maxPvs = mMaxPvsSize;
5558        }
5559        else
5560        {
5561                // problem matt: why did I start here from zero?
5562                minPvs = 0;
5563                maxPvs = mMaxPvsSize;
5564        }
5565
5566        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5567        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5568       
5569        SetValidity(minPvs, maxPvs);
5570
5571       
5572        // area is not up to date, has to be recomputed
5573        mTotalAreaValid = false;
5574        VssRayContainer postProcessRays;
5575        GetRaySets(rays, mPostProcessSamples, postProcessRays);
5576
5577        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
5578
5579
5580        // compute tree by merging the nodes of the spatial hierarchy
5581        ViewCell *root = ConstructSpatialMergeTree(mHierarchyManager->GetVspTree()->GetRoot());
5582        mViewCellsTree->SetRoot(root);
5583
5584        //////////////////////////
5585        //-- update pvs up to the root of the hierarchy
5586
5587        ObjectPvs pvs;
5588        UpdatePvsForEvaluation(root, pvs);
5589
5590
5591        //////////////////////
5592        //-- render simulation after merge + refine
5593
5594        cout << "\nview cells partition render time before compress" << endl << endl;
5595        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
5596        SimulationStatistics ss;
5597        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
5598        cout << ss << endl;
5599       
5600
5601        mHierarchyManager->CreateUniqueObjectIds();
5602
5603        ///////////
5604        //-- compression
5605
5606        if (0) CompressViewCells();
5607
5608        /////////////
5609        //-- some tasks still to do on the view cells:
5610        //-- Compute meshes from view cell geometry, evaluate volume and / or area
5611
5612        if (1) FinalizeViewCells(true);
5613
5614        return 0;
5615}
5616
5617
5618int VspOspViewCellsManager::GetType() const
5619{
5620        return VSP_OSP;
5621}
5622
5623
5624ViewCell *VspOspViewCellsManager::ConstructSpatialMergeTree(VspNode *root)
5625{
5626        // terminate recursion
5627        if (root->IsLeaf())
5628        {
5629                VspLeaf *leaf = dynamic_cast<VspLeaf *>(root);
5630                leaf->GetViewCell()->SetMergeCost(0.0f);
5631                return leaf->GetViewCell();
5632        }
5633       
5634        VspInterior *interior = dynamic_cast<VspInterior *>(root);
5635        ViewCellInterior *viewCellInterior = new ViewCellInterior();
5636               
5637        // evaluate merge cost for priority traversal
5638        const float mergeCost = -(float)root->mTimeStamp;
5639        viewCellInterior->SetMergeCost(mergeCost);
5640
5641        float volume = 0;
5642       
5643        VspNode *front = interior->GetFront();
5644        VspNode *back = interior->GetBack();
5645
5646        ObjectPvs frontPvs, backPvs;
5647
5648        /////////
5649        //-- recursivly compute child hierarchies
5650
5651        ViewCell *backVc = ConstructSpatialMergeTree(back);
5652        ViewCell *frontVc = ConstructSpatialMergeTree(front);
5653
5654        viewCellInterior->SetupChildLink(backVc);
5655        viewCellInterior->SetupChildLink(frontVc);
5656
5657        volume += backVc->GetVolume();
5658        volume += frontVc->GetVolume();
5659
5660        viewCellInterior->SetVolume(volume);
5661
5662        return viewCellInterior;
5663}
5664
5665
5666bool VspOspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
5667{
5668        if (!ViewCellsConstructed())
5669                return ViewCellsManager::GetViewPoint(viewPoint);
5670
5671        // TODO: set reasonable limit
5672        const int limit = 20;
5673
5674        for (int i = 0; i < limit; ++ i)
5675        {
5676                viewPoint = mViewSpaceBox.GetRandomPoint();
5677
5678                if (mHierarchyManager->GetVspTree()->ViewPointValid(viewPoint))
5679                {
5680                        return true;
5681                }
5682        }
5683
5684        Debug << "failed to find valid view point, taking " << viewPoint << endl;
5685        return false;
5686}
5687
5688
5689void VspOspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
5690                                                                                                        ViewCell *vc,
5691                                                                                                        const AxisAlignedBox3 *sceneBox,
5692                                                                                                        const AxisAlignedPlane *clipPlane
5693                                                                                                        ) const
5694{
5695        ViewCellContainer leaves;
5696        mViewCellsTree->CollectLeaves(vc, leaves);
5697        ViewCellContainer::const_iterator it, it_end = leaves.end();
5698
5699        Plane3 plane;
5700        if (clipPlane)
5701        {
5702                // arbitrary plane definition
5703                plane = clipPlane->GetPlane();
5704        }
5705
5706        for (it = leaves.begin(); it != it_end; ++ it)
5707        {
5708                VspViewCell *vspVc = dynamic_cast<VspViewCell *>(*it);
5709                VspLeaf *l = vspVc->mLeaves[0];
5710
5711                const AxisAlignedBox3 box =
5712                        mHierarchyManager->GetVspTree()->GetBoundingBox(vspVc->mLeaves[0]);
5713               
5714                if (sceneBox && !Overlap(*sceneBox, box))
5715                        continue;
5716
5717                if (clipPlane)
5718                {
5719                        if (box.Side(plane) == -1)
5720                        {
5721                                exporter->ExportBox(box);
5722                        }
5723                        else if (box.Side(plane) == 0)
5724                        {
5725                                // intersection
5726                                AxisAlignedBox3 fbox, bbox;
5727                                box.Split(clipPlane->mAxis, clipPlane->mPosition, fbox, bbox);
5728                                exporter->ExportBox(bbox);
5729                        }
5730                }
5731                else
5732                {
5733                        exporter->ExportBox(box);
5734                }
5735        }
5736}
5737
5738
5739bool VspOspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
5740{
5741  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
5742  // validy update in preprocessor for all managers)
5743  return ViewCellsManager::ViewPointValid(viewPoint);
5744
5745  //    return mViewSpaceBox.IsInside(viewPoint) &&
5746  //               mVspTree->ViewPointValid(viewPoint);
5747}
5748
5749
5750float VspOspViewCellsManager::UpdateObjectCosts()
5751{
5752        float maxRenderCost = 0;
5753
5754        cout << "updating object pvs cost ... ";
5755        const long startTime = GetTime();
5756
5757        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
5758
5759        Intersectable::NewMail();
5760
5761        const float invViewSpaceVol = 1.0f / GetViewSpaceBox().GetVolume();
5762
5763        for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
5764        {
5765                ViewCell *vc = *vit;
5766
5767                ObjectPvsIterator pit = vc->GetPvs().GetIterator();
5768
5769                // output PVS of view cell
5770                while (pit.HasMoreEntries())
5771                {               
5772                        ObjectPvsEntry entry = pit.Next();
5773                               
5774                        BvhNode *node = dynamic_cast<BvhNode *>(entry.mObject);
5775                       
5776                        // hack!!
5777                        if (!node->IsLeaf())
5778                        {
5779                                cout << "error, can only do leaves" << endl;
5780                                return 0;
5781                        }
5782       
5783                        if (!node->Mailed())
5784                        {
5785                                node->Mail();
5786                                node->mRenderCost = 0;
5787                        }
5788
5789                        const float rc = (float)((BvhLeaf *)node)->mObjects.size();
5790
5791                        node->mRenderCost += rc * vc->GetVolume() * invViewSpaceVol;
5792
5793                        if (node->mRenderCost > maxRenderCost)
5794                                maxRenderCost = node->mRenderCost;
5795                }
5796        }
5797
5798        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3f << " secs" << endl;
5799
5800        return maxRenderCost;
5801}
5802
5803
5804void VspOspViewCellsManager::Visualize(const ObjectContainer &objects,
5805                                                                           const VssRayContainer &sampleRays)
5806{
5807        if (!ViewCellsConstructed())
5808                return;
5809
5810        VssRayContainer visRays;
5811        GetRaySets(sampleRays, mVisualizationSamples, visRays);
5812
5813        ////////////
5814        //-- export final view cells
5815
5816        Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
5817
5818        //Vector3 scale(0.9f, 0.9f, 0.9f);
5819        Vector3 scale(1.0f, 1.0f, 1.0f);
5820
5821        if (exporter)
5822        {
5823                if (CLAMP_TO_BOX)
5824                {       
5825                        exporter->mClampToBox = true;   
5826                }
5827
5828                EvaluateViewCellsStats();
5829
5830                const long starttime = GetTime();
5831                cout << "exporting final view cells (after initial construction + post process) ... ";
5832
5833                // matt: hack for clamping scene
5834                AxisAlignedBox3 bbox = mViewSpaceBox;
5835                bbox.Scale(scale);
5836
5837                if (0 && mExportRays)
5838                {       
5839                        exporter->ExportRays(visRays, RgbColor(0, 1, 0));
5840                }
5841
5842                // hack color code (show pvs size)
5843                const int savedColorCode = mColorCode;
5844
5845                const float maxRenderCost = UpdateObjectCosts();
5846                cout << "maxRenderCost: " << maxRenderCost << endl;
5847                mColorCode = 0; // 0 = random, 1 = export pvs
5848
5849                mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects,
5850                                                                                                          CLAMP_TO_BOX ? &bbox : NULL, maxRenderCost, false);
5851               
5852
5853                //ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
5854                ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
5855
5856                delete exporter;
5857
5858                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
5859                mColorCode = savedColorCode;
5860        }
5861
5862        exporter = Exporter::GetExporter("final_object_partition.wrl");
5863
5864        if (exporter)
5865        {
5866                if (CLAMP_TO_BOX)
5867                {       
5868                        exporter->mClampToBox = true;   
5869                }
5870
5871                EvaluateViewCellsStats();
5872
5873                const long starttime = GetTime();
5874                cout << "exporting final objects (after initial construction + post process) ... ";
5875
5876                // matt: hack for clamping scene
5877                AxisAlignedBox3 bbox = mViewSpaceBox;
5878                bbox.Scale(scale);
5879
5880                // hack color code (show pvs size)
5881                const int savedColorCode = mColorCode;
5882
5883                mColorCode = 1; // 0 = random, 1 = export pvs
5884                const float maxRenderCost = -1;
5885
5886                mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects,
5887                                                                                                          CLAMP_TO_BOX ? &bbox : NULL, maxRenderCost, false);
5888               
5889
5890                //ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, mColorCode, GetClipPlane());
5891                ExportViewCellsForViz(exporter, NULL, mColorCode, GetClipPlane());
5892
5893                delete exporter;
5894
5895                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
5896                mColorCode = savedColorCode;
5897        }
5898
5899#if 0
5900        // export final object partition
5901        exporter = Exporter::GetExporter("final_object_partition.wrl");
5902
5903        if (exporter)
5904        {
5905                if (CLAMP_TO_BOX)
5906                {       
5907                        exporter->mClampToBox = true;   
5908                }
5909
5910                const long starttime = GetTime();
5911
5912                // matt: hack for making visualization smaller in size
5913                AxisAlignedBox3 bbox = mHierarchyManager->GetObjectSpaceBox();
5914                bbox.Scale(scale);
5915
5916                cout << "exporting object space hierarchy ... ";
5917                mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects, CLAMP_TO_BOX ? &bbox : NULL, -1);
5918
5919                delete exporter;
5920                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
5921        }
5922#endif
5923
5924        // visualization of the view cells
5925    if (0)
5926        {       
5927                ExportMergedViewCells(objects);
5928        }
5929
5930        // export some view cells
5931        int leafOut;
5932        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
5933
5934        const bool sortViewCells = false;
5935        const bool exportPvs = true;
5936        const bool exportRays = true;
5937        const int raysOut = 100;
5938
5939        ExportSingleViewCells(objects,
5940                                                  leafOut,
5941                                                  sortViewCells,
5942                                                  exportPvs,
5943                                                  exportRays,
5944                                                  raysOut,
5945                                                  "");
5946}
5947
5948
5949void VspOspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
5950                                                                                                   const int maxViewCells,
5951                                                                                                   const bool sortViewCells,
5952                                                                                                   const bool exportPvs,
5953                                                                                                   const bool exportRays,
5954                                                                                                   const int maxRays,
5955                                                                                                   const string prefix,
5956                                                                                                   VssRayContainer *visRays)
5957{
5958        if (sortViewCells)
5959        {
5960                // sort view cells to visualize the view cells with highest render cost
5961                sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
5962        }
5963
5964        ViewCell::NewMail();
5965        const int limit = min(maxViewCells, (int)mViewCells.size());
5966       
5967        cout << "\nExporting " << limit << " single view cells: " << endl;
5968       
5969        for (int i = 0; i < limit; ++ i)
5970        {
5971                cout << "creating output for view cell " << i << " ... ";
5972               
5973                // largest view cell pvs first of random view cell
5974                ViewCell *vc = sortViewCells ?
5975                        mViewCells[i] : mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
5976               
5977                if (vc->Mailed()) // view cell already processed
5978                        continue;
5979
5980                vc->Mail();
5981
5982                ObjectPvs pvs;
5983                mViewCellsTree->GetPvs(vc, pvs);
5984
5985                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
5986                Exporter *exporter = Exporter::GetExporter(s);
5987               
5988                cout << "view cell " << vc->GetId() << ": pvs cost=" << mViewCellsTree->GetPvsCost(vc) << endl;
5989
5990                if (exportPvs)
5991                {
5992                        Material m;
5993
5994                        Intersectable::NewMail();
5995                       
5996                        ObjectPvsIterator pit = pvs.GetIterator();
5997
5998                        // output PVS of view cell
5999                        while (pit.HasMoreEntries())
6000                        {               
6001                                ObjectPvsEntry entry = pit.Next();
6002                               
6003                                Intersectable *intersect = entry.mObject;
6004
6005                                if (!intersect->Mailed())
6006                                {
6007                                        m = RandomMaterial();
6008                                        exporter->SetForcedMaterial(m);
6009
6010                                        exporter->ExportIntersectable(intersect);
6011                                        intersect->Mail();
6012                                }
6013                        }
6014                }
6015
6016                if (exportRays)
6017                {
6018                        ////////////
6019                        //-- export the sample rays
6020
6021                        // output rays stored with the view cells during subdivision
6022                        VssRayContainer vcRays;
6023                        VssRayContainer collectRays;
6024
6025                        // collect intial view cells
6026                        ViewCellContainer leaves;
6027                        mViewCellsTree->CollectLeaves(vc, leaves);
6028
6029                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
6030
6031                        for (vit = leaves.begin(); vit != vit_end; ++ vit)
6032                        {
6033                                VspLeaf *vcLeaf = dynamic_cast<VspViewCell *>(*vit)->mLeaves[0];
6034                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
6035
6036                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
6037                                {
6038                                        collectRays.push_back(*rit);
6039                                }
6040                        }
6041
6042                        const int raysOut = min((int)collectRays.size(), maxRays);
6043
6044                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
6045
6046                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
6047                        {
6048                                const float p = RandomValue(0.0f, (float)collectRays.size());
6049
6050                                if (p < raysOut)
6051                                        vcRays.push_back(*rit);
6052                        }
6053
6054                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
6055                }
6056               
6057       
6058                /////////////////
6059                //-- export view cell geometry
6060
6061                exporter->SetWireframe();
6062
6063                Material m;
6064                m.mDiffuseColor = RgbColor(0, 1, 0);
6065                exporter->SetForcedMaterial(m);
6066
6067                ExportViewCellGeometry(exporter, vc, NULL, NULL);
6068                exporter->SetFilled();
6069
6070                DEL_PTR(exporter);
6071                cout << "finished" << endl;
6072        }
6073
6074        cout << endl;
6075}
6076
6077
6078int VspOspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
6079                                                                                                        ViewCellContainer &viewCells) const
6080{
6081        return mHierarchyManager->GetVspTree()->ComputeBoxIntersections(box, viewCells);
6082}
6083
6084
6085int VspOspViewCellsManager::CastLineSegment(const Vector3 &origin,
6086                                                                                        const Vector3 &termination,
6087                                                                                        ViewCellContainer &viewcells)
6088{
6089        return mHierarchyManager->GetVspTree()->CastLineSegment(origin, termination, viewcells);
6090}
6091
6092
6093bool VspOspViewCellsManager::ExportViewCells(const string filename,
6094                                                                                         const bool exportPvs,
6095                                                                                         const ObjectContainer &objects)
6096{
6097        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
6098                return false;
6099
6100        const long starttime = GetTime();
6101        cout << "exporting view cells to xml ... ";
6102       
6103        OUT_STREAM stream(filename.c_str());
6104
6105        // for output we need unique ids for each view cell
6106        CreateUniqueViewCellIds();
6107
6108        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
6109        stream << "<VisibilitySolution>" << endl;
6110
6111        // §§ tmp matt: for storage cost
6112        if (0 && exportPvs)
6113        {
6114        ///////////////
6115                //-- export bounding boxes
6116                //-- The bounding boxes are used to identify
6117                //-- the objects in the rendering engine
6118                mHierarchyManager->ExportBoundingBoxes(stream, objects);
6119        }
6120
6121        //////////////////////////
6122        //-- export the view cells and the pvs
6123
6124        const int numViewCells = mCurrentViewCellsStats.viewCells;
6125
6126        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
6127        mViewCellsTree->Export(stream, exportPvs);
6128        stream << "</ViewCells>" << endl;
6129
6130        //////////////////////
6131        //-- export the view space hierarchy
6132       
6133        stream << "<ViewSpaceHierarchy type=\"vsp\""
6134                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
6135                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
6136
6137        mHierarchyManager->GetVspTree()->Export(stream);
6138        stream << "</ViewSpaceHierarchy>" << endl;
6139
6140        ////////////////////// 
6141        //-- export the object space partition
6142       
6143        mHierarchyManager->ExportObjectSpaceHierarchy(stream);
6144       
6145        stream << "</VisibilitySolution>" << endl;
6146        stream.close();
6147       
6148        cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3 << " secs" << endl;
6149        return true;
6150}
6151
6152
6153
6154ViewCell *VspOspViewCellsManager::GetViewCell(const Vector3 &point,
6155                                                                                          const bool active) const
6156{
6157        if (!ViewCellsConstructed())
6158                return NULL;
6159
6160        if (!mViewSpaceBox.IsInside(point))
6161                return NULL;
6162
6163        return mHierarchyManager->GetVspTree()->GetViewCell(point, active);
6164}
6165
6166
6167void VspOspViewCellsManager::CreateMesh(ViewCell *vc)
6168{
6169        // matt: TODO
6170        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
6171
6172        ViewCellContainer leaves;
6173        mViewCellsTree->CollectLeaves(vc, leaves);
6174
6175        ViewCellContainer::const_iterator it, it_end = leaves.end();
6176
6177    for (it = leaves.begin(); it != it_end; ++ it)
6178        {
6179                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
6180                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
6181        IncludeBoxInMesh(box, *mesh);
6182        }
6183
6184        vc->SetMesh(mesh);
6185}
6186
6187
6188int VspOspViewCellsManager::CastBeam(Beam &beam)
6189{
6190        // matt: TODO
6191        return 0;
6192}
6193
6194
6195void VspOspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
6196{
6197        float area = 0;
6198        float volume = 0;
6199
6200        ViewCellContainer leaves;
6201        mViewCellsTree->CollectLeaves(viewCell, leaves);
6202
6203        ViewCellContainer::const_iterator it, it_end = leaves.end();
6204
6205    for (it = leaves.begin(); it != it_end; ++ it)
6206        {
6207                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
6208               
6209                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
6210
6211                const float lVol = box.GetVolume();
6212                const float lArea = box.SurfaceArea();
6213
6214                area += lArea;
6215                volume += lVol;
6216
6217        CreateMesh(*it);
6218        }
6219
6220        viewCell->SetVolume(volume);
6221        viewCell->SetArea(area);
6222}
6223
6224
6225void VspOspViewCellsManager::PrepareLoadedViewCells()
6226{
6227        // TODO
6228}
6229
6230
6231static void PrintCompressionStats(HierarchyManager *hm, const int pvsEntries)
6232{
6233        float mem = (float)pvsEntries * ObjectPvs::GetEntrySize();
6234               
6235        float fullmem = mem +
6236                        (hm->GetVspTree()->GetStatistics().Leaves() * 16 +
6237                         hm->mBvHierarchy->GetStatistics().Leaves() * 16) / float(1024 * 1024);
6238
6239        cout << "entries: " << pvsEntries << ", mem=" << mem << ", fullmem=" << fullmem <<endl;
6240        Debug << "entries: " << pvsEntries << ", mem=" << mem << ", fullmem=" << fullmem <<endl;
6241}
6242
6243
6244void VspOspViewCellsManager::CompressViewCells()
6245{
6246        if (!(ViewCellsTreeConstructed() && mCompressViewCells))
6247                return;
6248
6249        ////////////
6250        //-- compression
6251
6252        int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
6253
6254        cout << "before compression: " << endl;
6255        Debug << "before compression: " << endl;
6256       
6257        PrintCompressionStats(mHierarchyManager, pvsEntries);
6258
6259        if (mCompressObjects)
6260        {
6261                cout << "compressing in the objects: " << endl;
6262                Debug << "compressing in the objects: " << endl;
6263
6264                pvsEntries = mHierarchyManager->CompressObjectSpace();
6265        }
6266        else
6267        {
6268                cout << "compressing in the view space: " << endl;
6269                Debug << "compressing in the view space: " << endl;
6270
6271                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
6272                pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
6273        }
6274
6275        PrintCompressionStats(mHierarchyManager, pvsEntries);
6276}
6277
6278
6279ViewCellsManager *VspOspViewCellsManager::LoadViewCells(const string &filename,
6280                                                                                                                ObjectContainer *objects,
6281                                                                                                                const bool finalizeViewCells,
6282                                                                                                                BoundingBoxConverter *bconverter)
6283                                                                                                 
6284{
6285        ViewCellsManager *vm =
6286                ViewCellsManager::LoadViewCells(filename, objects, finalizeViewCells, bconverter);
6287#if 0
6288        // insert scene objects in tree
6289        mOspTree->InsertObjects(mOspTree->GetRoot(), *objects);
6290#endif
6291        return vm;
6292}
6293
6294
6295void
6296VspOspViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
6297{
6298  mHierarchyManager->CollectObjects(box, objects);
6299}
6300
6301
6302#if 1
6303
6304void VspOspViewCellsManager::EvalViewCellPartition()
6305{
6306        int samplesPerPass;
6307        int numSamples;
6308        int castSamples = 0;
6309        int oldSamples = 0;
6310        int samplesForStats;
6311        char statsPrefix[100];
6312        char suffix[100];
6313        int splitsStepSize;
6314
6315        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
6316        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
6317        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
6318        Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
6319        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.stepSize", splitsStepSize);
6320       
6321        bool useHisto;
6322        int histoMem;
6323
6324        Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
6325        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoMem", histoMem);
6326
6327        Debug << "step size: " << splitsStepSize << endl;
6328        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
6329        Debug << "view cell evaluation samples: " << numSamples << endl;
6330        Debug << "view cell stats prefix: " << statsPrefix << endl;
6331
6332    cout << "reseting pvs ... ";
6333               
6334        // reset pvs and start over from zero
6335        mViewCellsTree->ResetPvs();
6336       
6337        cout << "finished" << endl;
6338    cout << "Evaluating view cell partition ... " << endl;
6339
6340        vector<int> evalStrats;
6341
6342        // mix of sampling strategies
6343        if (0)
6344        {
6345                evalStrats.push_back(SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION);
6346        }
6347        else
6348        {
6349                /*evalStrats.push_back(SamplingStrategy::OBJECT_BASED_DISTRIBUTION);
6350                evalStrats.push_back(SamplingStrategy::REVERSE_VIEWSPACE_BORDER_BASED_DISTRIBUTION);
6351                evalStrats.push_back(SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION);
6352                */
6353                evalStrats.push_back(SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION);
6354        }
6355                       
6356    Debug << "casting eval strategies: ";
6357        for (int i = 0; i < (int)evalStrats.size(); ++ i)
6358                Debug << evalStrats[i] << " ";
6359        Debug << endl;
6360
6361        cout << "casting eval strategies: ";
6362        for (int i = 0; i < (int)evalStrats.size(); ++ i)
6363                cout << evalStrats[i] << " ";
6364        cout << endl;
6365
6366        int pass = 0;
6367
6368        while (castSamples < numSamples)
6369        {               
6370                ///////////////
6371                //-- we have to use uniform sampling strategy for construction rays
6372
6373                VssRayContainer evaluationSamples;
6374                const int samplingType = mEvaluationSamplingType;
6375
6376                long startTime = GetTime();
6377
6378                cout << "casting " << samplesPerPass << " samples ... ";
6379                Debug << "casting " << samplesPerPass << " samples ... ";
6380       
6381                if (1)
6382                {
6383                        CastPassSamples(samplesPerPass, evalStrats, evaluationSamples);
6384                }
6385                else
6386                {
6387                        // use mixed distributions
6388                        CastPassSamples2(samplesPerPass, evaluationSamples);
6389                }
6390
6391                castSamples += samplesPerPass;
6392
6393                Real timeDiff = TimeDiff(startTime, GetTime());
6394               
6395                cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
6396                cout << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
6397               
6398                Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
6399                Debug << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
6400
6401                startTime = GetTime();
6402
6403                ComputeSampleContributions(evaluationSamples, true, false);
6404
6405                timeDiff = TimeDiff(startTime, GetTime());
6406                cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6407                Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6408
6409                if ((castSamples >= samplesForStats + oldSamples) ||
6410                        (castSamples >= numSamples))
6411                {
6412                        oldSamples += samplesForStats;
6413
6414                        ///////////
6415                        //-- output stats
6416
6417                        sprintf(suffix, "-%09d-eval.log", castSamples);
6418                        const string filename = string(statsPrefix) + string(suffix);
6419
6420                        startTime = GetTime();
6421                       
6422                        cout << "compute new statistics ... " << endl;
6423
6424                        ofstream ofstr(filename.c_str());
6425                        mHierarchyManager->EvaluateSubdivision2(ofstr, splitsStepSize, false, useHisto, histoMem, pass);
6426
6427                        timeDiff = TimeDiff(startTime, GetTime());
6428                        cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6429                        cout << "*************************************" << endl;
6430
6431                        Debug << "statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
6432
6433#if 0
6434                        //////////////
6435                        // filtered stats
6436
6437                        sprintf(suffix, "-%09d-eval-filter.log", castSamples);
6438                        const string filename2 = string(statsPrefix) + string(suffix);
6439
6440                        startTime = GetTime();
6441                       
6442                        cout << "compute new statistics for filtered pvs ... " << endl;
6443
6444                        ofstream ofstr2(filename2.c_str());
6445                        mHierarchyManager->EvaluateSubdivision2(ofstr2, splitsStepSize, true);
6446
6447                        timeDiff = TimeDiff(startTime, GetTime());
6448                        cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6449                        cout << "*************************************" << endl;
6450                        Debug << "filtered statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
6451#endif
6452
6453                        // only for debugging purpose
6454                        if (0)
6455                        {
6456                                ViewCellContainer viewCells;
6457                                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), viewCells);
6458
6459                                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
6460                                int pvsSize = 0;
6461
6462                                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
6463                                {
6464                                        pvsSize += (*vit)->GetPvs().GetSize();
6465                                }
6466
6467                                cout << "debug entries: " << pvsSize << ", memcost: "
6468                                         << (float)pvsSize * ObjectPvs::GetEntrySize() << endl;
6469                        }
6470                        ++ pass;
6471                }
6472
6473                disposeRays(evaluationSamples, NULL);
6474        }
6475
6476        ////////////
6477        //-- histogram
6478#if 1
6479        const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
6480        int histoStepSize;
6481
6482        Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
6483        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoStepSize", histoStepSize);
6484
6485        if (useHisto)
6486        {
6487                // evaluate view cells in a histogram           
6488                char str[64];
6489
6490                // hack: just show final view cells
6491                int pass = (int)mViewCells.size();
6492                //for (int pass = histoStepSize; pass <= numLeaves; pass += histoStepSize)
6493                if (1)
6494                {
6495                        string filename;
6496
6497                        cout << "computing histogram for " << pass << " view cells" << endl;
6498
6499                        //////////////////////////////////////////
6500            //-- evaluate histogram for pvs size
6501
6502                        cout << "computing pvs histogram for " << pass << " view cells" << endl;
6503
6504                        sprintf(str, "-%09d-histo-pvs2.log", pass);
6505                        filename = string(statsPrefix) + string(str);
6506
6507                        EvalViewCellHistogramForPvsSize(filename, pass);
6508                }
6509        }
6510#endif
6511}
6512
6513#endif
6514
6515
6516
6517}
Note: See TracBrowser for help on using the repository browser.