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

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