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

Revision 1983, 167.4 KB checked in by bittner, 17 years ago (diff)

merge

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