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

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

test version
build script for testing. code is set uo for testing also

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