source: trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellsManager.cpp @ 590

Revision 590, 75.9 KB checked in by mattausch, 18 years ago (diff)

implemented some code for merge history loading

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