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

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