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

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