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

Revision 580, 70.2 KB checked in by mattausch, 18 years ago (diff)

implemented variance
started implementing merge history

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