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

Revision 694, 91.6 KB checked in by mattausch, 19 years ago (diff)

added means for rotating scene

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