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

Revision 579, 67.5 KB checked in by mattausch, 18 years ago (diff)

started to include variance into the measures

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