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

Revision 666, 86.4 KB checked in by mattausch, 18 years ago (diff)

debug version for testing subdivision quality

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