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

Revision 722, 100.7 KB checked in by mattausch, 19 years ago (diff)
Line 
1#include "ViewCellsManager.h"
2#include "RenderSimulator.h"
3#include "Mesh.h"
4#include "Triangle3.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "X3dParser.h"
8#include "ViewCellBsp.h"
9#include "KdTree.h"
10#include "VspKdTree.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
18// HACK
19const static bool SAMPLE_AFTER_SUBDIVISION = true;
20const static bool TEST_EMPTY_VIEW_CELLS = false;
21
22
23
24template <typename T> class myless
25{
26public:
27        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
28        bool operator() (T v1, T v2) const
29        {
30                return (v1->GetMergeCost() < v2->GetMergeCost());
31        }
32};
33
34//typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > FilterQueue;
35
36
37
38ViewCellsManager::ViewCellsManager():
39mRenderer(NULL),
40mInitialSamples(0),
41mConstructionSamples(0),
42mPostProcessSamples(0),
43mVisualizationSamples(0),
44mTotalAreaValid(false),
45mTotalArea(0.0f),
46mViewCellsFinished(false),
47mMaxPvsSize(9999999),
48mMinPvsSize(0), // one means only empty view cells are invalid
49mMaxPvsRatio(1.0),
50mViewCellPvsIsUpdated(false)
51{
52        mViewSpaceBox.Initialize();
53        ParseEnvironment();
54
55        mViewCellsTree = new ViewCellsTree(this);
56}
57
58
59void ViewCellsManager::ParseEnvironment()
60{
61        // visualization stuff
62        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
63        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
64        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
65       
66        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", mPruneEmptyViewCells);
67
68        // HACK
69        if (0)
70                mMinPvsSize = mPruneEmptyViewCells ? 1 : 0;
71        else
72                mMinPvsSize = 0;
73
74        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
75
76        environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
77        environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
78        environment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
79
80        environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
81
82        environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
83        environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
84       
85        environment->GetIntValue("ViewCells.active", mNumActiveViewCells);
86        environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
87        environment->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
88        environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
89        environment->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
90        environment->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
91        environment->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
92        environment->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
93
94        char buf[100];
95        environment->GetStringValue("ViewCells.samplingType", buf);
96
97       
98        if (strcmp(buf, "box") == 0)
99        {
100                mSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
101        }
102        else if (strcmp(buf, "directional") == 0)
103        {
104                mSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
105        }
106        else
107        {
108                Debug << "error! wrong sampling type" << endl;
109                exit(0);
110        }
111
112        environment->GetStringValue("ViewCells.Evaluation.samplingType", buf);
113       
114        if (strcmp(buf, "box") == 0)
115        {
116                mEvaluationSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
117        }
118        else if (strcmp(buf, "directional") == 0)
119        {
120                mEvaluationSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
121        }
122        else
123        {
124                Debug << "error! wrong sampling type" << endl;
125                exit(0);
126        }
127
128    environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
129
130        if (strcmp(buf, "PVS") == 0)
131                mColorCode = 1;
132        else if (strcmp(buf, "MergedLeaves") == 0)
133                mColorCode = 2;
134        else if (strcmp(buf, "MergedTreeDiff") == 0)
135                mColorCode = 3;
136        else
137                mColorCode = 0;
138
139
140
141        Debug << "***********View Cells options ****************" << endl;
142        Debug << "color code: " << mColorCode << endl;
143
144        Debug << "export rays: " << mExportRays << endl;
145        Debug << "export geometry: " << mExportGeometry << endl;
146        Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
147       
148        Debug << "prune empty view cells: " << mPruneEmptyViewCells << endl;
149       
150        Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
151        Debug << "construction samples: " << mConstructionSamples << endl;
152        Debug << "post process samples: " << mPostProcessSamples << endl;
153        Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
154        Debug << "visualization samples: " << mVisualizationSamples << endl;
155        Debug << "construction samples per pass: " << mSamplesPerPass << endl;
156        Debug << "export to file: " << mExportViewCells << endl;
157       
158        Debug << "active: " << mNumActiveViewCells << endl;
159        Debug << "post process compress: " << mCompressViewCells << endl;
160        Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
161        Debug << "post process merge: " << mMergeViewCells << endl;
162        Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
163        Debug << "sampling type: " << mSamplingType << endl;
164        Debug << "show visualization: " << mShowVisualization << endl;
165        Debug << "filter width: " << mFilterWidth << endl;
166        Debug << "sample after subdivision: " << SAMPLE_AFTER_SUBDIVISION << endl;
167        Debug << endl;
168}
169
170
171ViewCellsManager::~ViewCellsManager()
172{
173        DEL_PTR(mRenderer);
174
175        if (!ViewCellsTreeConstructed())
176                CLEAR_CONTAINER(mViewCells);
177        else
178                DEL_PTR(mViewCellsTree);
179
180        CLEAR_CONTAINER(mMeshContainer);
181}
182
183
184void ViewCellsManager::CollectEmptyViewCells()
185{
186        mEmptyViewCells.clear();
187        ViewCellContainer leaves;
188        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
189
190        ViewCellContainer::const_iterator it, it_end = leaves.end();
191
192        cout << "collecting empty view cells" << endl;
193       
194        for (it = leaves.begin(); it != it_end; ++ it)
195        {
196                if ((*it)->GetPvs().Empty())
197                {
198                        mEmptyViewCells.push_back(*it);
199                }
200        }
201        Debug << "empty view cells found: " << (int)mEmptyViewCells.size() << endl;
202}
203
204
205void ViewCellsManager::TestEmptyViewCells(const ObjectContainer &obj)
206{
207        ViewCellContainer::const_iterator it, it_end = mEmptyViewCells.end();
208
209        char buf[50];
210        int i = 0;
211        for (it = mEmptyViewCells.begin(); it != it_end; ++ it)
212        {
213                if (!(*it)->GetPvs().Empty())
214                {
215                        sprintf(buf, "empty-viewcells-%09d.x3d", i/*(*it)->GetId()*/);
216                        Exporter *exporter = Exporter::GetExporter(buf);
217                       
218                        if (exporter && i < 20)
219                        {
220                                Ray *pray = (*it)->mPiercingRays[0];
221                                Debug << "view cell " << (*it)->GetId() << " not empty, pvs: " << (*it)->GetPvs().GetSize() << " " << (int)pray->intersections.size() << endl;
222
223                                exporter->ExportRays((*it)->mPiercingRays);
224                                                       
225                                exporter->SetFilled();
226                                exporter->SetForcedMaterial(RgbColor(0,0,1));
227
228                                for (int j = 0; j < (int)pray->intersections.size(); ++ j)
229                                {
230                                        if (pray->intersections[j].mObject)
231                                                exporter->ExportIntersectable(pray->intersections[j].mObject);
232                                }
233
234                                //exporter->SetWireframe();
235                                exporter->SetForcedMaterial(RgbColor(0,1,0));
236                                exporter->ExportGeometry(obj);
237
238                                exporter->SetFilled();
239
240                                exporter->SetForcedMaterial(RgbColor(1,0,0));
241                                ExportViewCellGeometry(exporter, *it);
242
243                                delete exporter;               
244                        }
245
246               
247                        ++ i;
248                }
249        }
250        Debug << "\nSampled " << i << " new view cells (" << " of " << (int)mEmptyViewCells.size() << ")" << endl << endl;
251}
252
253
254int ViewCellsManager::CastPassSamples(const int samplesPerPass,
255                                                                          const int sampleType,
256                                                                          VssRayContainer &passSamples) const
257{
258        SimpleRayContainer simpleRays;
259
260        preprocessor->GenerateRays(samplesPerPass,
261                                                           sampleType,
262                                                           simpleRays);
263
264        // shoot simple ray and add it to importance samples
265        preprocessor->CastRays(simpleRays, passSamples);
266
267        return (int)passSamples.size();
268}
269
270
271
272/// helper function which destroys rays or copies them into the output ray container
273inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
274{
275        cout << "disposing samples ... ";
276        long startTime = GetTime();
277        int n = (int)rays.size();
278
279        if (outRays)
280        {
281                VssRayContainer::const_iterator it, it_end = rays.end();
282
283                for (it = rays.begin(); it != it_end; ++ it)
284                {
285                        outRays->push_back(*it);
286                }
287        }
288        else
289        {
290                VssRayContainer::const_iterator it, it_end = rays.end();
291
292                for (it = rays.begin(); it != it_end; ++ it)
293                {
294                        //(*it)->Unref();
295                        if (!(*it)->IsActive())
296                                delete (*it);
297                }
298        }
299
300        cout << "finished" << endl;
301        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
302}
303
304
305int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
306{
307        int numSamples = 0;
308        SimpleRayContainer simpleRays;
309       
310        VssRayContainer initialSamples;
311
312        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
313
314        //-- construction rays => we use uniform samples for this
315        CastPassSamples(mInitialSamples,
316                                        mSamplingType,
317                                        initialSamples);
318       
319        cout << "finished" << endl;
320
321       
322        // construct view cells
323        const int numInitialSamples =
324                ConstructSubdivision(preprocessor->mObjects, initialSamples);
325
326        numSamples += numInitialSamples;
327
328        // rays can be passed or deleted
329        disposeRays(initialSamples, outRays);
330       
331        // testing the view cell filter functionality   
332        if (0) TestFilter(preprocessor->mObjects);
333
334        // -- stats after contruction
335        ResetViewCells();
336
337        Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
338
339        if (1) // export initial view cells
340        {
341                const char filename[] = "view_cells.wrl";
342                Exporter *exporter = Exporter::GetExporter(filename);
343
344       
345                if (exporter)
346                {
347                        cout << "exporting initial view cells (=leaves) to " << filename << " ... ";
348                        if (mExportGeometry)
349                        {
350                                exporter->ExportGeometry(preprocessor->mObjects);
351                        }
352
353                        //exporter->SetWireframe();
354                        ExportViewCellsForViz(exporter);
355
356                        delete exporter;
357                        cout << "finished" << endl;
358                }
359        }
360
361        //-- guided rays are used for further sampling
362        const int n = mConstructionSamples; //+initialSamples;
363
364        // should we use directional samples?
365        bool dirSamples = (mSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
366
367        // -- the main loop
368        while (numSamples < n)
369        {
370                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
371                VssRayContainer constructionSamples;
372
373                const int samplingType = mSamplingType;
374                        /*dirSamples ?
375                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
376                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;*/
377
378                if (0) dirSamples = !dirSamples; // toggle sampling method
379
380                numSamples += CastPassSamples(mSamplesPerPass,
381                                                                          samplingType,
382                                                                          constructionSamples);
383
384                cout << "finished" << endl;
385
386                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
387
388                // TODO: leak?
389                if (1 || SAMPLE_AFTER_SUBDIVISION)
390                        ComputeSampleContributions(constructionSamples, true, false);
391
392                cout << "finished" << endl;
393
394
395                disposeRays(constructionSamples, outRays);
396
397                cout << "total samples: " << numSamples << endl;
398        }
399       
400
401        //-- post processing
402        VssRayContainer postProcessSamples;
403
404        //-- construction rays
405        CastPassSamples(mPostProcessSamples,
406                                        mSamplingType,
407                                        postProcessSamples);
408
409
410        // stats before post processing (i.e., merge)
411        EvaluateViewCellsStats();
412        Debug << "\noriginal view cell partition before post process:\n" << mCurrentViewCellsStats << endl;
413
414        mRenderer->RenderScene();
415        SimulationStatistics ss;
416        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
417
418    Debug << ss << endl;
419
420
421
422        cout << "starting post processing and visualization" << endl;
423
424
425        // store view cells for postprocessing
426        const bool storeViewCells = true;
427
428
429        if (SAMPLE_AFTER_SUBDIVISION)
430                ComputeSampleContributions(postProcessSamples, true, storeViewCells);
431
432        //-- post processing (e.g.,merging) of the view cells
433        PostProcess(preprocessor->mObjects, postProcessSamples);
434
435        // only for debugging purpose
436        if (TEST_EMPTY_VIEW_CELLS)
437                CollectEmptyViewCells();
438
439
440        //-- visualization
441        if (mShowVisualization)
442        {
443                VssRayContainer visualizationSamples;
444
445                //-- construction rays => we use uniform samples for this
446                CastPassSamples(mVisualizationSamples,
447                                            Preprocessor::DIRECTION_BASED_DISTRIBUTION,
448                                                visualizationSamples);
449
450                if (SAMPLE_AFTER_SUBDIVISION)
451                        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
452
453                // different visualizations
454                Visualize(preprocessor->mObjects, visualizationSamples);
455
456                disposeRays(visualizationSamples, outRays);
457        }
458
459        // needed to fix empty view cells
460    //SetValidity(0, 99999999999);
461
462
463        // evaluation of the paritition, i.e., a number of new samples are cast
464        if (mEvaluateViewCells)
465        {
466                EvalViewCellPartition(preprocessor);
467        }
468       
469        if (0)
470        {
471                ViewCellContainer leaves;
472                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
473                mViewCellsTree->ResetPvs();
474                VssRayContainer dummyRays;
475                CastPassSamples(mInitialSamples, mSamplingType, dummyRays);
476       
477                //ComputeSampleContributions(initialSamples, true, false);
478                ComputeSampleContributions(dummyRays, true, false);
479
480                ViewCellContainer::const_iterator it, it_end = leaves.end();
481
482                for (it = leaves.begin(); it != it_end; ++ it)
483                {
484                        mViewCellsTree->PropagatePvs(*it);
485                }
486
487                mViewCellsTree->ExportStats("dummy.log");
488        }
489
490        return numSamples;
491}
492
493
494void ViewCellsManager::EvalViewCellPartition(Preprocessor *preprocessor)
495{
496        int samplesPerPass;
497        int numSamples;
498        int castSamples = 0;
499
500        char s[64];
501
502        environment->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
503        environment->GetIntValue("ViewCells.Evaluation.samples", numSamples);
504
505        char statsPrefix[100];
506        environment->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
507
508        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
509        Debug << "view cell evaluation samples: " << numSamples << endl;
510        Debug << "view cell stats prefix: " << statsPrefix << endl;
511
512        //VssRayContainer outRays;
513        // should directional sampling be used?
514        bool dirSamples = (mEvaluationSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
515
516        cout << "Evaluating view cell partition" << endl;
517
518        ViewCellContainer leaves;
519        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
520
521        bool startFromZero = true;
522
523        // reset pvs and start over from zero
524        if (startFromZero)
525        {
526                mViewCellsTree->ResetPvs();
527        }
528        else // statistics without addidtional samples
529        {
530                cout << "compute new statistics ... ";
531                sprintf(s, "-%09d-eval.log", castSamples);
532                string fName = string(statsPrefix) + string(s);
533
534                mViewCellsTree->ExportStats(fName);
535                cout << "finished" << endl;
536        }
537       
538
539        while (castSamples < numSamples)
540        {
541                VssRayContainer evaluationSamples;
542
543                const int samplingType = mEvaluationSamplingType;
544                /*      dirSamples ?
545                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
546                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
547                */
548                //-- construction rays => we use uniform samples for this
549                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
550               
551                castSamples += samplesPerPass;
552
553                cout << "casting " << (int)evaluationSamples.size() << " samples " << endl;
554
555                ComputeSampleContributions(evaluationSamples, true, false);
556
557                cout << "compute new statistics ... ";
558
559                ViewCellContainer::const_iterator it, it_end = leaves.end();
560
561                for (it = leaves.begin(); it != it_end; ++ it)
562                {
563                        mViewCellsTree->PropagatePvs(*it);
564                }
565
566                // output stats
567                sprintf(s, "-%09d-eval.log", castSamples);
568                string fileName = string(statsPrefix) + string(s);
569
570                mViewCellsTree->ExportStats(fileName);
571
572                cout << "finished" << endl;
573       
574                disposeRays(evaluationSamples, NULL);
575        }
576
577        // find empty view cells bug
578        if (TEST_EMPTY_VIEW_CELLS)
579        {
580                TestEmptyViewCells(preprocessor->mObjects);
581        }
582}
583
584
585inline float EvalMergeCost(ViewCell *root, ViewCell *candidate)
586{
587        return root->GetPvs().GetPvsHomogenity(candidate->GetPvs());
588}
589
590
591int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
592{
593        int bestViewCellIdx = 0;
594
595        float mergeCost = Limits::Infinity;
596        int i = 0;
597
598        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
599
600        for (it = neighborhood.begin(); it != it_end; ++ it, ++ i)
601        {
602                const float mc = EvalMergeCost(root, *it);
603               
604                if (mc < mergeCost)
605                {
606                        mergeCost = mc;
607                        bestViewCellIdx = i;
608                }
609        }
610
611        return bestViewCellIdx;
612}
613
614
615ViewCell *ViewCellsManager::ConstructLocalMergeTree(ViewCell *currentViewCell,
616                                                                                                        const ViewCellContainer &viewCells)
617{
618        ViewCell *root = currentViewCell;
619        ViewCellContainer neighborhood = viewCells;
620
621        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
622
623        const int n = min(mMaxFilterSize, (int)neighborhood.size());
624        //-- use priority queue to merge leaf pairs
625
626        //cout << "neighborhood: " << neighborhood.size() << endl;
627        //const float maxAvgCost = 350;
628        for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
629        {
630                const int bestViewCellIdx = GetBestViewCellIdx(root, neighborhood);
631               
632                ViewCell *bestViewCell = neighborhood[bestViewCellIdx];
633       
634                // remove from vector
635                swap(neighborhood[bestViewCellIdx], neighborhood.back());
636                neighborhood.pop_back();
637       
638                //              cout << "vc idx: " << bestViewCellIdx << endl;
639                if (!bestViewCell || !root)
640                        cout << "warning!!" << endl;
641               
642                // create new root of the hierarchy
643                root = MergeViewCells(root, bestViewCell);
644        }
645
646        return root;   
647}
648
649
650struct SortableViewCellEntry {
651
652  SortableViewCellEntry() {}
653  SortableViewCellEntry(const float v, ViewCell *cell):mValue(v), mViewCell(cell) {}
654 
655  float mValue;
656  ViewCell *mViewCell;
657
658  friend bool operator<(const SortableViewCellEntry &a, const SortableViewCellEntry &b) {
659        return a.mValue < b.mValue;
660  }
661};
662
663ViewCell *
664ViewCellsManager::ConstructLocalMergeTree2(ViewCell *currentViewCell,
665                                                                                   const ViewCellContainer &viewCells)
666{
667 
668  vector<SortableViewCellEntry> neighborhood(viewCells.size());
669  int i, j;
670  for (i = 0, j = 0; i < viewCells.size(); i++) {
671        if (viewCells[i] != currentViewCell)
672          neighborhood[j++] = SortableViewCellEntry(
673                                                                                                EvalMergeCost(currentViewCell, viewCells[i]),
674                                                                                                viewCells[i]);
675  }
676  neighborhood.resize(j);
677 
678  sort(neighborhood.begin(), neighborhood.end());
679 
680  ViewCell *root = currentViewCell;
681 
682  vector<SortableViewCellEntry>::const_iterator it, it_end = neighborhood.end();
683 
684  const int n = min(mMaxFilterSize, (int)neighborhood.size());
685  //-- use priority queue to merge leaf pairs
686 
687  //cout << "neighborhood: " << neighborhood.size() << endl;
688  for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
689        {
690          ViewCell *bestViewCell = neighborhood[nMergedViewCells].mViewCell;
691          //cout <<nMergedViewCells<<":"<<"homogenity=" <<neighborhood[nMergedViewCells].mValue<<endl;
692          // create new root of the hierarchy
693          root = MergeViewCells(root, bestViewCell);
694          // set negative cost so that this view cell gets deleted
695          root->SetMergeCost(-1.0f);
696        }
697 
698  return root; 
699}
700
701void
702ViewCellsManager::DeleteLocalMergeTree(ViewCell *vc
703                                                                           ) const
704{
705  if (!vc->IsLeaf() && vc->GetMergeCost() < 0.0f) {
706        ViewCellInterior *vci = (ViewCellInterior *) vc;
707        ViewCellContainer::const_iterator it, it_end = vci->mChildren.end();
708       
709        for (it = vci->mChildren.begin(); it != it_end; ++ it)
710          DeleteLocalMergeTree(*it);
711        vci->mChildren.clear();
712        delete vci;
713  }
714}
715
716bool ViewCellsManager::CheckValidity(ViewCell *vc,
717                                                                         int minPvsSize,
718                                                                         int maxPvsSize) const
719{
720
721        if ((vc->GetPvs().GetSize() > maxPvsSize) ||
722                (vc->GetPvs().GetSize() < minPvsSize))
723        {
724                return false;
725        }
726
727        return true;
728}
729
730
731bool ViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
732{
733        return false;
734}
735
736int ViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
737                                                                                          ViewCellContainer &viewCells) const
738{
739        return 0;
740};
741
742AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
743                                                                                                const float width) const
744{
745        Vector3 min = viewPoint - width * 0.5f;
746        Vector3 max = viewPoint + width * 0.5;
747
748        return AxisAlignedBox3(min, max);
749}
750
751
752void ViewCellsManager::GetPrVS(const Vector3 &viewPoint, PrVs &prvs)
753{
754        const AxisAlignedBox3 box = GetFilterBBox(viewPoint, mFilterWidth);
755
756        ViewCell *currentViewCell = GetViewCell(viewPoint);
757
758        ViewCellContainer viewCells;
759        ComputeBoxIntersections(box, viewCells);
760
761        ViewCell *root = ConstructLocalMergeTree2(currentViewCell, viewCells);
762
763        prvs.mViewCell = root;
764        //prvs.mPvs = root->GetPvs();
765}
766
767
768bool ViewCellsManager::ViewCellsTreeConstructed() const
769{
770        return mViewCellsTree->GetRoot();
771}
772
773
774void ViewCellsManager::SetValidity(ViewCell *vc,
775                                                                   int minPvs,
776                                                                   int maxPvs) const
777{
778        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
779}
780
781
782void
783ViewCellsManager::SetValidity(
784                                                          int minPvsSize,
785                                                          int maxPvsSize) const
786{
787  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
788
789  for (it = mViewCells.begin(); it != it_end; ++ it) {
790        SetValidity(*it, minPvsSize, maxPvsSize);
791  }
792}
793
794void
795ViewCellsManager::SetValidityPercentage(
796                                                                                const float minValid,
797                                                                                const float maxValid
798                                                                                )
799{
800  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
801
802  int start = mViewCells.size()*minValid;
803  int end = mViewCells.size()*maxValid;
804
805  for (int i=0; i < mViewCells.size(); i++)
806        mViewCells[i]->SetValid(i >= start && i <= end);
807}
808
809int
810ViewCellsManager::CountValidViewcells() const
811{
812  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
813  int valid = 0;
814  for (it = mViewCells.begin(); it != it_end; ++ it) {
815        if ((*it)->GetValid())
816          valid ++;
817  }
818  return valid;
819}
820
821
822bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
823{
824        X3dParser parser;
825
826        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
827
828        bool success = parser.ParseFile(filename, *this);
829        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
830
831        return success;
832}
833
834
835bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
836{
837        viewPoint = mViewSpaceBox.GetRandomPoint();
838
839        return true;
840}
841
842
843float ViewCellsManager::GetViewSpaceVolume()
844{
845        return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
846}
847
848
849bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
850{
851  if (!ViewCellsConstructed())
852        return mViewSpaceBox.IsInside(viewPoint);
853  else {
854        if (!mViewSpaceBox.IsInside(viewPoint))
855          return false;
856        ViewCell *viewcell = GetViewCell(viewPoint);
857        if (!viewcell || !viewcell->GetValid())
858          return false;
859  }
860  return true;
861}
862
863
864float
865ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
866                                                                                         const bool addRays,
867                                                                                         const bool storeViewCells
868                                                                                         )
869{
870  // view cells not yet constructed
871  if (!ViewCellsConstructed())
872        return 0.0f;
873
874  VssRayContainer::const_iterator it, it_end = rays.end();
875
876  float sum = 0.0f;
877  for (it = rays.begin(); it != it_end; ++ it)
878  {
879          sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
880          //ComputeSampleContributions(*(*it), addRays);
881          //    sum += (*it)->mPvsContribution;
882  }
883
884  return sum;
885}
886
887
888void ViewCellsManager::EvaluateViewCellsStats()
889{
890        mCurrentViewCellsStats.Reset();
891
892        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
893
894        for (it = mViewCells.begin(); it != it_end; ++ it)
895        {
896                mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
897        }
898}
899
900
901void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
902                                                                                                float &expectedRenderCost,
903                                                                                                float &deviation,
904                                                                                                float &variance,
905                                                                                                int &totalPvs,
906                                                                                                float &avgRenderCost)
907{
908        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
909
910
911        //-- compute expected value
912
913        totalRenderCost = 0;
914        totalPvs = 0;
915
916        for (it = mViewCells.begin(); it != it_end; ++ it)
917        {
918                ViewCell *vc = *it;
919                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
920                totalPvs += (int)vc->GetPvs().GetSize();
921        }
922
923        // normalize with view space box
924        totalRenderCost /= mViewSpaceBox.GetVolume();
925        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
926        avgRenderCost = totalPvs / (float)mViewCells.size();
927
928
929        //-- compute standard defiation
930        variance = 0;
931        deviation = 0;
932
933        for (it = mViewCells.begin(); it != it_end; ++ it)
934        {
935                ViewCell *vc = *it;
936
937                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
938                float dev;
939
940                if (1)
941                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
942                else
943                        dev = fabs(expectedRenderCost - renderCost);
944
945                deviation += dev;
946                variance += dev * dev;
947        }
948
949        variance /= (float)mViewCells.size();
950        deviation /= (float)mViewCells.size();
951}
952
953
954
955void ViewCellsManager::AddViewCell(ViewCell *viewCell)
956{
957        mViewCells.push_back(viewCell);
958}
959
960
961float ViewCellsManager::GetArea(ViewCell *viewCell) const
962{
963        return viewCell->GetArea();
964}
965
966
967float ViewCellsManager::GetVolume(ViewCell *viewCell) const
968{
969        return viewCell->GetVolume();
970}
971
972
973void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
974                                                                           ViewCellContainer &viewCells,
975                                                                           const int maxViewCells) const
976{
977        // maximal max viewcells
978        int limit = maxViewCells > 0 ?
979                Min((int)objects.size(), maxViewCells) : (int)objects.size();
980
981        for (int i = 0; i < limit; ++ i)
982        {
983                Intersectable *object = objects[i];
984
985                // extract the mesh instances
986                if (object->Type() == Intersectable::MESH_INSTANCE)
987                {
988                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
989
990                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
991                        viewCells.push_back(viewCell);
992                }
993                //TODO: transformed meshes
994        }
995}
996
997
998ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
999                                                                                        const float height) const
1000{
1001        // one mesh per view cell
1002        Mesh *mesh = new Mesh();
1003
1004        //-- construct prism
1005
1006        // bottom
1007        mesh->mFaces.push_back(new Face(2,1,0));
1008        // top
1009    mesh->mFaces.push_back(new Face(3,4,5));
1010        // sides
1011        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
1012        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
1013        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
1014
1015        //--- extrude new vertices for top of prism
1016        Vector3 triNorm = baseTri.GetNormal();
1017
1018        Triangle3 topTri;
1019
1020        // add base vertices and calculate top vertices
1021        for (int i = 0; i < 3; ++ i)
1022                mesh->mVertices.push_back(baseTri.mVertices[i]);
1023
1024        // add top vertices
1025        for (int i = 0; i < 3; ++ i)
1026                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
1027
1028        mesh->Preprocess();
1029
1030        return GenerateViewCell(mesh);
1031}
1032
1033
1034void ViewCellsManager::FinalizeViewCells(const bool createMesh)
1035{
1036        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1037
1038        // volume and area of the view cells are recomputed and a view cell mesh is created
1039        for (it = mViewCells.begin(); it != it_end; ++ it)
1040        {
1041                Finalize(*it, createMesh);
1042        }
1043
1044        mTotalAreaValid = false;
1045}
1046
1047
1048void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
1049{
1050        // implemented in subclasses
1051}
1052
1053
1054ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
1055{
1056        // generate parent view cell
1057        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
1058
1059        vc->GetPvs() = left->GetPvs();
1060        // merge pvs
1061        vc->GetPvs().Merge(right->GetPvs());
1062
1063        //-- merge ray sets
1064        if (0)
1065        {
1066                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
1067                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
1068
1069                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
1070                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
1071                                   vc->mPiercingRays.begin());
1072        }
1073
1074        // set only links to child (not from child to parent, maybe not wished!!)
1075        vc->mChildren.push_back(left);
1076        vc->mChildren.push_back(right);
1077
1078        return vc;
1079}
1080
1081
1082ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
1083{
1084        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
1085
1086        ViewCellContainer::const_iterator it, it_end = children.end();
1087
1088        for (it = children.begin(); it != it_end; ++ it)
1089        {
1090                // merge pvs
1091                vc->GetPvs().Merge((*it)->GetPvs());
1092                vc->mChildren.push_back(*it);
1093                //vc->SetupChildLink(*it);
1094        }
1095
1096        return vc;
1097}
1098
1099
1100void ViewCellsManager::SetRenderer(Renderer *renderer)
1101{
1102        mRenderer = renderer;
1103}
1104
1105
1106ViewCellsTree *ViewCellsManager::GetViewCellsTree()
1107{
1108        return mViewCellsTree;
1109}
1110
1111
1112void ViewCellsManager::SetVisualizationSamples(const int visSamples)
1113{
1114        mVisualizationSamples = visSamples;
1115}
1116
1117
1118void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
1119{
1120        mConstructionSamples = constructionSamples;
1121}
1122
1123
1124void ViewCellsManager::SetInitialSamples(const int initialSamples)
1125{
1126        mInitialSamples = initialSamples;
1127}
1128
1129
1130void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
1131{
1132        mPostProcessSamples = postProcessSamples;
1133}
1134
1135
1136int ViewCellsManager::GetVisualizationSamples() const
1137{
1138        return mVisualizationSamples;
1139}
1140
1141
1142int ViewCellsManager::GetConstructionSamples() const
1143{
1144        return mConstructionSamples;
1145}
1146
1147
1148int ViewCellsManager::GetPostProcessSamples() const
1149{
1150        return mPostProcessSamples;
1151}
1152
1153
1154void ViewCellsManager::UpdatePvs()
1155{
1156        if (mViewCellPvsIsUpdated || !ViewCellsTreeConstructed())
1157                return;
1158
1159        mViewCellPvsIsUpdated = true;
1160
1161        ViewCellContainer leaves;
1162        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
1163
1164        ViewCellContainer::const_iterator it, it_end = leaves.end();
1165
1166        for (it = leaves.begin(); it != it_end; ++ it)
1167        {
1168                mViewCellsTree->PropagatePvs(*it);
1169        }
1170}
1171
1172
1173void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
1174{
1175        // update pvs of view cells tree if necessary
1176        UpdatePvs();
1177
1178        ViewCellContainer::const_iterator it = mViewCells.begin();
1179
1180        stat.viewcells = 0;
1181        stat.minPvs = 100000000;
1182        stat.maxPvs = 0;
1183        stat.avgPvs = 0.0f;
1184
1185        for (; it != mViewCells.end(); ++ it)
1186        {
1187                ViewCell *viewcell = *it;
1188               
1189                const int pvsSize = mViewCellsTree->GetPvsSize(viewcell);
1190               
1191                if (pvsSize < stat.minPvs)
1192                        stat.minPvs = pvsSize;
1193                if (pvsSize > stat.maxPvs)
1194                        stat.maxPvs = pvsSize;
1195                stat.avgPvs += pvsSize;
1196               
1197                ++ stat.viewcells;
1198        }
1199
1200        if (stat.viewcells)
1201                stat.avgPvs/=stat.viewcells;
1202}
1203
1204
1205void ViewCellsManager::PrintPvsStatistics(ostream &s)
1206{
1207  s<<"############# Viewcell PVS STAT ##################\n";
1208  PvsStatistics pvsStat;
1209  GetPvsStatistics(pvsStat);
1210  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
1211  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
1212  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
1213}
1214
1215
1216int ViewCellsManager::CastBeam(Beam &beam)
1217{
1218        return 0;
1219}
1220
1221
1222ViewCellContainer &ViewCellsManager::GetViewCells()
1223{
1224        return mViewCells;
1225}
1226
1227
1228void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
1229{
1230        mViewSpaceBox = box;
1231
1232        CreateClipPlane();
1233       
1234        mTotalAreaValid = false;
1235}
1236
1237
1238void ViewCellsManager::CreateClipPlane()
1239{
1240        int axis = 0;
1241        float pos;
1242
1243        environment->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
1244
1245        Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
1246
1247        if (mUseClipPlaneForViz)
1248        environment->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
1249
1250        Vector3 normal(0,0,0);
1251        normal[axis] = 1;
1252
1253        mClipPlane = Plane3(normal, point);
1254}
1255
1256
1257AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
1258{
1259        return mViewSpaceBox;
1260}
1261
1262
1263void ViewCellsManager::ResetViewCells()
1264{
1265        // recollect view cells
1266        mViewCells.clear();
1267        CollectViewCells();
1268       
1269       
1270        // stats are computed once more
1271        mCurrentViewCellsStats.Reset();
1272        EvaluateViewCellsStats();
1273
1274        // has to be recomputed
1275        mTotalAreaValid = false;
1276}
1277
1278
1279int ViewCellsManager::GetMaxPvsSize() const
1280{
1281        return mMaxPvsSize;
1282}
1283
1284
1285void
1286ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
1287{
1288  if (!ViewCellsConstructed())
1289        return;
1290
1291  VssRayContainer::const_iterator it, it_end = rays.end();
1292
1293  for (it = rays.begin(); it != it_end; ++ it) {
1294        AddSampleContributions(*(*it));
1295  }
1296}
1297
1298
1299int ViewCellsManager::GetMinPvsSize() const
1300{
1301        return mMinPvsSize;
1302}
1303
1304
1305
1306float ViewCellsManager::GetMaxPvsRatio() const
1307{
1308        return mMaxPvsRatio;
1309}
1310
1311
1312void
1313ViewCellsManager::AddSampleContributions(VssRay &ray)
1314{
1315  // assumes viewcells have been stored...
1316  ViewCellContainer *viewcells = &ray.mViewCells;
1317  ViewCellContainer::const_iterator it;
1318  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
1319        ViewCell *viewcell = *it;
1320        if (viewcell->GetValid()) {
1321          // if ray not outside of view space
1322          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1323        }
1324  }
1325}
1326
1327
1328float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
1329                                                                                                   const bool addRays,
1330                                                                                                   const bool storeViewCells)
1331{
1332        ViewCellContainer viewcells;
1333
1334        ray.mPvsContribution = 0;
1335        ray.mRelativePvsContribution = 0.0f;
1336
1337        static Ray hray;
1338        hray.Init(ray);
1339        //hray.mFlags |= Ray::CULL_BACKFACES;
1340        //Ray hray(ray);
1341
1342        float tmin = 0, tmax = 1.0;
1343
1344        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
1345                return 0;
1346
1347        Vector3 origin = hray.Extrap(tmin);
1348        Vector3 termination = hray.Extrap(tmax);
1349
1350        CastLineSegment(origin, termination, viewcells);
1351
1352        // copy viewcells memory efficiently
1353        //const bool storeViewcells = !addRays;
1354
1355        if (storeViewCells)
1356        {
1357                ray.mViewCells.reserve(viewcells.size());
1358                ray.mViewCells = viewcells;
1359        }
1360
1361        ViewCellContainer::const_iterator it = viewcells.begin();
1362
1363        for (; it != viewcells.end(); ++ it)
1364        {
1365                ViewCell *viewcell = *it;
1366
1367                if (viewcell->GetValid())
1368                {
1369                        // HACK
1370#if TEST_EMPTY_VIEW_CELLS
1371                                for (int i = 0; i < mEmptyViewCells.size(); ++i)
1372                                {
1373                                        if (viewcell == mEmptyViewCells[i])
1374                                        {
1375                                                viewcell->mPiercingRays.push_back(new Ray(ray));
1376                                                Debug << "empty view cell ray found: " << ray.mOriginObject << ", " << ray.mTerminationObject << endl;
1377                                        }
1378                                }
1379#endif
1380                        // if ray not outside of view space
1381                        float contribution;
1382                        if (ray.mTerminationObject &&
1383                                viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
1384                                                                                                                 ray.mPdf,
1385                                                                                                                 contribution))
1386                        {
1387                                ++ ray.mPvsContribution;
1388                                ray.mRelativePvsContribution += contribution;
1389                        }
1390
1391                        //for directional sampling it is important to count only contributions
1392                        // made in one direction!!!
1393                        // the other contributions of this sample will be counted for the oposite ray!
1394#if 0
1395                        if (ray.mOriginObject &&
1396                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
1397                                                                                                                 ray.mPdf,
1398                                                                                                                 contribution))
1399                        {
1400                                ++ ray.mPvsContribution;
1401                                ray.mRelativePvsContribution += contribution;
1402                        }
1403#endif
1404                }
1405        }
1406
1407       
1408        if (addRays)
1409        {
1410                for (it = viewcells.begin(); it != viewcells.end(); ++ it)
1411                {
1412                        ViewCell *viewcell = *it;
1413           
1414                        if (viewcell->GetValid())
1415                        {
1416                                // if ray not outside of view space
1417                                 if (ray.mTerminationObject)
1418                                         viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1419
1420#if 0
1421                                 if (ray.mOriginObject)
1422                                         viewcell->GetPvs().AddSample(ray.mOriginObject, ray.mPdf);
1423#endif
1424                        }
1425                }
1426        }
1427
1428        return ray.mRelativePvsContribution;
1429}
1430
1431
1432void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
1433                                                                  const int maxSize,
1434                                                                  VssRayContainer &usedRays,
1435                                                                  VssRayContainer *savedRays) const
1436{
1437        const int limit = min(maxSize, (int)sourceRays.size());
1438        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
1439
1440        VssRayContainer::const_iterator it, it_end = sourceRays.end();
1441        for (it = sourceRays.begin(); it != it_end; ++ it)
1442        {
1443                if (Random(1.0f) < prop)
1444                        usedRays.push_back(*it);
1445                else if (savedRays)
1446                        savedRays->push_back(*it);
1447        }
1448}
1449
1450
1451float ViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1452{
1453        return mViewCellsTree->GetPvsSize(viewCell) * objRendercost;
1454}
1455
1456
1457float ViewCellsManager::GetAccVcArea()
1458{
1459        // if already computed
1460        if (mTotalAreaValid)
1461                return mTotalArea;
1462
1463        mTotalArea = 0;
1464        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1465
1466        for (it = mViewCells.begin(); it != it_end; ++ it)
1467        {
1468                //Debug << "area: " << GetArea(*it);
1469        mTotalArea += GetArea(*it);
1470        }
1471
1472        mTotalAreaValid = true;
1473
1474        return mTotalArea;
1475}
1476
1477
1478void ViewCellsManager::PrintStatistics(ostream &s) const
1479{
1480        s << mCurrentViewCellsStats << endl;
1481}
1482
1483
1484void ViewCellsManager::CreateUniqueViewCellIds()
1485{
1486        if (ViewCellsTreeConstructed())
1487                mViewCellsTree->CreateUniqueViewCellsIds();
1488        else
1489                for (int i = 0; i < (int)mViewCells.size(); ++ i)
1490                        mViewCells[i]->SetId(i);
1491}
1492
1493
1494void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
1495{
1496        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1497
1498        for (it = mViewCells.begin(); it != it_end; ++ it)
1499        {
1500                if (!mOnlyValidViewCells || (*it)->GetValid())
1501                {
1502                        ExportColor(exporter, *it);             
1503                        ExportViewCellGeometry(exporter, *it,
1504                                mUseClipPlaneForViz ? &mClipPlane : NULL);
1505                }
1506        }
1507}
1508
1509
1510void ViewCellsManager::CreateViewCellMeshes()
1511{
1512        // convert to meshes
1513        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1514
1515        for (it = mViewCells.begin(); it != it_end; ++ it)
1516        {
1517                if (!(*it)->GetMesh())
1518                        CreateMesh(*it);
1519        }
1520}
1521
1522
1523bool ViewCellsManager::ExportViewCells(const string filename)
1524{
1525        return false;
1526}
1527
1528
1529void ViewCellsManager::CollectViewCells(const int n)
1530{
1531        mNumActiveViewCells = n;
1532        mViewCells.clear();
1533        CollectViewCells();
1534}
1535
1536
1537void ViewCellsManager::SetViewCellsActive()
1538{
1539        ++ ViewCell::sLastUpdated;
1540        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1541        for (it = mViewCells.begin(); it != it_end; ++ it)
1542        {
1543                (*it)->SetActive();
1544        }
1545}
1546
1547/**********************************************************************/
1548/*                   BspViewCellsManager implementation               */
1549/**********************************************************************/
1550
1551
1552BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
1553ViewCellsManager(), mBspTree(bspTree)
1554{
1555        environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
1556        mBspTree->SetViewCellsManager(this);
1557        mBspTree->mViewCellsTree = mViewCellsTree;
1558}
1559
1560
1561bool BspViewCellsManager::ViewCellsConstructed() const
1562{
1563        return mBspTree->GetRoot() != NULL;
1564}
1565
1566
1567ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1568{
1569        return new BspViewCell(mesh);
1570}
1571
1572
1573int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1574                                                                                          const VssRayContainer &rays)
1575{
1576        // if view cells were already constructed
1577        if (ViewCellsConstructed())
1578                return 0;
1579
1580        int sampleContributions = 0;
1581
1582        // construct view cells using the collected samples
1583        RayContainer constructionRays;
1584        VssRayContainer savedRays;
1585
1586        const int limit = min(mInitialSamples, (int)rays.size());
1587
1588        VssRayContainer::const_iterator it, it_end = rays.end();
1589
1590        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
1591
1592        for (it = rays.begin(); it != it_end; ++ it)
1593        {
1594                if (Random(1.0f) < prop)
1595                        constructionRays.push_back(new Ray(*(*it)));
1596                else
1597                        savedRays.push_back(*it);
1598        }
1599
1600    if (mViewCells.empty())
1601        {
1602                // no view cells loaded
1603                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
1604                // collect final view cells
1605                mBspTree->CollectViewCells(mViewCells);
1606        }
1607        else
1608        {
1609                mBspTree->Construct(mViewCells);
1610        }
1611
1612        // destroy rays created only for construction
1613        CLEAR_CONTAINER(constructionRays);
1614
1615        Debug << mBspTree->GetStatistics() << endl;
1616
1617        //EvaluateViewCellsStats();
1618        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
1619
1620        // recast rest of the rays
1621        if (SAMPLE_AFTER_SUBDIVISION)
1622                ComputeSampleContributions(savedRays, true, false);
1623
1624        // real meshes are contructed at this stage
1625        if (0)
1626        {
1627                cout << "finalizing view cells ... ";
1628                FinalizeViewCells(true);
1629                cout << "finished" << endl;     
1630        }
1631
1632        return sampleContributions;
1633}
1634
1635
1636void BspViewCellsManager::CollectViewCells()
1637{
1638        // view cells tree constructed
1639        if (!ViewCellsTreeConstructed())
1640        {               
1641                mBspTree->CollectViewCells(mViewCells);
1642        }
1643        else
1644        {
1645                // we can use the view cells tree hierarchy to get the right set
1646                mViewCellsTree->CollectBestViewCellSet(mViewCells,
1647                                                                                           mNumActiveViewCells);
1648        }
1649}
1650
1651
1652float BspViewCellsManager::GetProbability(ViewCell *viewCell)
1653{
1654        // compute view cell area as subsititute for probability
1655        if (1)
1656                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1657        else
1658                return GetArea(viewCell) / GetAccVcArea();
1659}
1660
1661
1662
1663int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1664                                                                                 const Vector3 &termination,
1665                                                                                 ViewCellContainer &viewcells)
1666{
1667        return mBspTree->CastLineSegment(origin, termination, viewcells);
1668}
1669
1670
1671int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
1672                                                                         const VssRayContainer &rays)
1673{
1674        if (!ViewCellsConstructed())
1675        {
1676                Debug << "view cells not constructed" << endl;
1677                return 0;
1678        }
1679       
1680        // view cells already finished before post processing step (i.e. because they were loaded)
1681        if (mViewCellsFinished)
1682        {
1683                FinalizeViewCells(true);
1684                EvaluateViewCellsStats();
1685
1686                return 0;
1687        }
1688
1689        //-- post processing of bsp view cells
1690
1691    int vcSize = 0;
1692        int pvsSize = 0;
1693
1694        //-- merge view cells
1695        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1696        long startTime = GetTime();
1697       
1698        VssRayContainer postProcessRays;
1699        GetRaySets(rays, mPostProcessSamples, postProcessRays);
1700
1701        if (mMergeViewCells)
1702        {
1703                cout << "constructing visibility based merge tree" << endl;
1704                mViewCellsTree->ConstructMergeTree(rays, objects);
1705        }
1706        else
1707        {
1708                cout << "constructing spatial merge tree" << endl;
1709                // create spatial merge hierarchy
1710                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mBspTree->GetRoot()));
1711        }
1712
1713        // export statistics after merge
1714        if (1)
1715        {
1716                char mstats[100];
1717                environment->GetStringValue("ViewCells.mergeStats", mstats);
1718                mViewCellsTree->ExportStats(mstats);
1719        }
1720
1721        //-- stats and visualizations
1722        cout << "finished" << endl;
1723        cout << "merged view cells in "
1724                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1725
1726        Debug << "Postprocessing: Merged view cells in "
1727                << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1728       
1729
1730        //-- visualization and statistics
1731    // reset view cells and stats
1732        ResetViewCells();
1733        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
1734
1735
1736        int savedColorCode  = mColorCode;
1737       
1738        //BspLeaf::NewMail();
1739        if (1) // export merged view cells
1740        {
1741                mColorCode = 0;
1742               
1743                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1744               
1745
1746                cout << "exporting view cells after merge ... ";
1747
1748                if (exporter)
1749                {
1750                        if (mExportGeometry)
1751                                exporter->ExportGeometry(objects);
1752
1753                        //exporter->SetWireframe();
1754                        exporter->SetFilled();
1755                        ExportViewCellsForViz(exporter);
1756
1757
1758                        delete exporter;
1759                }
1760                cout << "finished" << endl;
1761        }
1762
1763        if (1) // export merged view cells
1764        {
1765                mColorCode = 1;
1766
1767                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
1768       
1769                cout << "exporting view cells after merge (pvs size) ... ";     
1770
1771                if (exporter)
1772                {
1773                        //exporter->SetWireframe();
1774                       
1775                        if (mExportGeometry)
1776                                exporter->ExportGeometry(objects);
1777
1778                        //exporter->SetWireframe();
1779                        exporter->SetFilled();
1780                        ExportViewCellsForViz(exporter);
1781
1782                        delete exporter;
1783                }
1784                cout << "finished" << endl;
1785        }
1786
1787       
1788        // only for testing
1789        TestSubdivision();
1790
1791        mColorCode = savedColorCode;
1792
1793        // compute final meshes and volume / area
1794        if (1) FinalizeViewCells(true);
1795
1796        // write view cells to disc
1797        if (mExportViewCells)
1798        {
1799                char buff[100];
1800                environment->GetStringValue("ViewCells.filename", buff);
1801                string vcFilename(buff);
1802
1803                ExportViewCells(buff);
1804        }
1805
1806        return 0;
1807}
1808
1809
1810BspViewCellsManager::~BspViewCellsManager()
1811{
1812}
1813
1814
1815int BspViewCellsManager::GetType() const
1816{
1817        return BSP;
1818}
1819
1820
1821void BspViewCellsManager::Visualize(const ObjectContainer &objects,
1822                                                                        const VssRayContainer &sampleRays)
1823{
1824        if (!ViewCellsConstructed())
1825                return;
1826       
1827        int savedColorCode = mColorCode;
1828
1829       
1830       
1831        if (1) // export final view cells
1832        {
1833                mColorCode = 1;
1834
1835                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
1836       
1837                cout << "exporting view cells after merge (pvs size) ... ";     
1838
1839                if (exporter)
1840                {
1841                        //exporter->SetWireframe();
1842                       
1843                        if (mExportGeometry)
1844                                exporter->ExportGeometry(objects);
1845
1846                        //exporter->SetWireframe();
1847                        exporter->SetFilled();
1848                        ExportViewCellsForViz(exporter);
1849
1850                        delete exporter;
1851                }
1852                cout << "finished" << endl;
1853        }
1854
1855        mColorCode = savedColorCode;
1856
1857        //-- visualization of the BSP splits
1858        bool exportSplits = false;
1859        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1860
1861        if (exportSplits)
1862        {
1863                cout << "exporting splits ... ";
1864                ExportSplits(objects);
1865                cout << "finished" << endl;
1866        }
1867
1868        // export single view cells
1869        ExportBspPvs(objects);
1870}
1871
1872
1873inline bool vc_gt(ViewCell *a, ViewCell *b)
1874{
1875        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1876}
1877
1878
1879void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
1880{
1881        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1882
1883        if (exporter)
1884        {
1885                //exporter->SetFilled();
1886
1887                if (mExportGeometry)
1888                        exporter->ExportGeometry(objects);
1889
1890                Material m;
1891                m.mDiffuseColor = RgbColor(1, 0, 0);
1892                exporter->SetForcedMaterial(m);
1893                exporter->SetWireframe();
1894
1895                exporter->ExportBspSplits(*mBspTree, true);
1896
1897                //NOTE: take forced material, else big scenes cannot be viewed
1898                m.mDiffuseColor = RgbColor(0, 1, 0);
1899                exporter->SetForcedMaterial(m);
1900                //exporter->ResetForcedMaterial();
1901
1902                delete exporter;
1903        }
1904}
1905
1906
1907void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
1908{
1909        const int leafOut = 10;
1910
1911        ViewCell::NewMail();
1912
1913        //-- some rays for output
1914        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
1915
1916        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1917        Debug << "\nOutput view cells: " << endl;
1918
1919        // sort view cells to get largest view cells
1920        if (0)
1921                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1922
1923        int limit = min(leafOut, (int)mViewCells.size());
1924
1925        for (int i = 0; i < limit; ++ i)
1926        {
1927                cout << "creating output for view cell " << i << " ... ";
1928                VssRayContainer vcRays;
1929                Intersectable::NewMail();
1930                ViewCell *vc;
1931
1932                if (0)
1933                        vc = mViewCells[i];
1934                else
1935                        vc = mViewCells[Random((int)mViewCells.size())];
1936
1937                cout << "creating output for view cell " << i << " ... ";
1938
1939                if(0)
1940                {
1941                        // check whether we can add the current ray to the output rays
1942                        for (int k = 0; k < raysOut; ++ k)
1943                        {
1944                                BspRay *ray = mBspRays[k];
1945                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1946                                {
1947                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1948                                        if (vc == leaf->GetViewCell())
1949                                                vcRays.push_back(ray->vssRay);
1950                                }
1951                        }
1952                }
1953
1954                //bspLeaves[j]->Mail();
1955                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1956
1957                Exporter *exporter = Exporter::GetExporter(s);
1958
1959                exporter->SetWireframe();
1960
1961                Material m;//= RandomMaterial();
1962                m.mDiffuseColor = RgbColor(0, 1, 0);
1963                exporter->SetForcedMaterial(m);
1964
1965                ExportViewCellGeometry(exporter, vc);
1966               
1967                // export rays piercing this view cell
1968                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1969
1970                m.mDiffuseColor = RgbColor(1, 0, 0);
1971                exporter->SetForcedMaterial(m);
1972
1973                ObjectPvsMap::const_iterator it,
1974                        it_end = vc->GetPvs().mEntries.end();
1975
1976                exporter->SetFilled();
1977
1978                // output PVS of view cell
1979                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1980                {
1981                        Intersectable *intersect = (*it).first;
1982
1983                        if (!intersect->Mailed())
1984                        {
1985                                Material m = RandomMaterial();
1986                                exporter->SetForcedMaterial(m);
1987
1988                                exporter->ExportIntersectable(intersect);
1989                                intersect->Mail();
1990                        }
1991                }
1992
1993                DEL_PTR(exporter);
1994                cout << "finished" << endl;
1995        }
1996
1997        Debug << endl;
1998}
1999
2000
2001void BspViewCellsManager::ExportColor(Exporter *exporter,
2002                                                                          ViewCell *vc) const
2003{
2004        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
2005
2006        float importance = 0;
2007        static Material m;
2008
2009        switch (mColorCode)
2010        {
2011        case 0: // Random
2012                {
2013                        if (vcValid)
2014                        {
2015                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
2016                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
2017                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
2018                        }
2019                        else
2020                        {
2021                                m.mDiffuseColor.r = 0.0f;
2022                                m.mDiffuseColor.g = 1.0f;
2023                                m.mDiffuseColor.b = 0.0f;
2024                        }
2025
2026                        exporter->SetForcedMaterial(m);
2027                        return;
2028                }
2029               
2030        case 1: // pvs
2031                {
2032                        importance = (float)vc->GetPvs().GetSize() /
2033                                (float)mCurrentViewCellsStats.maxPvs;
2034
2035                }
2036                break;
2037        case 2: // merges
2038                {
2039            int lSize = mViewCellsTree->GetSize(vc);
2040                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
2041                }
2042                //break;
2043        case 3: // merge tree differene
2044                {
2045                        // TODO
2046                        //importance = (float)GetMaxTreeDiff(vc) /
2047                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2048
2049                }
2050                break;
2051        default:
2052                break;
2053        }
2054
2055        // special color code for invalid view cells
2056        m.mDiffuseColor.r = importance;
2057        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2058        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
2059
2060        //Debug << "importance: " << importance << endl;
2061        exporter->SetForcedMaterial(m);
2062}
2063
2064
2065void BspViewCellsManager::TestSubdivision()
2066{
2067        ViewCellContainer leaves;
2068        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
2069
2070        ViewCellContainer::const_iterator it, it_end = leaves.end();
2071
2072        const float vol = mViewSpaceBox.GetVolume();
2073        float subdivVol = 0;
2074        float newVol = 0;
2075
2076        for (it = leaves.begin(); it != it_end; ++ it)
2077        {
2078                BspNodeGeometry geom;
2079                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2080                mBspTree->ConstructGeometry(leaf, geom);
2081
2082                const float lVol = geom.GetVolume();
2083               
2084                newVol += lVol;
2085                subdivVol += (*it)->GetVolume();
2086
2087                float thres = 0.9f;
2088                if ((lVol < ((*it)->GetVolume() * thres)) ||
2089                        (lVol * thres > ((*it)->GetVolume())))
2090                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
2091        }
2092       
2093        Debug << "exact volume: " << vol << endl;
2094        Debug << "subdivision volume: " << subdivVol << endl;
2095        Debug << "new volume: " << newVol << endl;
2096}
2097
2098
2099void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2100                                                                                                 ViewCell *vc,
2101                                                                                                 const Plane3 *clipPlane) const
2102{
2103        if (vc->GetMesh())
2104        {
2105                exporter->ExportMesh(vc->GetMesh());
2106                return;
2107        }
2108
2109        BspNodeGeometry geom;
2110        mBspTree->ConstructGeometry(vc, geom);
2111
2112        if (clipPlane)
2113        {
2114                const int cf = Polygon3::ClassifyPlane(geom.GetPolys(), *clipPlane, 0.0001f);
2115
2116                if (cf == Polygon3::BACK_SIDE)
2117                {
2118                        exporter->ExportPolygons(geom.GetPolys());
2119                }
2120                else if (cf == Polygon3::SPLIT)
2121                {
2122                        BspNodeGeometry front;
2123                        BspNodeGeometry back;
2124
2125                        geom.SplitGeometry(front,
2126                                                           back,
2127                                                           *clipPlane,
2128                                                           mViewSpaceBox,
2129                                                           0.0001f);
2130
2131                        if (back.Valid())
2132                                exporter->ExportPolygons(back.GetPolys());
2133                }
2134        }
2135        else
2136        {
2137                exporter->ExportPolygons(geom.GetPolys());
2138        }
2139}
2140
2141
2142void BspViewCellsManager::CreateMesh(ViewCell *vc)
2143{
2144        if (vc->GetMesh())
2145                delete vc->GetMesh();
2146
2147        BspNodeGeometry geom;
2148       
2149        mBspTree->ConstructGeometry(vc, geom);
2150
2151        Mesh *mesh = new Mesh();
2152        geom.AddToMesh(*mesh);
2153        vc->SetMesh(mesh);
2154        mMeshContainer.push_back(mesh);
2155}
2156
2157
2158void BspViewCellsManager::Finalize(ViewCell *viewCell,
2159                                                                   const bool createMesh)
2160{
2161        float area = 0;
2162        float volume = 0;
2163
2164        ViewCellContainer leaves;
2165        mViewCellsTree->CollectLeaves(viewCell, leaves);
2166
2167        ViewCellContainer::const_iterator it, it_end = leaves.end();
2168
2169    for (it = leaves.begin(); it != it_end; ++ it)
2170        {
2171                BspNodeGeometry geom;
2172                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2173                mBspTree->ConstructGeometry(leaf, geom);
2174
2175                const float lVol = geom.GetVolume();
2176                const float lArea = geom.GetArea();
2177
2178                //(*it)->SetVolume(vol);
2179                //(*it)->SetArea(area);
2180
2181                area += lArea;
2182                volume += lVol;
2183
2184        CreateMesh(*it);
2185        }
2186
2187        viewCell->SetVolume(volume);
2188        viewCell->SetArea(area);
2189}
2190
2191
2192ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
2193{
2194        if (!mBspTree)
2195                return NULL;
2196
2197        if (!mViewSpaceBox.IsInside(point))
2198                return NULL;
2199       
2200        return mBspTree->GetViewCell(point);
2201}
2202
2203
2204void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2205                                                                                                 vector<MergeCandidate> &candidates)
2206{
2207        cout << "collecting merge candidates ... " << endl;
2208
2209        if (mUseRaysForMerge)
2210        {
2211                mBspTree->CollectMergeCandidates(rays, candidates);
2212        }
2213        else
2214        {
2215                vector<BspLeaf *> leaves;
2216                mBspTree->CollectLeaves(leaves);
2217                mBspTree->CollectMergeCandidates(leaves, candidates);
2218        }
2219
2220        cout << "fininshed collecting candidates" << endl;
2221}
2222
2223
2224
2225bool BspViewCellsManager::ExportViewCells(const string filename)
2226{
2227        cout << "exporting view cells to xml ... ";
2228        std::ofstream stream;
2229
2230        // for output we need unique ids for each view cell
2231        CreateUniqueViewCellIds();
2232
2233
2234        stream.open(filename.c_str());
2235        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2236        stream << "<Visibility_Solution>" << endl;
2237
2238        //-- the view space bounding box
2239        stream << "<ViewSpaceBox"
2240                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
2241                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
2242
2243        //-- the type of the view cells hierarchy
2244        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
2245        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
2246        //-- load the view cells itself, i.e., the ids and the pvs
2247        stream << "<ViewCells>" << endl;
2248
2249#if 0
2250       
2251        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2252               
2253        for (it = mViewCells.begin(); it != it_end; ++ it)
2254                ExportViewCell(*it, stream);
2255#else
2256        mViewCellsTree->Export(stream);
2257#endif
2258
2259        stream << "</ViewCells>" << endl;
2260
2261        //-- load the hierarchy
2262        stream << "<Hierarchy>" << endl;
2263        mBspTree->Export(stream);
2264        stream << endl << "</Hierarchy>" << endl;
2265
2266        stream << "</Visibility_Solution>" << endl;
2267        stream.close();
2268
2269        cout << "finished" << endl;
2270
2271        return true;
2272}
2273
2274
2275void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
2276{
2277        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2278        for (it = mViewCells.begin(); it != it_end; ++ it)
2279        {
2280                ViewCell *vc = *it;
2281                ViewCellContainer leaves;
2282                mViewCellsTree->CollectLeaves(vc, leaves);
2283               
2284                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2285
2286                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2287                {
2288                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
2289                        bspVc->mLeaf->SetViewCell(vc);
2290                }
2291        }
2292}
2293
2294
2295ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
2296{
2297        if (root->IsLeaf())
2298        {
2299                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
2300
2301                viewCell->SetMergeCost(0.0f);
2302
2303                return viewCell;
2304        }
2305       
2306        BspInterior *interior = dynamic_cast<BspInterior *>(root);
2307        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2308               
2309        float mergeCost = 1.0f / (float)root->mTimeStamp;
2310        //Debug << "timestamp: " << root->mTimeStamp;
2311        //Debug << "merge cost: " << mergeCost << endl;
2312
2313        viewCellInterior->SetMergeCost(mergeCost);
2314
2315        float volume = 0;
2316       
2317        BspNode *front = interior->GetFront();
2318        BspNode *back = interior->GetBack();
2319
2320        // recursivly compute child hierarchies
2321        ViewCell *backVc = ConstructSpatialMergeTree(back);
2322        ViewCell *frontVc = ConstructSpatialMergeTree(front);
2323
2324        viewCellInterior->SetupChildLink(frontVc);
2325        viewCellInterior->SetupChildLink(backVc);
2326
2327
2328        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2329        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
2330
2331        volume += backVc->GetVolume();
2332        volume += frontVc->GetVolume();
2333
2334        viewCellInterior->SetVolume(volume);
2335
2336        return viewCellInterior;
2337}
2338
2339
2340/************************************************************************/
2341/*                   KdViewCellsManager implementation                  */
2342/************************************************************************/
2343
2344
2345
2346KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
2347ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
2348{
2349}
2350
2351
2352float KdViewCellsManager::GetProbability(ViewCell *viewCell)
2353{
2354        // compute view cell area / volume as subsititute for probability
2355        if (0)
2356                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2357        else
2358                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
2359}
2360
2361
2362
2363
2364void KdViewCellsManager::CollectViewCells()
2365{
2366        //mKdTree->CollectViewCells(mViewCells); TODO
2367}
2368
2369
2370int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2371                                                                  const VssRayContainer &rays)
2372{
2373        // if view cells already constructed
2374        if (ViewCellsConstructed())
2375                return 0;
2376
2377        mKdTree->Construct();
2378
2379        mTotalAreaValid = false;
2380        // create the view cells
2381        mKdTree->CreateAndCollectViewCells(mViewCells);
2382
2383        // cast rays
2384        ComputeSampleContributions(rays, true, false);
2385
2386        EvaluateViewCellsStats();
2387        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
2388
2389        return 0;
2390}
2391
2392
2393bool KdViewCellsManager::ViewCellsConstructed() const
2394{
2395        return mKdTree->GetRoot() != NULL;
2396}
2397
2398int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
2399                                                                        const VssRayContainer &rays)
2400{
2401        return 0;
2402}
2403
2404void KdViewCellsManager::Visualize(const ObjectContainer &objects,
2405                                                                   const VssRayContainer &sampleRays)
2406{
2407        if (!ViewCellsConstructed())
2408                return;
2409
2410        // using view cells instead of the kd PVS of objects
2411        const bool useViewCells = true;
2412        bool exportRays = false;
2413
2414        int limit = min(mVisualizationSamples, (int)sampleRays.size());
2415        const int pvsOut = min((int)objects.size(), 10);
2416        VssRayContainer *rays = new VssRayContainer[pvsOut];
2417
2418        if (useViewCells)
2419        {
2420                const int leafOut = 10;
2421
2422                ViewCell::NewMail();
2423
2424                //-- some rays for output
2425                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
2426                Debug << "visualization using " << raysOut << " samples" << endl;
2427
2428                //-- some random view cells and rays for output
2429                vector<KdLeaf *> kdLeaves;
2430
2431                for (int i = 0; i < leafOut; ++ i)
2432                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
2433
2434                for (int i = 0; i < kdLeaves.size(); ++ i)
2435                {
2436                        KdLeaf *leaf = kdLeaves[i];
2437                        RayContainer vcRays;
2438
2439                        cout << "creating output for view cell " << i << " ... ";
2440#if 0
2441                        // check whether we can add the current ray to the output rays
2442                        for (int k = 0; k < raysOut; ++ k)
2443                        {
2444                                Ray *ray = sampleRays[k];
2445
2446                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
2447                                {
2448                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
2449
2450                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
2451                                        {
2452                                                vcRays.push_back(ray);
2453                                        }
2454                                }
2455                        }
2456#endif
2457                        Intersectable::NewMail();
2458
2459                        ViewCell *vc = leaf->mViewCell;
2460
2461                        //bspLeaves[j]->Mail();
2462                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
2463
2464                        Exporter *exporter = Exporter::GetExporter(s);
2465                        exporter->SetFilled();
2466
2467                        exporter->SetWireframe();
2468                        //exporter->SetFilled();
2469
2470                        Material m;//= RandomMaterial();
2471                        m.mDiffuseColor = RgbColor(1, 1, 0);
2472                        exporter->SetForcedMaterial(m);
2473
2474                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
2475                        exporter->ExportBox(box);
2476
2477                        // export rays piercing this view cell
2478                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
2479
2480                        m.mDiffuseColor = RgbColor(1, 0, 0);
2481                        exporter->SetForcedMaterial(m);
2482
2483                        // exporter->SetWireframe();
2484                        exporter->SetFilled();
2485
2486                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
2487                        // output PVS of view cell
2488                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
2489                        {
2490                                Intersectable *intersect = (*it).first;
2491                                if (!intersect->Mailed())
2492                                {
2493                                        exporter->ExportIntersectable(intersect);
2494                                        intersect->Mail();
2495                                }
2496                        }
2497
2498                        DEL_PTR(exporter);
2499                        cout << "finished" << endl;
2500                }
2501
2502                DEL_PTR(rays);
2503        }
2504        else // using kd PVS of objects
2505        {
2506                for (int i = 0; i < limit; ++ i)
2507                {
2508                        VssRay *ray = sampleRays[i];
2509
2510                        // check whether we can add this to the rays
2511                        for (int j = 0; j < pvsOut; j++)
2512                        {
2513                                if (objects[j] == ray->mTerminationObject)
2514                                {
2515                                        rays[j].push_back(ray);
2516                                }
2517                        }
2518                }
2519
2520                if (exportRays)
2521                {
2522                        Exporter *exporter = NULL;
2523                        exporter = Exporter::GetExporter("sample-rays.x3d");
2524                        exporter->SetWireframe();
2525                        exporter->ExportKdTree(*mKdTree);
2526
2527                        for (i=0; i < pvsOut; i++)
2528                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
2529
2530                        exporter->SetFilled();
2531
2532                        delete exporter;
2533                }
2534
2535                for (int k=0; k < pvsOut; k++)
2536                {
2537                        Intersectable *object = objects[k];
2538                        char s[64];
2539                        sprintf(s, "sample-pvs%04d.x3d", k);
2540
2541                        Exporter *exporter = Exporter::GetExporter(s);
2542                        exporter->SetWireframe();
2543
2544                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
2545                        Intersectable::NewMail();
2546
2547                        // avoid adding the object to the list
2548                        object->Mail();
2549                        ObjectContainer visibleObjects;
2550
2551                        for (; i != object->mKdPvs.mEntries.end(); i++)
2552                        {
2553                                KdNode *node = (*i).first;
2554                                exporter->ExportBox(mKdTree->GetBox(node));
2555
2556                                mKdTree->CollectObjects(node, visibleObjects);
2557                        }
2558
2559                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
2560                        exporter->SetFilled();
2561
2562                        for (int j = 0; j < visibleObjects.size(); j++)
2563                                exporter->ExportIntersectable(visibleObjects[j]);
2564
2565                        Material m;
2566                        m.mDiffuseColor = RgbColor(1, 0, 0);
2567                        exporter->SetForcedMaterial(m);
2568                        exporter->ExportIntersectable(object);
2569
2570                        delete exporter;
2571                }
2572        }
2573}
2574
2575
2576void KdViewCellsManager::ExportColor(Exporter *exporter,
2577                                                                         ViewCell *vc) const
2578{
2579        // TODO
2580}
2581
2582
2583ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2584{
2585        return new KdViewCell(mesh);
2586}
2587
2588
2589void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2590                                                                                                ViewCell *vc,
2591                                                                                                const Plane3 *clipPlane) const
2592{
2593        ViewCellContainer leaves;
2594
2595        mViewCellsTree->CollectLeaves(vc, leaves);
2596        ViewCellContainer::const_iterator it, it_end = leaves.end();
2597
2598        for (it = leaves.begin(); it != it_end; ++ it)
2599        {
2600                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
2601       
2602                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
2603        }
2604}
2605
2606
2607int KdViewCellsManager::GetType() const
2608{
2609        return ViewCellsManager::KD;
2610}
2611
2612
2613
2614KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
2615{
2616        KdNode *node = leaf;
2617
2618        while (node->mParent && node->mDepth > mKdPvsDepth)
2619                node = node->mParent;
2620        return node;
2621}
2622
2623int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
2624                                                                                const Vector3 &termination,
2625                                                                                ViewCellContainer &viewcells)
2626{
2627        return mKdTree->CastLineSegment(origin, termination, viewcells);
2628}
2629
2630
2631void KdViewCellsManager::CreateMesh(ViewCell *vc)
2632{
2633        // TODO
2634}
2635
2636
2637
2638void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2639                                                                                                vector<MergeCandidate> &candidates)
2640{
2641        // TODO
2642}
2643
2644
2645/**********************************************************************/
2646/*                   VspKdViewCellsManager implementation             */
2647/**********************************************************************/
2648
2649
2650VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
2651ViewCellsManager(), mVspKdTree(vspKdTree)
2652{
2653        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
2654        mVspKdTree->SetViewCellsManager(this);
2655}
2656
2657float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
2658{
2659        // compute view cell area / volume as subsititute for probability
2660        if (0)
2661                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2662        else
2663                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
2664}
2665
2666
2667
2668
2669void VspKdViewCellsManager::CollectViewCells()
2670{
2671        mVspKdTree->CollectViewCells(mViewCells);
2672}
2673
2674
2675int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2676                                                                                                const VssRayContainer &rays)
2677{
2678        // if view cells already constructed
2679        if (ViewCellsConstructed())
2680                return 0;
2681
2682        VssRayContainer constructionRays;
2683        VssRayContainer savedRays;
2684
2685        GetRaySets(rays,
2686                           mInitialSamples,
2687                           constructionRays,
2688                           &savedRays);
2689
2690        Debug << "constructing vsp kd tree using "
2691                  << (int)constructionRays.size() << " samples" << endl;
2692
2693        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
2694        Debug << mVspKdTree->GetStatistics() << endl;
2695
2696        // export leaf building blocks
2697        ExportLeaves(objects, rays);
2698
2699        // finally merge kd leaf building blocks to view cells
2700        const int merged = mVspKdTree->MergeViewCells(rays);
2701
2702        // collapse siblings belonging to the same view cell
2703        mVspKdTree->RefineViewCells(rays);
2704
2705        // collapse siblings belonging to the same view cell
2706        mVspKdTree->CollapseTree();
2707
2708        // evaluale view cell stats
2709        ResetViewCells();
2710
2711        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
2712
2713        long startTime = GetTime();
2714
2715        // recast rest of rays
2716        ComputeSampleContributions(savedRays, true, false);
2717
2718        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2719                  << " secs" << endl;
2720
2721        return merged;
2722}
2723
2724bool VspKdViewCellsManager::ViewCellsConstructed() const
2725{
2726        return mVspKdTree->GetRoot() != NULL;
2727}
2728
2729
2730ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2731{
2732        return new VspKdViewCell(mesh);
2733}
2734
2735int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
2736                                                                           const VssRayContainer &rays)
2737{
2738        if (!ViewCellsConstructed())
2739                return 0;
2740
2741        // recalculate stats
2742        EvaluateViewCellsStats();
2743
2744        return 0;
2745}
2746
2747
2748void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2749                                                                                 const VssRayContainer &sampleRays)
2750{
2751        if (!ViewCellsConstructed())
2752                return;
2753
2754        //-- export leaf building blocks
2755        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
2756        if (!exporter)
2757                return;
2758
2759        if (mExportGeometry)
2760                exporter->ExportGeometry(objects);
2761       
2762        //exporter->SetWireframe();
2763        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2764        exporter->ExportVspKdTree(*mVspKdTree);
2765
2766        if (mExportRays)
2767        {
2768                const float prob = (float)mVisualizationSamples
2769                        / ((float)sampleRays.size() + Limits::Small);
2770
2771                exporter->SetWireframe();
2772
2773                //-- collect uniformly distributed rays
2774                VssRayContainer rays;
2775
2776                for (int i = 0; i < sampleRays.size(); ++ i)
2777                {
2778                        if (RandomValue(0,1) < prob)
2779                                rays.push_back(sampleRays[i]);
2780                }
2781                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2782        }
2783
2784        delete exporter;
2785}
2786
2787void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2788                                                                          const VssRayContainer &sampleRays)
2789{
2790        if (!ViewCellsConstructed())
2791                return;
2792
2793        //-- export single view cells
2794        for (int i = 0; i < 10; ++ i)
2795        {
2796                char s[64];
2797                sprintf(s, "vsp_viewcell%04d.x3d", i);
2798                Exporter *exporter = Exporter::GetExporter(s);
2799                const int idx =
2800                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
2801
2802                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
2803
2804                //-- export geometry
2805                Material m;
2806                m.mDiffuseColor = RgbColor(0, 1, 1);
2807
2808                exporter->SetForcedMaterial(m);
2809                exporter->SetWireframe();
2810
2811                ExportViewCellGeometry(exporter, vc);
2812
2813                //-- export stored rays
2814               
2815                if (mExportRays)
2816                {
2817                        ViewCellContainer leaves;
2818                        mViewCellsTree->CollectLeaves(vc, leaves);
2819
2820                        ViewCellContainer::const_iterator it,
2821                                it_end = leaves.end();
2822
2823                        for (it = leaves.begin(); it != it_end; ++ it)
2824                        {
2825                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2826                                VspKdLeaf *leaf = vspKdVc->mLeaf;
2827                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
2828
2829                                VssRayContainer vssRays;
2830
2831                                VssRayContainer castRays;
2832                                VssRayContainer initRays;
2833
2834                                leaf->GetRays(vssRays);
2835
2836                                VssRayContainer::const_iterator it, it_end = vssRays.end();
2837                                const float prop = 200.0f / (float)vssRays.size();
2838
2839                                for (it = vssRays.begin(); it != it_end; ++ it)
2840                                {
2841                                        if (Random(1) < prop)
2842                                                if ((*it)->mTerminationObject == NULL)
2843                                                        castRays.push_back(*it);
2844                                                else
2845                                                        initRays.push_back(*it);
2846                                }
2847
2848                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2849                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
2850                        }
2851                }
2852       
2853                //-- output PVS of view cell
2854                m.mDiffuseColor = RgbColor(1, 0, 0);
2855                exporter->SetForcedMaterial(m);
2856
2857                Intersectable::NewMail();
2858
2859                ObjectPvsMap::const_iterator it,
2860                        it_end = vc->GetPvs().mEntries.end();
2861
2862                exporter->SetFilled();
2863
2864                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2865                {
2866                        Intersectable *intersect = (*it).first;
2867
2868                        if (!intersect->Mailed())
2869                        {
2870                                Material m = RandomMaterial();
2871                                exporter->SetForcedMaterial(m);
2872
2873                                exporter->ExportIntersectable(intersect);
2874                                intersect->Mail();
2875                        }
2876                }
2877
2878                delete exporter;
2879        }
2880
2881        //-- export final view cells
2882        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2883
2884        //if (exportGeometry) exporter->SetWireframe();
2885        //else exporter->SetFilled();
2886
2887        ExportViewCellsForViz(exporter);
2888
2889        if (mExportGeometry)
2890        {
2891                exporter->SetFilled();
2892                exporter->ExportGeometry(objects);
2893        }
2894
2895        if (mExportRays)
2896        {
2897                const float prob = (float)mVisualizationSamples
2898                        / ((float)sampleRays.size() + Limits::Small);
2899
2900                exporter->SetWireframe();
2901
2902                VssRayContainer rays;
2903
2904                for (int i = 0; i < sampleRays.size(); ++ i)
2905                {
2906                  if (RandomValue(0,1) < prob)
2907                        rays.push_back(sampleRays[i]);
2908                }
2909                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2910        }
2911
2912        delete exporter;
2913}
2914
2915int VspKdViewCellsManager::GetType() const
2916{
2917        return VSP_KD;
2918}
2919
2920
2921int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2922                                                                                   const Vector3 &termination,
2923                                                                                   ViewCellContainer &viewcells)
2924{
2925        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
2926}
2927
2928
2929void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2930                                                                                ViewCell *vc) const
2931{
2932        if (mColorCode == 0) // Random color
2933                return;
2934
2935        float importance = 0;
2936
2937        switch (mColorCode)
2938        {
2939        case 1: // pvs
2940                {
2941                        importance = (float)vc->GetPvs().GetSize() /
2942                                (float)mCurrentViewCellsStats.maxPvs;
2943                }
2944                break;
2945        case 2: // merged leaves
2946                {
2947                int lSize = mViewCellsTree->GetSize(vc);
2948                        importance = (float)lSize /
2949                                (float)mCurrentViewCellsStats.maxLeaves;
2950                }
2951                break;
2952        case 3: // merged tree depth difference
2953                {
2954                        //importance = (float)GetMaxTreeDiff(vc) /
2955                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2956                }
2957                break;
2958        default:
2959                break;
2960        }
2961
2962        Material m;
2963        m.mDiffuseColor.b = 1.0f;
2964        m.mDiffuseColor.r = importance;
2965        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2966        //Debug << "importance: " << importance << endl;
2967        exporter->SetForcedMaterial(m);
2968}
2969
2970
2971void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2972                                                                                                   ViewCell *vc,
2973                                                                                                   const Plane3 *clipPlane) const
2974{
2975        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2976
2977        Mesh m;
2978
2979        ViewCellContainer leaves;
2980        mViewCellsTree->CollectLeaves(vc, leaves);
2981
2982        ViewCellContainer::const_iterator it, it_end = leaves.end();
2983
2984        for (it = leaves.begin(); it != it_end; ++ it)
2985        {
2986                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2987                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
2988        }
2989
2990        exporter->ExportMesh(&m);
2991}
2992
2993
2994void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2995{
2996        //TODO
2997}
2998
2999
3000void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3001                                                                                                   vector<MergeCandidate> &candidates)
3002{
3003        // TODO
3004}
3005
3006
3007/**************************************************************************/
3008/*                   VspBspViewCellsManager implementation                */
3009/**************************************************************************/
3010
3011
3012VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
3013ViewCellsManager(), mVspBspTree(vspBspTree)
3014{
3015        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
3016        mVspBspTree->SetViewCellsManager(this);
3017        mVspBspTree->mViewCellsTree = mViewCellsTree;
3018}
3019
3020
3021VspBspViewCellsManager::~VspBspViewCellsManager()
3022{
3023}
3024
3025
3026float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
3027{
3028        if (0 && mVspBspTree->mUseAreaForPvs)
3029                return GetArea(viewCell) / GetAccVcArea();
3030        else
3031                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
3032}
3033
3034
3035void VspBspViewCellsManager::CollectViewCells()
3036{
3037        // view cells tree constructed
3038        if (!ViewCellsTreeConstructed())
3039        {
3040                mVspBspTree->CollectViewCells(mViewCells, false);
3041        }
3042        else
3043        {       // we can use the view cells tree hierarchy to get the right set
3044                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
3045        }
3046}
3047
3048
3049bool VspBspViewCellsManager::ViewCellsConstructed() const
3050{
3051        return mVspBspTree->GetRoot() != NULL;
3052}
3053
3054
3055ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3056{
3057        return new BspViewCell(mesh);
3058}
3059
3060
3061int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
3062                                                                                                 const VssRayContainer &rays)
3063{
3064        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
3065
3066        // if view cells were already constructed
3067        if (ViewCellsConstructed())
3068                return 0;
3069
3070        int sampleContributions = 0;
3071
3072        VssRayContainer sampleRays;
3073
3074        int limit = min (mInitialSamples, (int)rays.size());
3075
3076        VssRayContainer constructionRays;
3077        VssRayContainer savedRays;
3078
3079        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
3080                  << ", actual rays: " << (int)rays.size() << endl;
3081
3082        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
3083
3084        Debug << "initial rays: " << (int)constructionRays.size() << endl;
3085        Debug << "saved rays: " << (int)savedRays.size() << endl;
3086
3087
3088        //TODO: remove
3089        if (1)
3090                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
3091        else
3092                mVspBspTree->Construct(rays, &mViewSpaceBox);
3093
3094        // collapse invalid regions
3095        cout << "collapsing invalid tree regions ... ";
3096        long startTime = GetTime();
3097        int collapsedLeaves = mVspBspTree->CollapseTree();
3098        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
3099                  << " seconds" << endl;
3100
3101    cout << "finished" << endl;
3102
3103        // -- stats
3104        Debug << mVspBspTree->GetStatistics() << endl;
3105
3106        ResetViewCells();
3107        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
3108
3109
3110        startTime = GetTime();
3111
3112        cout << "Computing remaining ray contributions ... ";
3113
3114        // recast rest of rays
3115        if (SAMPLE_AFTER_SUBDIVISION)
3116                ComputeSampleContributions(savedRays, true, false);
3117        cout << "finished" << endl;
3118
3119        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
3120                  << " secs" << endl;
3121
3122        cout << "construction finished" << endl;
3123
3124        // real meshes are contructed at this stage
3125        if (0)
3126        {
3127                cout << "finalizing view cells ... ";
3128                FinalizeViewCells(true);
3129                cout << "finished" << endl;
3130        }
3131
3132        return sampleContributions;
3133}
3134
3135
3136void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
3137                                                                                        const ObjectContainer &objects)
3138{
3139    int vcSize = 0;
3140        int pvsSize = 0;
3141
3142        //-- merge view cells
3143        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
3144        long startTime = GetTime();
3145
3146
3147        if (mMergeViewCells)
3148        {
3149                // TODO: should be done BEFORE the ray casting
3150                // compute tree by merging the nodes based on cost heuristics
3151                mViewCellsTree->ConstructMergeTree(rays, objects);
3152        }
3153        else
3154        {
3155                // compute tree by merging the nodes of the spatial hierarchy
3156                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
3157                mViewCellsTree->SetRoot(root);
3158        }
3159
3160        if (1)
3161        {
3162                char mstats[100];
3163                environment->GetStringValue("ViewCells.mergeStats", mstats);
3164                mViewCellsTree->ExportStats(mstats);
3165        }
3166
3167        //-- stats and visualizations
3168        cout << "finished merging" << endl;
3169        cout << "merged view cells in "
3170                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
3171
3172        Debug << "Postprocessing: Merged view cells in "
3173                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
3174       
3175
3176        int savedColorCode = mColorCode;
3177       
3178        // get currently active view cell set
3179        ResetViewCells();
3180        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
3181
3182        //BspLeaf::NewMail();
3183        if (1) // export merged view cells
3184        {
3185                mColorCode = 0;
3186                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
3187               
3188                cout << "exporting view cells after merge ... ";
3189
3190                if (exporter)
3191                {
3192                        if (0)
3193                                exporter->SetWireframe();
3194                        else
3195                                exporter->SetFilled();
3196
3197                        ExportViewCellsForViz(exporter);
3198
3199                        if (mExportGeometry)
3200                        {
3201                                Material m;
3202                                m.mDiffuseColor = RgbColor(0, 1, 0);
3203                                exporter->SetForcedMaterial(m);
3204                                exporter->SetFilled();
3205
3206                                exporter->ExportGeometry(objects);
3207                        }
3208
3209                        delete exporter;
3210                }
3211                cout << "finished" << endl;
3212        }
3213
3214        if (1) // export merged view cells using pvs coding
3215        {
3216                mColorCode = 1;
3217
3218                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
3219       
3220                cout << "exporting view cells after merge (pvs size) ... ";     
3221
3222                if (exporter)
3223                {
3224                        if (0)
3225                                exporter->SetWireframe();
3226                        else
3227                                exporter->SetFilled();
3228
3229                        ExportViewCellsForViz(exporter);
3230
3231                        if (mExportGeometry)
3232                        {
3233                                Material m;
3234                                m.mDiffuseColor = RgbColor(0, 1, 0);
3235                                exporter->SetForcedMaterial(m);
3236                                exporter->SetFilled();
3237
3238                                exporter->ExportGeometry(objects);
3239                        }
3240
3241                        delete exporter;
3242                }
3243                cout << "finished" << endl;
3244        }
3245
3246        mColorCode = savedColorCode;
3247
3248}
3249
3250
3251bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
3252{
3253        return GetSpatialNode(viewCell) != NULL;
3254}
3255
3256
3257BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
3258{
3259        if (!viewCell->IsLeaf())
3260        {
3261                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
3262
3263                return bspVc->mLeaf;
3264        }
3265        else
3266        {
3267                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
3268
3269                // cannot be node of binary tree
3270                if (interior->mChildren.size() != 2)
3271                        return NULL;
3272
3273                ViewCell *left = interior->mChildren[0];
3274                ViewCell *right = interior->mChildren[1];
3275
3276                BspNode *leftNode = GetSpatialNode(left);
3277                BspNode *rightNode = GetSpatialNode(right);
3278
3279                if (leftNode && rightNode && leftNode->IsSibling(rightNode))
3280                {
3281                        return leftNode->GetParent();
3282                }
3283        }
3284
3285        return NULL;
3286}
3287
3288
3289void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
3290                                                                                         const ObjectContainer &objects)
3291{
3292        Debug << "render time before refine:" << endl;
3293        mRenderer->RenderScene();
3294        SimulationStatistics ss;
3295        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
3296    Debug << ss << endl;
3297
3298        cout << "Refining the merged view cells ... ";
3299        long startTime = GetTime();
3300
3301        // refining the merged view cells
3302        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
3303
3304        //-- stats and visualizations
3305        cout << "finished" << endl;
3306        cout << "refined " << refined << " view cells in "
3307                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
3308
3309        Debug << "Postprocessing: refined " << refined << " view cells in "
3310                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
3311}
3312
3313
3314int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
3315                                                                                const VssRayContainer &rays)
3316{
3317        if (!ViewCellsConstructed())
3318        {
3319                Debug << "postprocess error: no view cells constructed" << endl;
3320                return 0;
3321        }
3322
3323
3324        // view cells already finished before post processing step
3325        // (i.e. because they were loaded)
3326        if (mViewCellsFinished)
3327        {
3328                FinalizeViewCells(true);
3329                EvaluateViewCellsStats();
3330
3331                return 0;
3332        }
3333
3334        // check if new view cells turned invalid
3335        int minPvs, maxPvs;
3336
3337        if (0)
3338        {
3339                minPvs = mMinPvsSize;
3340                maxPvs = mMaxPvsSize;
3341        }
3342        else
3343        {
3344                minPvs = mPruneEmptyViewCells ? 1 : 0;
3345                maxPvs = mMaxPvsSize;
3346        }
3347
3348        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3349        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
3350       
3351        SetValidity(minPvs, maxPvs);
3352
3353        // update valid view space according to valid view cells
3354        if (0) mVspBspTree->ValidateTree();
3355
3356        // area has to be recomputed
3357        mTotalAreaValid = false;
3358        VssRayContainer postProcessRays;
3359        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3360
3361        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
3362
3363
3364        // should maybe be done here to allow merge working with area or volume
3365        // and to correct the rendering statistics
3366        if (0) FinalizeViewCells(false);
3367               
3368        //-- merge the individual view cells
3369        MergeViewCells(postProcessRays, objects);
3370       
3371
3372        // only for debugging purpose: test if the subdivision is valid
3373        TestSubdivision();
3374
3375        //-- refines the merged view cells
3376        if (0) RefineViewCells(postProcessRays, objects);
3377
3378       
3379        //-- render simulation after merge + refine
3380        cout << "\nevaluating bsp view cells render time before compress ... ";
3381        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
3382        SimulationStatistics ss;
3383        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
3384 
3385
3386        cout << " finished" << endl;
3387        cout << ss << endl;
3388        Debug << ss << endl;
3389
3390
3391        //-- compression
3392        if (ViewCellsTreeConstructed() && mCompressViewCells)
3393        {
3394                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3395                Debug << "number of entries before compress: " << pvsEntries << endl;
3396
3397                mViewCellsTree->CompressViewCellsPvs();
3398
3399                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3400                Debug << "number of entries after compress: " << pvsEntries << endl;
3401        }
3402
3403
3404        // collapse sibling leaves that share the same view cell
3405        if (0)
3406                mVspBspTree->CollapseTree();
3407
3408        // recompute view cell list and statistics
3409        ResetViewCells();
3410
3411        // compute final meshes and volume / area
3412        if (1) FinalizeViewCells(true);
3413
3414
3415        // write view cells to disc
3416        if (mExportViewCells)
3417        {
3418                char buff[100];
3419                environment->GetStringValue("ViewCells.filename", buff);
3420                string vcFilename(buff);
3421
3422                ExportViewCells(buff);
3423        }
3424
3425        return 0;
3426}
3427
3428
3429int VspBspViewCellsManager::GetType() const
3430{
3431        return VSP_BSP;
3432}
3433
3434
3435ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
3436{
3437        if (root->IsLeaf())
3438        {
3439                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
3440
3441                viewCell->SetMergeCost(0.0f);
3442
3443                return viewCell;
3444        }
3445       
3446        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3447        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3448               
3449        float mergeCost = 1.0f / (float)root->mTimeStamp;
3450        //Debug << "timestamp: " << root->mTimeStamp;
3451        //Debug << "merge cost: " << mergeCost << endl;
3452
3453        viewCellInterior->SetMergeCost(mergeCost);
3454
3455        float volume = 0;
3456       
3457        BspNode *front = interior->GetFront();
3458        BspNode *back = interior->GetBack();
3459
3460        // recursivly compute child hierarchies
3461        ViewCell *backVc = ConstructSpatialMergeTree(back);
3462        ViewCell *frontVc = ConstructSpatialMergeTree(front);
3463
3464        viewCellInterior->SetupChildLink(frontVc);
3465        viewCellInterior->SetupChildLink(backVc);
3466
3467
3468        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
3469        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
3470
3471        volume += backVc->GetVolume();
3472        volume += frontVc->GetVolume();
3473
3474        viewCellInterior->SetVolume(volume);
3475
3476        return viewCellInterior;
3477}
3478
3479
3480bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
3481{
3482        if (!ViewCellsConstructed())
3483                return ViewCellsManager::GetViewPoint(viewPoint);
3484
3485        // TODO: set reasonable limit
3486        const int limit = 20;
3487
3488        for (int i = 0; i < limit; ++ i)
3489        {
3490                viewPoint = mViewSpaceBox.GetRandomPoint();
3491                if (mVspBspTree->ViewPointValid(viewPoint))
3492                {
3493                        return true;
3494                }
3495        }
3496        Debug << "failed to find valid view point, taking " << viewPoint << endl;
3497        return false;
3498}
3499
3500
3501bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
3502{
3503  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
3504  // validy update in preprocessor for all managers)
3505  return ViewCellsManager::ViewPointValid(viewPoint);
3506
3507  //    return mViewSpaceBox.IsInside(viewPoint) &&
3508  //               mVspBspTree->ViewPointValid(viewPoint);
3509}
3510
3511
3512void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
3513                                                                           const VssRayContainer &sampleRays)
3514{
3515        if (!ViewCellsConstructed())
3516                return;
3517
3518        VssRayContainer visRays;
3519        GetRaySets(sampleRays, mVisualizationSamples, visRays);
3520
3521       
3522        if (1) // export view cells
3523        {       // hack pvs
3524                int savedColorCode = mColorCode;
3525                mColorCode = 0;
3526                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
3527               
3528                if (exporter)
3529                {
3530                        cout << "exporting view cells after post process ... ";
3531
3532                        if (0)
3533                        {
3534                                exporter->SetWireframe();
3535                                exporter->ExportBox(mViewSpaceBox);
3536                                exporter->SetFilled();
3537                        }
3538
3539                        if (mExportGeometry)
3540                        {
3541                                exporter->ExportGeometry(objects);
3542                        }
3543
3544                        // export rays
3545                        if (mExportRays)
3546                        {
3547                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
3548                        }
3549
3550                        ExportViewCellsForViz(exporter);
3551                        delete exporter;
3552                        cout << "finished" << endl;
3553                }
3554
3555                mColorCode = savedColorCode;
3556        }
3557
3558        if (0)
3559        {
3560                cout << "exporting depth map ... ";
3561
3562                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
3563                if (exporter)
3564                {
3565                        if (1)
3566                        {
3567                                exporter->SetWireframe();
3568                                exporter->ExportBox(mViewSpaceBox);
3569                                exporter->SetFilled();
3570                        }
3571
3572                        if (mExportGeometry)
3573                        {
3574                                exporter->ExportGeometry(objects);
3575                        }
3576
3577                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
3578
3579                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
3580
3581                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
3582                        {
3583                                ViewCell *vc = *vit;
3584
3585                                ViewCellContainer leaves;
3586                                mViewCellsTree->CollectLeaves(vc, leaves);
3587
3588                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3589
3590                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
3591                                {
3592                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3593
3594                                        Material m;
3595
3596                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
3597                                        m.mDiffuseColor.r = relDepth;
3598                                        m.mDiffuseColor.g = 0.0f;
3599                                        m.mDiffuseColor.b = 1.0f - relDepth;
3600
3601                    exporter->SetForcedMaterial(m);
3602                               
3603
3604                                        BspNodeGeometry geom;
3605                                        mVspBspTree->ConstructGeometry(leaf, geom);
3606                                        exporter->ExportPolygons(geom.GetPolys());
3607                                }
3608                        }
3609
3610                        delete exporter;
3611                }
3612
3613
3614                cout << "finished" << endl;
3615        }
3616
3617        //-- visualization of the BSP splits
3618        bool exportSplits = false;
3619        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
3620
3621        if (exportSplits)
3622        {
3623                cout << "exporting splits ... ";
3624                ExportSplits(objects, visRays);
3625                cout << "finished" << endl;
3626        }
3627
3628        //-- export single view cells
3629        ExportBspPvs(objects, visRays);
3630}
3631
3632
3633void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3634                                                                                  const VssRayContainer &rays)
3635{
3636        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3637
3638        if (exporter)
3639        {
3640                Material m;
3641                m.mDiffuseColor = RgbColor(1, 0, 0);
3642                exporter->SetForcedMaterial(m);
3643                exporter->SetWireframe();
3644
3645                exporter->ExportBspSplits(*mVspBspTree, true);
3646
3647                // take forced material, else big scenes cannot be viewed
3648                m.mDiffuseColor = RgbColor(0, 1, 0);
3649                exporter->SetForcedMaterial(m);
3650                exporter->SetFilled();
3651
3652                exporter->ResetForcedMaterial();
3653
3654                // export rays
3655                if (mExportRays)
3656                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
3657
3658                if (mExportGeometry)
3659                        exporter->ExportGeometry(objects);
3660
3661                delete exporter;
3662        }
3663}
3664
3665
3666void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3667                                                                                  const VssRayContainer &rays)
3668{
3669        const int leafOut = 20;
3670
3671        ViewCell::NewMail();
3672
3673        cout << "visualization using " << (int)rays.size() << " samples" << endl;
3674        Debug << "visualization using " << (int)rays.size() << " samples" << endl;
3675        Debug << "\nOutput view cells: " << endl;
3676
3677        const bool sortViewCells = true;
3678
3679        // sort view cells to visualize the largest view cells
3680        if (sortViewCells)
3681                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
3682       
3683        int limit = min(leafOut, (int)mViewCells.size());
3684
3685        int raysOut = 0;
3686
3687        //-- some rays for output
3688        for (int i = 0; i < limit; ++ i)
3689        {
3690                cout << "creating output for view cell " << i << " ... ";
3691
3692                ViewCell *vc;
3693       
3694                if (sortViewCells) // largest view cell pvs first
3695                        vc = mViewCells[i];
3696                else
3697                        vc = mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
3698
3699                //bspLeaves[j]->Mail();
3700                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3701                Exporter *exporter = Exporter::GetExporter(s);
3702               
3703                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc) << endl;
3704
3705                if (1 || mExportRays)
3706                {
3707                        // output rays stored with the view cells during subdivision
3708                        if (0)
3709                        {
3710                                VssRayContainer vcRays;
3711                VssRayContainer collectRays;
3712
3713                                raysOut = min((int)rays.size(), 100);
3714
3715                                // collect intial view cells
3716                                ViewCellContainer leaves;
3717                                mViewCellsTree->CollectLeaves(vc, leaves);
3718
3719                                ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3720       
3721                                for (vit = leaves.begin(); vit != vit_end; ++ vit)
3722                                {
3723                                        BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaf;
3724                               
3725                                        VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
3726
3727                                        for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
3728                                        {
3729                                                collectRays.push_back(*rit);
3730                                        }
3731                                }
3732
3733                                VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3734
3735                                for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3736                                {
3737                                        float p = RandomValue(0.0f, (float)collectRays.size());
3738                       
3739                                        if (p < raysOut)
3740                                                vcRays.push_back(*rit);
3741                                }
3742                                //-- export rays piercing this view cell
3743                                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
3744                        }
3745               
3746                        // associate new rays with output view cell
3747                        if (1)
3748                        {
3749                                VssRayContainer vcRays;
3750                                raysOut = min((int)rays.size(), mVisualizationSamples);
3751                                // check whether we can add the current ray to the output rays
3752                                for (int k = 0; k < raysOut; ++ k)
3753                                {
3754                                        VssRay *ray = rays[k];
3755                                        for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3756                                        {
3757                                                ViewCell *rayvc = ray->mViewCells[j];
3758       
3759                                                if (rayvc == vc)
3760                                                        vcRays.push_back(ray);
3761                                        }
3762                                }       
3763                               
3764                                //-- export rays piercing this view cell
3765                                exporter->ExportRays(vcRays, RgbColor(1, 1, 0));
3766                        }
3767
3768                }
3769               
3770
3771                exporter->SetWireframe();
3772
3773                Material m;//= RandomMaterial();
3774                m.mDiffuseColor = RgbColor(0, 1, 0);
3775                exporter->SetForcedMaterial(m);
3776
3777                ExportViewCellGeometry(exporter, vc);
3778       
3779                exporter->SetFilled();
3780
3781
3782                if (1)
3783                {
3784                        ObjectPvsMap::const_iterator oit,
3785                                oit_end = vc->GetPvs().mEntries.end();
3786
3787
3788                        exporter->SetFilled();
3789
3790                        Intersectable::NewMail();
3791       
3792                        // output PVS of view cell
3793                        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
3794                        {               
3795                                Intersectable *intersect = (*oit).first;
3796
3797                                if (!intersect->Mailed())
3798                                {
3799                                        m = RandomMaterial();
3800                                        exporter->SetForcedMaterial(m);
3801
3802                                        exporter->ExportIntersectable(intersect);
3803                                        intersect->Mail();
3804                                }
3805                        }
3806                }
3807                else
3808                {
3809                        m.mDiffuseColor = RgbColor(1, 0, 0);
3810                        exporter->SetForcedMaterial(m);
3811
3812                        exporter->ExportGeometry(objects);
3813                }
3814
3815                DEL_PTR(exporter);
3816                cout << "finished" << endl;
3817        }
3818
3819        Debug << endl;
3820}
3821
3822
3823int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const
3824{
3825        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
3826}
3827
3828
3829int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3830                                                                                        const Vector3 &termination,
3831                                                                                        ViewCellContainer &viewcells)
3832{
3833        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
3834}
3835
3836
3837void VspBspViewCellsManager::ExportColor(Exporter *exporter,
3838                                                                                 ViewCell *vc) const
3839{
3840        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3841
3842        float importance = 0;
3843        static Material m;
3844
3845        switch (mColorCode)
3846        {
3847        case 0: // Random
3848                {
3849                        if (vcValid)
3850                        {
3851                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3852                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3853                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
3854                        }
3855                        else
3856                        {
3857                                m.mDiffuseColor.r = 0.0f;
3858                                m.mDiffuseColor.g = 1.0f;
3859                                m.mDiffuseColor.b = 0.0f;
3860                        }
3861
3862                        exporter->SetForcedMaterial(m);
3863                        return;
3864                }
3865               
3866        case 1: // pvs
3867                {
3868                        importance = (float)vc->GetPvs().GetSize() /
3869                                (float)mCurrentViewCellsStats.maxPvs;
3870
3871                }
3872                break;
3873        case 2: // merges
3874                {
3875            int lSize = mViewCellsTree->GetSize(vc);
3876                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
3877                }
3878                break;
3879        case 3: // merge tree differene
3880                {
3881                        importance = (float)GetMaxTreeDiff(vc) /
3882                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3883
3884                }
3885                break;
3886        default:
3887                break;
3888        }
3889
3890        // special color code for invalid view cells
3891        m.mDiffuseColor.r = importance;
3892        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3893        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
3894
3895        //Debug << "importance: " << importance << endl;
3896        exporter->SetForcedMaterial(m);
3897}
3898
3899
3900void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3901                                                    ViewCell *vc,
3902                                                                                                        const Plane3 *clipPlane) const
3903{
3904        if (vc->GetMesh())
3905        {
3906                exporter->ExportMesh(vc->GetMesh());
3907       
3908                return;
3909        }
3910
3911       
3912        if (clipPlane)
3913        {
3914                ViewCellContainer leaves;
3915                mViewCellsTree->CollectLeaves(vc, leaves);
3916                ViewCellContainer::const_iterator it, it_end = leaves.end();
3917
3918                for (it = leaves.begin(); it != it_end; ++ it)
3919                {
3920                        BspNodeGeometry geom;
3921
3922                        BspNodeGeometry front;
3923                        BspNodeGeometry back;
3924
3925                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3926                        mVspBspTree->ConstructGeometry(leaf, geom);
3927
3928                        const float eps = 0.00000001f;
3929                        const int cf = geom.Side(*clipPlane, eps);
3930
3931                        if (cf == -1)
3932                        {
3933                                exporter->ExportPolygons(geom.GetPolys());
3934                        }
3935                        else if (cf == 0)
3936                        {
3937                                geom.SplitGeometry(front,
3938                                                                   back,
3939                                                                   *clipPlane,
3940                                                                   mViewSpaceBox,
3941                                                                   eps);
3942       
3943                                //Debug << "geo size: " << geom.Size() << endl;
3944                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
3945                                if (back.Valid())
3946                                {
3947                                        exporter->ExportPolygons(back.GetPolys());
3948                                }                       
3949                        }
3950                }
3951        }
3952        else
3953        {
3954                BspNodeGeometry geom;
3955                mVspBspTree->ConstructGeometry(vc, geom);
3956                       
3957                exporter->ExportPolygons(geom.GetPolys());
3958        }
3959}
3960
3961
3962int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3963{
3964        ViewCellContainer leaves;
3965        mViewCellsTree->CollectLeaves(vc, leaves);
3966
3967        int maxDist = 0;
3968       
3969        // compute max height difference
3970        for (int i = 0; i < (int)leaves.size(); ++ i)
3971                for (int j = 0; j < (int)leaves.size(); ++ j)
3972        {
3973                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
3974
3975                if (i != j)
3976                {
3977                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
3978                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3979                        if (dist > maxDist)
3980                                maxDist = dist;
3981                }
3982        }
3983
3984        return maxDist;
3985}
3986
3987
3988ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
3989{
3990        if (!mVspBspTree)
3991                return NULL;
3992
3993        if (!mViewSpaceBox.IsInside(point))
3994          return NULL;
3995
3996        return mVspBspTree->GetViewCell(point);
3997}
3998
3999
4000void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
4001{
4002        if (vc->GetMesh())
4003                delete vc->GetMesh();
4004
4005       
4006        BspNodeGeometry geom;
4007
4008        mVspBspTree->ConstructGeometry(vc, geom);
4009       
4010        Mesh *mesh = new Mesh();
4011        geom.AddToMesh(*mesh);
4012        vc->SetMesh(mesh);
4013        mMeshContainer.push_back(mesh);
4014}
4015
4016
4017ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
4018                                                                                                  ObjectContainer *objects)
4019{
4020        ViewCellsParser parser;
4021
4022        ViewCellsManager *vm = NULL;
4023
4024        if (parser.ParseFile(filename, &vm, objects))
4025        {
4026                //vm->PrepareLoadedViewCells();
4027                vm->ResetViewCells();
4028
4029                vm->mViewCellsFinished = true;
4030                vm->mMaxPvsSize = (int)objects->size();
4031
4032                // create the meshes and compute volumes
4033                vm->FinalizeViewCells(true);
4034
4035                vm->mViewCellsTree->AssignRandomColors();
4036                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
4037        }
4038        else
4039        {
4040                Debug << "failed loading view cells" << endl;
4041                DEL_PTR(vm);
4042        }
4043
4044        return vm;
4045}
4046
4047
4048inline bool ilt(Intersectable *obj1, Intersectable *obj2)
4049{
4050        return obj1->mId < obj2->mId;
4051}
4052
4053
4054bool VspBspViewCellsManager::ExportViewCells(const string filename)
4055{
4056        cout << "exporting view cells to xml ... ";
4057        std::ofstream stream;
4058
4059        // for output we need unique ids for each view cell
4060        CreateUniqueViewCellIds();
4061
4062        stream.open(filename.c_str());
4063        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
4064        stream << "<Visibility_Solution>" << endl;
4065
4066        //-- the view space bounding box
4067        stream << "<ViewSpaceBox"
4068                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
4069                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
4070
4071        //-- the type of the view cells hierarchy
4072        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
4073
4074        //-- load the view cells itself, i.e., the ids and the pvs
4075        stream << "<ViewCells>" << endl;
4076       
4077#if 0
4078       
4079        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
4080               
4081        for (it = mViewCells.begin(); it != it_end; ++ it)
4082                ExportViewCell(*it, stream);
4083#else
4084        mViewCellsTree->Export(stream);
4085#endif
4086
4087        stream << "</ViewCells>" << endl;
4088
4089        //-- load the hierarchy
4090        stream << "<Hierarchy>" << endl;
4091        mVspBspTree->Export(stream);
4092        stream << endl << "</Hierarchy>" << endl;
4093
4094        stream << "</Visibility_Solution>" << endl;
4095        stream.close();
4096
4097        cout << "finished" << endl;
4098
4099        return true;
4100}
4101
4102
4103int VspBspViewCellsManager::CastBeam(Beam &beam)
4104{
4105        return mVspBspTree->CastBeam(beam);
4106}
4107
4108
4109void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
4110                                                                          const bool createMesh)
4111{
4112        float area = 0;
4113        float volume = 0;
4114
4115        ViewCellContainer leaves;
4116        mViewCellsTree->CollectLeaves(viewCell, leaves);
4117
4118        ViewCellContainer::const_iterator it, it_end = leaves.end();
4119
4120    for (it = leaves.begin(); it != it_end; ++ it)
4121        {
4122                BspNodeGeometry geom;
4123                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4124                mVspBspTree->ConstructGeometry(leaf, geom);
4125
4126                const float lVol = geom.GetVolume();
4127                const float lArea = geom.GetArea();
4128
4129                //(*it)->SetVolume(vol);
4130                //(*it)->SetArea(area);
4131
4132                area += lArea;
4133                volume += lVol;
4134
4135        CreateMesh(*it);
4136        }
4137
4138        viewCell->SetVolume(volume);
4139        viewCell->SetArea(area);
4140}
4141
4142
4143void VspBspViewCellsManager::TestSubdivision()
4144{
4145        ViewCellContainer leaves;
4146        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
4147
4148        ViewCellContainer::const_iterator it, it_end = leaves.end();
4149
4150        const float vol = mViewSpaceBox.GetVolume();
4151        float subdivVol = 0;
4152        float newVol = 0;
4153
4154        for (it = leaves.begin(); it != it_end; ++ it)
4155        {
4156                BspNodeGeometry geom;
4157                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4158                mVspBspTree->ConstructGeometry(leaf, geom);
4159
4160                const float lVol = geom.GetVolume();
4161               
4162                newVol += lVol;
4163                subdivVol += (*it)->GetVolume();
4164               
4165                float thres = 0.9f;
4166                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
4167                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
4168        }
4169       
4170        Debug << "exact volume: " << vol << endl;
4171        Debug << "subdivision volume: " << subdivVol << endl;
4172        Debug << "new volume: " << newVol << endl;
4173}
4174
4175
4176void VspBspViewCellsManager::PrepareLoadedViewCells()
4177{
4178        // TODO: do I still need this here?
4179        if (0)
4180                mVspBspTree->RepairViewCellsLeafLists();
4181}
4182
4183
4184void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
4185{
4186        Exporter *exporter = Exporter::GetExporter("filter.x3d");
4187
4188        Vector3 bsize = mViewSpaceBox.Size();
4189        const Vector3 viewPoint(mViewSpaceBox.Center());
4190        const Vector3 width = Vector3(mFilterWidth);
4191       
4192        PrVs testPrVs;
4193       
4194        if (exporter)
4195        {
4196                ViewCellContainer viewCells;
4197       
4198        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
4199
4200                GetPrVS(viewPoint, testPrVs);
4201
4202                exporter->SetWireframe();
4203
4204                exporter->SetForcedMaterial(RgbColor(1,1,1));
4205                exporter->ExportBox(tbox);
4206               
4207                exporter->SetFilled();
4208
4209                exporter->SetForcedMaterial(RgbColor(0,1,0));
4210                ExportViewCellGeometry(exporter,  GetViewCell(viewPoint));
4211
4212                //exporter->ResetForcedMaterial();
4213                exporter->SetForcedMaterial(RgbColor(0,0,1));
4214                ExportViewCellGeometry(exporter, testPrVs.mViewCell);
4215
4216        exporter->SetForcedMaterial(RgbColor(1,0,0));
4217                exporter->ExportGeometry(objects);
4218
4219                delete exporter;
4220        }
4221}
4222
4223
4224void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4225                                                                                                        vector<MergeCandidate> &candidates)
4226{       
4227        cout << "collecting merge candidates ... " << endl;
4228
4229        if (mUseRaysForMerge)
4230        {
4231                mVspBspTree->CollectMergeCandidates(rays, candidates);
4232        }
4233        else
4234        {
4235                vector<BspLeaf *> leaves;
4236                mVspBspTree->CollectLeaves(leaves);
4237       
4238                mVspBspTree->CollectMergeCandidates(leaves, candidates);
4239        }
4240
4241        cout << "fininshed collecting candidates" << endl;
4242}
4243
4244
4245void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
4246{
4247        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
4248        for (it = mViewCells.begin(); it != it_end; ++ it)
4249        {
4250        }
4251}
4252
4253//////////////////////////////////
4254ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
4255{
4256        //TODO
4257        return NULL;// new VspBspViewCellsManager();
4258}
4259
Note: See TracBrowser for help on using the repository browser.