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

Revision 719, 100.1 KB checked in by mattausch, 19 years ago (diff)

updating view cell hierarchy before pvs statistics

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