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

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