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

Revision 585, 71.2 KB checked in by mattausch, 18 years ago (diff)

fixed bug in compressing

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