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

Revision 584, 71.9 KB checked in by mattausch, 18 years ago (diff)
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        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2369
2370        int pvsSize = 0;
2371        int numPvsEntries = 0;
2372
2373        int vidx = 0;
2374        for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
2375        {
2376                const int vcPvs = mViewCellsTree->GetPvsSize(*vit);
2377                const int pvsEntries = mViewCellsTree->GetNumPvsEntries(*vit);
2378
2379                pvsSize += vcPvs;
2380                numPvsEntries += pvsEntries;
2381                Debug << "Viewcell " << vidx ++ << ": " << vcPvs << endl;
2382        }
2383
2384        Debug << "pvs size before compress: " << pvsSize << endl;
2385        Debug << "number of entries before compress: " << numPvsEntries << endl;
2386
2387        mViewCellsTree->CompressViewCellsPvs();
2388
2389        pvsSize = numPvsEntries = vidx = 0;
2390
2391        for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
2392        {
2393                const int vcPvs = mViewCellsTree->GetPvsSize(*vit);
2394                const int pvsEntries = mViewCellsTree->GetNumPvsEntries(*vit);
2395               
2396                pvsSize += vcPvs;
2397                numPvsEntries += pvsEntries;
2398                Debug << "Viewcell " << vidx ++ << ": " << vcPvs << endl;       
2399        }
2400
2401        Debug << "pvs size after compress: " << pvsSize << endl;
2402        Debug << "number of entries after compress: " << numPvsEntries << endl;
2403
2404        if (1)
2405        {               
2406                float totalCost, erc, var, dev, avg;
2407                int totalpvs;
2408
2409                mViewCellsStats.Reset();
2410
2411        EvaluateRenderStatistics(totalCost, erc, dev, var, totalpvs, avg);
2412               
2413                Debug << "statistics after merge " 
2414                          << " erc: " << erc
2415                          << " dev: " << dev
2416                          << " totalpvs: " << totalpvs
2417                          << " avg: " << avg << endl;
2418        }
2419
2420
2421        //-- export shuffled view cells
2422        if (1)
2423        {
2424                cout << "exporting shuffled view cells ... ";
2425
2426                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2427                if (exporter)
2428                {
2429                        if (1)
2430                        {
2431                                exporter->SetWireframe();
2432                                exporter->ExportBox(mViewSpaceBox);
2433                                exporter->SetFilled();
2434                        }
2435
2436                        if (mExportGeometry)
2437                        {
2438                                exporter->ExportGeometry(objects);
2439                        }
2440
2441                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2442
2443                        Material vm, lm;
2444
2445                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2446                        {
2447                                ViewCell *vc = *vit;
2448
2449                                vm = RandomMaterial();
2450
2451                                lm = vm;
2452
2453                                vm.mDiffuseColor.r -= 0.45f;
2454                                vm.mDiffuseColor.g -= 0.45f;
2455                                vm.mDiffuseColor.b -= 0.45f;
2456
2457
2458                                ViewCellContainer leaves;
2459                                mViewCellsTree->CollectLeaves(vc, leaves);
2460
2461                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2462
2463                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2464                                {
2465                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2466
2467                                        if (leaf->Mailed())
2468                                                exporter->SetForcedMaterial(lm);
2469                                        else
2470                                                exporter->SetForcedMaterial(vm);
2471
2472                                        BspNodeGeometry geom;
2473                                        mVspBspTree->ConstructGeometry(leaf, geom);
2474                                        exporter->ExportPolygons(geom.mPolys);
2475                                }
2476                        }
2477
2478                        delete exporter;
2479                }
2480
2481
2482                cout << "finished" << endl;
2483        }
2484
2485        // collapse sibling leaves that share the same view cell
2486        mVspBspTree->CollapseTree();
2487        // recompute view cell list and statistics
2488        ResetViewCells();
2489
2490        // real meshes are only contructed only at this stage
2491        FinalizeViewCells(true);
2492
2493        // for output we need unique ids for each view cell
2494        CreateUniqueViewCellIds();
2495
2496        // write view cells to disc
2497        if (mExportViewCells)
2498        {
2499                char buff[100];
2500                environment->GetStringValue("ViewCells.filename", buff);
2501                string vcFilename(buff);
2502
2503                ExportViewCells(buff);
2504        }
2505
2506        return 0;
2507}
2508
2509
2510int VspBspViewCellsManager::GetType() const
2511{
2512        return VSP_BSP;
2513}
2514
2515
2516bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2517{
2518        if (!ViewCellsConstructed())
2519                return ViewCellsManager::GetViewPoint(viewPoint);
2520
2521        // TODO: set reasonable limit
2522        const int limit = 20;
2523
2524        for (int i = 0; i < limit; ++ i)
2525        {
2526                viewPoint = mViewSpaceBox.GetRandomPoint();
2527                if (mVspBspTree->ViewPointValid(viewPoint))
2528                {
2529                        return true;
2530                }
2531        }
2532        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2533        return false;
2534}
2535
2536
2537bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2538{
2539  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2540  // validy update in preprocessor for all managers)
2541  return ViewCellsManager::ViewPointValid(viewPoint);
2542
2543  //    return mViewSpaceBox.IsInside(viewPoint) &&
2544  //               mVspBspTree->ViewPointValid(viewPoint);
2545}
2546
2547
2548void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2549                                                                           const VssRayContainer &sampleRays)
2550{
2551        if (!ViewCellsConstructed())
2552                return;
2553
2554        VssRayContainer visRays;
2555        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2556
2557        if (1) // export view cells
2558        {
2559                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2560
2561                if (exporter)
2562                {
2563                        cout << "exporting view cells after post process ... ";
2564
2565                        if (1)
2566                        {
2567                                exporter->SetWireframe();
2568                                exporter->ExportBox(mViewSpaceBox);
2569                                exporter->SetFilled();
2570                        }
2571
2572                        if (mExportGeometry)
2573                        {
2574                                exporter->ExportGeometry(objects);
2575                        }
2576
2577                        // export rays
2578                        if (mExportRays)
2579                        {
2580                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2581                        }
2582
2583                        ExportViewCellsForViz(exporter);
2584                        delete exporter;
2585                        cout << "finished" << endl;
2586                }
2587        }
2588
2589        if (1)
2590        {
2591                cout << "exporting depth map ... ";
2592
2593                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2594                if (exporter)
2595                {
2596                        if (1)
2597                        {
2598                                exporter->SetWireframe();
2599                                exporter->ExportBox(mViewSpaceBox);
2600                                exporter->SetFilled();
2601                        }
2602
2603                        if (mExportGeometry)
2604                        {
2605                                exporter->ExportGeometry(objects);
2606                        }
2607
2608                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
2609
2610                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2611
2612                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2613                        {
2614                                ViewCell *vc = *vit;
2615
2616                                ViewCellContainer leaves;
2617                                mViewCellsTree->CollectLeaves(vc, leaves);
2618
2619                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2620
2621                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2622                                {
2623                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2624
2625                                        Material m;
2626
2627                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
2628                                        m.mDiffuseColor.r = relDepth;
2629                                        m.mDiffuseColor.g = 0.0f;
2630                                        m.mDiffuseColor.b = 1.0f - relDepth;
2631
2632                    exporter->SetForcedMaterial(m);
2633                               
2634
2635                                        BspNodeGeometry geom;
2636                                        mVspBspTree->ConstructGeometry(leaf, geom);
2637                                        exporter->ExportPolygons(geom.mPolys);
2638                                }
2639                        }
2640
2641                        delete exporter;
2642                }
2643
2644
2645                cout << "finished" << endl;
2646        }
2647
2648        //-- visualization of the BSP splits
2649        bool exportSplits = false;
2650        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2651
2652        if (exportSplits)
2653        {
2654                cout << "exporting splits ... ";
2655                ExportSplits(objects, visRays);
2656                cout << "finished" << endl;
2657        }
2658
2659        //-- export single view cells
2660        ExportBspPvs(objects, visRays);
2661}
2662
2663
2664void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2665                                                                                  const VssRayContainer &rays)
2666{
2667        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2668
2669        if (exporter)
2670        {
2671                Material m;
2672                m.mDiffuseColor = RgbColor(1, 0, 0);
2673                exporter->SetForcedMaterial(m);
2674                exporter->SetWireframe();
2675
2676                exporter->ExportBspSplits(*mVspBspTree, true);
2677
2678                // take forced material, else big scenes cannot be viewed
2679                m.mDiffuseColor = RgbColor(0, 1, 0);
2680                exporter->SetForcedMaterial(m);
2681                exporter->SetFilled();
2682
2683                exporter->ResetForcedMaterial();
2684
2685                // export rays
2686                if (mExportRays)
2687                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
2688
2689                if (mExportGeometry)
2690                        exporter->ExportGeometry(objects);
2691
2692                delete exporter;
2693        }
2694}
2695
2696
2697void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2698                                                                                  const VssRayContainer &rays)
2699{
2700        const int leafOut = 10;
2701
2702        ViewCell::NewMail();
2703
2704        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2705        Debug << "\nOutput view cells: " << endl;
2706
2707        // sort view cells to visualize the largest view cells
2708#if 0
2709        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2710#endif
2711        int limit = min(leafOut, (int)mViewCells.size());
2712
2713#if 1
2714        //-- some rays for output
2715        const int raysOut = min((int)rays.size(), mVisualizationSamples);
2716
2717#endif
2718
2719        for (int i = 0; i < limit; ++ i)
2720        {
2721                cout << "creating output for view cell " << i << " ... ";
2722
2723                VssRayContainer vcRays;
2724                Intersectable::NewMail();
2725                ViewCell *vc;
2726       
2727                if (0) // largest view cell pvs first
2728                        vc = mViewCells[i];
2729                else
2730                        vc = mViewCells[Random((int)mViewCells.size())];
2731
2732        if (1)
2733                {
2734                        // check whether we can add the current ray to the output rays
2735                        for (int k = 0; k < raysOut; ++ k)
2736                        {
2737                                VssRay *ray = rays[k];
2738                                for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
2739                                {
2740                                        ViewCell *rayvc = ray->mViewCells[j];
2741#if VC_HISTORY
2742                                        BspLeaf *leaf = rayvc->mLeaf;
2743                                        if (vc == rayvc)
2744                                                vcRays.push_back(ray);
2745#endif
2746                                }
2747                        }
2748                }
2749
2750                //bspLeaves[j]->Mail();
2751                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2752                Exporter *exporter = Exporter::GetExporter(s);
2753                exporter->SetWireframe();
2754
2755                Material m;//= RandomMaterial();
2756                m.mDiffuseColor = RgbColor(0, 1, 0);
2757                exporter->SetForcedMaterial(m);
2758
2759                ExportViewCellGeometry(exporter, vc);
2760
2761
2762                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
2763                          << ", piercing rays=" << (int)vcRays.size() << endl;
2764                        //  << ", leaves=" << (int)vc->mLeaves.size() << endl;
2765
2766               
2767                //-- export rays piercing this view cell
2768                if (1)
2769                {
2770                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2771                }
2772                else
2773                {
2774
2775                        ViewCellContainer leaves;
2776                        mViewCellsTree->CollectLeaves(vc, leaves);
2777
2778                        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2779
2780                        for (lit = leaves.begin(); lit != lit_end; ++ lit)
2781                        {
2782                                BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2783                                exporter->ExportRays(l->mVssRays);
2784                        }
2785                }
2786
2787       
2788                m.mDiffuseColor = RgbColor(1, 0, 0);
2789                exporter->SetForcedMaterial(m);
2790
2791                ObjectPvsMap::const_iterator it,
2792                        it_end = vc->GetPvs().mEntries.end();
2793
2794                exporter->SetFilled();
2795
2796       
2797                // output PVS of view cell
2798                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2799                {
2800               
2801                        Intersectable *intersect = (*it).first;
2802
2803                        if (!intersect->Mailed())
2804                        {
2805                                Material m = RandomMaterial();
2806                                exporter->SetForcedMaterial(m);
2807
2808                                exporter->ExportIntersectable(intersect);
2809                                intersect->Mail();
2810                        }
2811                }
2812
2813               
2814                DEL_PTR(exporter);
2815                cout << "finished" << endl;
2816        }
2817
2818        Debug << endl;
2819}
2820
2821
2822int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2823                                                                                        const Vector3 &termination,
2824                                                                                        ViewCellContainer &viewcells)
2825{
2826        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
2827}
2828
2829
2830void VspBspViewCellsManager::ExportColor(Exporter *exporter,
2831                                                                                 ViewCell *vc) const
2832{
2833        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
2834
2835        float importance = 0;
2836        static Material m;
2837
2838        switch (mColorCode)
2839        {
2840        case 0: // Random
2841                {
2842                        if (vcValid)
2843                        {
2844                                m = RandomMaterial();
2845                        }
2846                        else
2847                        {
2848                                m.mDiffuseColor.r = 0.0f;
2849                                m.mDiffuseColor.g = 1.0f;
2850                                m.mDiffuseColor.b = 0.0f;
2851                        }
2852                }
2853                return;
2854        case 1: // pvs
2855                {
2856                        importance = (float)vc->GetPvs().GetSize() /
2857                                (float)mViewCellsStats.maxPvs;
2858
2859                }
2860                break;
2861        case 2: // merges
2862                {
2863            int lSize = mViewCellsTree->GetSize(vc);
2864       
2865                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
2866                }
2867                break;
2868        case 3: // merge tree differene
2869                {
2870                        importance = (float)GetMaxTreeDiff(vc) /
2871                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2872
2873                }
2874                break;
2875        default:
2876                break;
2877        }
2878
2879        // special color code for invalid view cells
2880        m.mDiffuseColor.r = importance;
2881        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2882        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
2883
2884        //Debug << "importance: " << importance << endl;
2885        exporter->SetForcedMaterial(m);
2886}
2887
2888
2889void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2890                                                                                          ViewCell *vc) const
2891{
2892        if (vc->GetMesh())
2893        {
2894                exporter->ExportMesh(vc->GetMesh());
2895                return;
2896        }
2897
2898        BspNodeGeometry geom;
2899        mVspBspTree->ConstructGeometry(vc, geom);
2900        exporter->ExportPolygons(geom.mPolys);
2901}
2902
2903
2904int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
2905{
2906        ViewCellContainer leaves;
2907        mViewCellsTree->CollectLeaves(vc, leaves);
2908
2909        int maxDist = 0;
2910       
2911        // compute max height difference
2912        for (int i = 0; i < (int)leaves.size(); ++ i)
2913                for (int j = 0; j < (int)leaves.size(); ++ j)
2914        {
2915                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
2916
2917                if (i != j)
2918                {
2919                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
2920                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
2921                        if (dist > maxDist)
2922                                maxDist = dist;
2923                }
2924        }
2925
2926        return maxDist;
2927}
2928
2929
2930ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
2931{
2932        if (!mVspBspTree)
2933                return NULL;
2934
2935        if (!mViewSpaceBox.IsInside(point))
2936          return NULL;
2937
2938        return mVspBspTree->GetViewCell(point);
2939}
2940
2941
2942void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
2943{
2944        if (vc->GetMesh())
2945                delete vc->GetMesh();
2946
2947        BspNodeGeometry geom;
2948       
2949        mVspBspTree->ConstructGeometry(vc, geom);
2950
2951        Mesh *mesh = new Mesh();
2952        geom.AddToMesh(*mesh);
2953        vc->SetMesh(mesh);
2954        mMeshContainer.push_back(mesh);
2955}
2956
2957
2958ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
2959                                                                                                  ObjectContainer *objects)
2960{
2961        ViewCellsParser parser;
2962
2963        ViewCellsManager *vm = NULL;
2964
2965        if (parser.ParseFile(filename, &vm, objects))
2966        {
2967                vm->PrepareLoadedViewCells();
2968                vm->ResetViewCells();
2969
2970                vm->mViewCellsFinished = true;
2971                vm->mMaxPvsSize = (int)objects->size();
2972
2973                vm->FinalizeViewCells(true);
2974
2975                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
2976
2977                //vm->ExportViewCells("test.xml");
2978        }
2979        else
2980        {
2981                Debug << "failed loading view cells" << endl;
2982                DEL_PTR(vm);
2983        }
2984
2985
2986        return vm;
2987}
2988
2989
2990inline bool ilt(Intersectable *obj1, Intersectable *obj2)
2991{
2992        return obj1->mId < obj2->mId;
2993}
2994
2995
2996bool VspBspViewCellsManager::ExportViewCells(const string filename)
2997{
2998        cout << "exporting view cells to xml ... ";
2999        std::ofstream stream;
3000
3001        // for output we need unique ids for each view cell
3002        //CreateUniqueViewCellIds();
3003
3004        stream.open(filename.c_str());
3005        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3006        stream << "<Visibility_Solution>" << endl;
3007
3008        //-- the view space bounding box
3009        stream << "<ViewSpaceBox"
3010                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3011                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3012
3013        //-- the type of the view cells hierarchy
3014        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3015
3016        //-- load the view cells itself, i.e., the ids and the pvs
3017        stream << "<ViewCells>" << endl;
3018        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3019        for (it = mViewCells.begin(); it != it_end; ++ it)
3020                ExportViewCell(*it, stream);
3021
3022        stream << "</ViewCells>" << endl;
3023
3024        //-- load the hierarchy
3025        stream << "<BspTree>" << endl;
3026        mVspBspTree->Export(stream);
3027        stream << endl << "</BspTree>" << endl;
3028
3029        stream << "</Visibility_Solution>" << endl;
3030        stream.close();
3031
3032        cout << "finished" << endl;
3033
3034        return true;
3035}
3036
3037
3038int VspBspViewCellsManager::CastBeam(Beam &beam)
3039{
3040        return mVspBspTree->CastBeam(beam);
3041}
3042
3043
3044void VspBspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
3045{
3046        CreateMesh(viewCell);
3047
3048        float area = 0;
3049        float volume = 0;
3050
3051        ViewCellContainer leaves;
3052        mViewCellsTree->CollectLeaves(viewCell, leaves);
3053
3054        ViewCellContainer::const_iterator it, it_end = leaves.end();
3055
3056        for (it = leaves.begin(); it != it_end; ++ it)
3057        {
3058                BspNodeGeometry geom;
3059                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3060                mVspBspTree->ConstructGeometry(leaf, geom);
3061
3062                area += geom.GetArea();
3063                volume += geom.GetVolume();
3064        }
3065
3066        viewCell->SetVolume(volume);
3067        viewCell->SetArea(area);
3068}
3069
3070
3071void VspBspViewCellsManager::PrepareLoadedViewCells()
3072{
3073        // TODO: do I still need this here?
3074        mVspBspTree->RepairViewCellsLeafLists();
3075}
3076
3077
3078
3079void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3080                                                                                                        vector<MergeCandidate> &candidates)
3081{       
3082        cout << "collecting merge candidates ... " << endl;
3083
3084        if (mUseRaysForMerge)
3085        {
3086                mVspBspTree->CollectMergeCandidates(rays, candidates);
3087        }
3088        else
3089        {
3090                vector<BspLeaf *> leaves;
3091                mVspBspTree->CollectLeaves(leaves);
3092                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3093        }
3094
3095        cout << "fininshed collecting candidates" << endl;
3096}
3097
3098
3099
3100//////////////////////////////////
3101ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3102{
3103        //TODO
3104        return NULL;// new VspBspViewCellsManager();
3105}
3106
Note: See TracBrowser for help on using the repository browser.