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

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