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

Revision 573, 63.9 KB checked in by mattausch, 18 years ago (diff)

implemented functtion for view cell construction

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