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

Revision 577, 66.7 KB checked in by mattausch, 18 years ago (diff)

fixed loading function: the view cell manager is chosen depending on
the type in the file. the view space box is saved with the file

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