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

Revision 581, 70.6 KB checked in by mattausch, 18 years ago (diff)

added function for pvs compression

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