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

Revision 594, 77.8 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       
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.useCuttingPlane", 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        if (mMergeViewCells)
1156        {
1157                cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1158                long startTime = GetTime();
1159       
1160                VssRayContainer postProcessRays;
1161                GetRaySets(rays, mPostProcessSamples, postProcessRays);
1162
1163                merged = mViewCellsTree->ConstructMergeTree(rays, objects);
1164
1165                //-- stats and visualizations
1166                cout << "finished" << endl;
1167                cout << "merged " << merged << " view cells in "
1168                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1169
1170                Debug << "Postprocessing: Merged " << merged << " view cells in "
1171                        << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
1172                        << "using " << (int)rays.size() << " samples" << endl << endl;
1173        }
1174
1175        // reset view cells and stats
1176        ResetViewCells();
1177        FinalizeViewCells(true);
1178       
1179        // HACK: removes view cells in bsp leaves with active ones
1180        if (0)
1181                AddCurrentViewCellsToHierarchy();
1182
1183        // write view cells to disc
1184        if (mExportViewCells)
1185        {
1186                char buff[100];
1187                environment->GetStringValue("ViewCells.filename", buff);
1188                string vcFilename(buff);
1189
1190                ExportViewCells(buff);
1191        }
1192
1193        return merged;
1194}
1195
1196
1197BspViewCellsManager::~BspViewCellsManager()
1198{
1199}
1200
1201
1202int BspViewCellsManager::GetType() const
1203{
1204        return BSP;
1205}
1206
1207
1208void BspViewCellsManager::Visualize(const ObjectContainer &objects,
1209                                                                        const VssRayContainer &sampleRays)
1210{
1211        if (!ViewCellsConstructed())
1212                return;
1213       
1214        //BspLeaf::NewMail();
1215        if (1) // export merged view cells
1216        {
1217
1218                cout << "reseting view cells ... ";
1219                ResetViewCells();
1220
1221                cout << "finished" << endl;
1222
1223                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1224                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
1225
1226                cout << "exporting view cells after merge ... ";
1227
1228                if (exporter)
1229                {
1230                        if (0)
1231                                exporter->SetWireframe();
1232                        else
1233                                exporter->SetFilled();
1234
1235                        ExportViewCellsForViz(exporter);
1236
1237                        if (mExportGeometry)
1238                        {
1239                                Material m;
1240                                m.mDiffuseColor = RgbColor(0, 1, 0);
1241                                exporter->SetForcedMaterial(m);
1242                                exporter->SetFilled();
1243
1244                                exporter->ExportGeometry(objects);
1245                        }
1246
1247                        delete exporter;
1248                }
1249                cout << "finished" << endl;
1250        }
1251
1252        //-- visualization of the BSP splits
1253        bool exportSplits = false;
1254        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1255
1256        if (exportSplits)
1257        {
1258                cout << "exporting splits ... ";
1259                ExportSplits(objects);
1260                cout << "finished" << endl;
1261        }
1262
1263        ExportBspPvs(objects);
1264}
1265
1266
1267inline bool vc_gt(ViewCell *a, ViewCell *b)
1268{
1269        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1270}
1271
1272
1273void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
1274{
1275        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1276
1277        if (exporter)
1278        {
1279                Material m;
1280                m.mDiffuseColor = RgbColor(1, 0, 0);
1281                exporter->SetForcedMaterial(m);
1282                exporter->SetWireframe();
1283
1284                exporter->ExportBspSplits(*mBspTree, true);
1285
1286                //NOTE: take forced material, else big scenes cannot be viewed
1287                m.mDiffuseColor = RgbColor(0, 1, 0);
1288                exporter->SetForcedMaterial(m);
1289                //exporter->ResetForcedMaterial();
1290
1291                exporter->SetFilled();
1292
1293                if (mExportGeometry)
1294                        exporter->ExportGeometry(objects);
1295
1296                delete exporter;
1297        }
1298}
1299
1300
1301void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
1302{
1303        const int leafOut = 10;
1304
1305        ViewCell::NewMail();
1306
1307        //-- some rays for output
1308        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
1309
1310        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1311        Debug << "\nOutput view cells: " << endl;
1312
1313        // sort view cells to get largest view cells
1314        if (0)
1315                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1316
1317        int limit = min(leafOut, (int)mViewCells.size());
1318
1319        for (int i = 0; i < limit; ++ i)
1320        {
1321                cout << "creating output for view cell " << i << " ... ";
1322                VssRayContainer vcRays;
1323                Intersectable::NewMail();
1324                ViewCell *vc;
1325
1326                if (0)
1327                        vc = mViewCells[i];
1328                else
1329                        vc = mViewCells[Random((int)mViewCells.size())];
1330
1331                cout << "creating output for view cell " << i << " ... ";
1332
1333                if(0)
1334                {
1335                        // check whether we can add the current ray to the output rays
1336                        for (int k = 0; k < raysOut; ++ k)
1337                        {
1338                                BspRay *ray = mBspRays[k];
1339                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1340                                {
1341                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1342                                        if (vc == leaf->GetViewCell())
1343                                                vcRays.push_back(ray->vssRay);
1344                                }
1345                        }
1346                }
1347
1348                //bspLeaves[j]->Mail();
1349                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1350
1351                Exporter *exporter = Exporter::GetExporter(s);
1352
1353                exporter->SetWireframe();
1354
1355                Material m;//= RandomMaterial();
1356                m.mDiffuseColor = RgbColor(0, 1, 0);
1357                exporter->SetForcedMaterial(m);
1358
1359                ExportViewCellGeometry(exporter, vc);
1360               
1361
1362                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
1363                          << ", piercing rays=" << (int)vcRays.size() << endl;
1364                         // << ", leaves=" << (int)vc->mLeaves.size() << endl;
1365
1366
1367                // export rays piercing this view cell
1368                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1369
1370                m.mDiffuseColor = RgbColor(1, 0, 0);
1371                exporter->SetForcedMaterial(m);
1372
1373                ObjectPvsMap::const_iterator it,
1374                        it_end = vc->GetPvs().mEntries.end();
1375
1376                exporter->SetFilled();
1377
1378                // output PVS of view cell
1379                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1380                {
1381                        Intersectable *intersect = (*it).first;
1382
1383                        if (!intersect->Mailed())
1384                        {
1385                                Material m = RandomMaterial();
1386                                exporter->SetForcedMaterial(m);
1387
1388                                exporter->ExportIntersectable(intersect);
1389                                intersect->Mail();
1390                        }
1391                }
1392
1393                DEL_PTR(exporter);
1394                cout << "finished" << endl;
1395        }
1396
1397        Debug << endl;
1398}
1399
1400
1401void BspViewCellsManager::ExportColor(Exporter *exporter,
1402                                                                          ViewCell *vc) const
1403{
1404        if (mColorCode == 0) // Random color
1405        {
1406                exporter->ResetForcedMaterial();
1407                return;
1408        }
1409
1410        float importance = 0;
1411
1412        switch (mColorCode)
1413        {
1414        case 1: // pvs
1415                {
1416                        importance = (float)vc->GetPvs().GetSize() /
1417                                (float)mViewCellsStats.maxPvs;
1418                }
1419                break;
1420        case 2: // merges
1421                {
1422                        importance = (float)mViewCellsTree->GetSize(vc) /
1423                                (float)mViewCellsStats.maxLeaves;
1424                }
1425                break;
1426        case 3: // merge tree differene
1427                {
1428                        // TODO
1429                }
1430                break;
1431        default:
1432                break;
1433        }
1434
1435        Material m;
1436        m.mDiffuseColor.b = 1.0f;
1437        m.mDiffuseColor.r = importance;
1438        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1439
1440        exporter->SetForcedMaterial(m);
1441}
1442
1443
1444void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1445                                                                                                 ViewCell *vc,
1446                                                                                                 const Plane3 *cuttingPlane) const
1447{
1448        if (vc->GetMesh())
1449        {
1450                exporter->ExportMesh(vc->GetMesh());
1451       
1452                return;
1453        }
1454
1455        BspNodeGeometry geom;
1456        mBspTree->ConstructGeometry(vc, geom);
1457
1458
1459        if (cuttingPlane)
1460        {
1461                BspNodeGeometry front;
1462                BspNodeGeometry back;
1463
1464                geom.SplitGeometry(front,
1465                                                   back,
1466                                                   *cuttingPlane,
1467                                                   mViewSpaceBox,
1468                                                   0.005);
1469
1470                exporter->ExportPolygons(back.mPolys);
1471        }
1472        else
1473        {
1474                exporter->ExportPolygons(geom.mPolys);
1475        }
1476}
1477
1478
1479void BspViewCellsManager::CreateMesh(ViewCell *vc)
1480{
1481        if (vc->GetMesh())
1482                delete vc->GetMesh();
1483
1484        BspNodeGeometry geom;
1485       
1486        mBspTree->ConstructGeometry(vc, geom);
1487
1488        Mesh *mesh = new Mesh();
1489        geom.AddToMesh(*mesh);
1490        vc->SetMesh(mesh);
1491        mMeshContainer.push_back(mesh);
1492}
1493
1494
1495void BspViewCellsManager::Finalize(ViewCell *viewCell,
1496                                                                   const bool createMesh)
1497{
1498        CreateMesh(viewCell);
1499
1500        float area = 0;
1501        float volume = 0;
1502
1503        ViewCellContainer leaves;
1504        mViewCellsTree->CollectLeaves(viewCell, leaves);
1505
1506        ViewCellContainer::const_iterator it, it_end = leaves.end();
1507
1508        for (it = leaves.begin(); it != it_end; ++ it)
1509        {
1510                BspNodeGeometry geom;
1511                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
1512                mBspTree->ConstructGeometry(leaf, geom);
1513
1514                area += geom.GetArea();
1515                volume += geom.GetVolume();
1516        }
1517
1518        viewCell->SetVolume(volume);
1519        viewCell->SetArea(area);
1520}
1521
1522
1523ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
1524{
1525        if (!mBspTree)
1526                return NULL;
1527
1528        if (!mViewSpaceBox.IsInside(point))
1529                return NULL;
1530       
1531        return mBspTree->GetViewCell(point);
1532}
1533
1534
1535void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1536                                                                                                 vector<MergeCandidate> &candidates)
1537{
1538        cout << "collecting merge candidates ... " << endl;
1539
1540        if (mUseRaysForMerge)
1541        {
1542                mBspTree->CollectMergeCandidates(rays, candidates);
1543        }
1544        else
1545        {
1546                vector<BspLeaf *> leaves;
1547                mBspTree->CollectLeaves(leaves);
1548                mBspTree->CollectMergeCandidates(leaves, candidates);
1549        }
1550
1551        cout << "fininshed collecting candidates" << endl;
1552}
1553
1554
1555
1556bool BspViewCellsManager::ExportViewCells(const string filename)
1557{
1558        cout << "exporting view cells to xml ... ";
1559        std::ofstream stream;
1560
1561        // for output we need unique ids for each view cell
1562        CreateUniqueViewCellIds();
1563
1564
1565        stream.open(filename.c_str());
1566        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
1567        stream << "<Visibility_Solution>" << endl;
1568
1569        //-- the view space bounding box
1570        stream << "<ViewSpaceBox"
1571                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
1572                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
1573
1574        //-- the type of the view cells hierarchy
1575        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
1576        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
1577        //-- load the view cells itself, i.e., the ids and the pvs
1578        stream << "<ViewCells>" << endl;
1579        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1580        for (it = mViewCells.begin(); it != it_end; ++ it)
1581                ExportViewCell(*it, stream);
1582
1583        stream << "</ViewCells>" << endl;
1584
1585        //-- load the hierarchy
1586        stream << "<Hierarchy>" << endl;
1587        mBspTree->Export(stream);
1588        stream << endl << "</Hierarchy>" << endl;
1589
1590        stream << "</Visibility_Solution>" << endl;
1591        stream.close();
1592
1593        cout << "finished" << endl;
1594
1595        return true;
1596}
1597
1598
1599void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
1600{
1601        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1602        for (it = mViewCells.begin(); it != it_end; ++ it)
1603        {
1604                ViewCell *vc = *it;
1605                ViewCellContainer leaves;
1606                mViewCellsTree->CollectLeaves(vc, leaves);
1607               
1608                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
1609
1610                for (lit = leaves.begin(); lit != lit_end; ++ lit)
1611                {
1612                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
1613                        bspVc->mLeaf->SetViewCell(vc);
1614                }
1615        }
1616}
1617
1618/************************************************************************/
1619/*                   KdViewCellsManager implementation                  */
1620/************************************************************************/
1621
1622
1623
1624KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
1625ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
1626{
1627}
1628
1629float KdViewCellsManager::GetProbability(ViewCell *viewCell)
1630{
1631        // compute view cell area / volume as subsititute for probability
1632#if 0
1633        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1634#endif
1635#if 1
1636        return GetArea(viewCell) / GetAccVcArea();
1637#endif
1638#if 0
1639        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1640#endif
1641}
1642
1643
1644float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1645{
1646        return viewCell->GetPvs().GetSize() * objRendercost;
1647}
1648
1649
1650void KdViewCellsManager::CollectViewCells()
1651{
1652        //mKdTree->CollectViewCells(mViewCells); TODO
1653}
1654
1655
1656int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1657                                                                  const VssRayContainer &rays)
1658{
1659        // if view cells already constructed
1660        if (ViewCellsConstructed())
1661                return 0;
1662
1663        mKdTree->Construct();
1664
1665        mTotalAreaValid = false;
1666        // create the view cells
1667        mKdTree->CreateAndCollectViewCells(mViewCells);
1668
1669        // cast rays
1670        ComputeSampleContributions(rays, true, false);
1671
1672        EvaluateViewCellsStats();
1673        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1674
1675        return 0;
1676}
1677
1678
1679bool KdViewCellsManager::ViewCellsConstructed() const
1680{
1681        return mKdTree->GetRoot() != NULL;
1682}
1683
1684int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1685                                                                        const VssRayContainer &rays)
1686{
1687        return 0;
1688}
1689
1690void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1691                                                                   const VssRayContainer &sampleRays)
1692{
1693        if (!ViewCellsConstructed())
1694                return;
1695
1696        // using view cells instead of the kd PVS of objects
1697        const bool useViewCells = true;
1698        bool exportRays = false;
1699
1700        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1701        const int pvsOut = min((int)objects.size(), 10);
1702        VssRayContainer *rays = new VssRayContainer[pvsOut];
1703
1704        if (useViewCells)
1705        {
1706                const int leafOut = 10;
1707
1708                ViewCell::NewMail();
1709
1710                //-- some rays for output
1711                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1712                Debug << "visualization using " << raysOut << " samples" << endl;
1713
1714                //-- some random view cells and rays for output
1715                vector<KdLeaf *> kdLeaves;
1716
1717                for (int i = 0; i < leafOut; ++ i)
1718                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1719
1720                for (int i = 0; i < kdLeaves.size(); ++ i)
1721                {
1722                        KdLeaf *leaf = kdLeaves[i];
1723                        RayContainer vcRays;
1724
1725                        cout << "creating output for view cell " << i << " ... ";
1726#if 0
1727                        // check whether we can add the current ray to the output rays
1728                        for (int k = 0; k < raysOut; ++ k)
1729                        {
1730                                Ray *ray = sampleRays[k];
1731
1732                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1733                                {
1734                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1735
1736                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1737                                        {
1738                                                vcRays.push_back(ray);
1739                                        }
1740                                }
1741                        }
1742#endif
1743                        Intersectable::NewMail();
1744
1745                        ViewCell *vc = leaf->mViewCell;
1746
1747                        //bspLeaves[j]->Mail();
1748                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1749
1750                        Exporter *exporter = Exporter::GetExporter(s);
1751                        exporter->SetFilled();
1752
1753                        exporter->SetWireframe();
1754                        //exporter->SetFilled();
1755
1756                        Material m;//= RandomMaterial();
1757                        m.mDiffuseColor = RgbColor(1, 1, 0);
1758                        exporter->SetForcedMaterial(m);
1759
1760                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1761                        exporter->ExportBox(box);
1762
1763                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1764                                << ", piercing rays=" << (int)vcRays.size() << endl;
1765
1766                        // export rays piercing this view cell
1767                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1768
1769                        m.mDiffuseColor = RgbColor(1, 0, 0);
1770                        exporter->SetForcedMaterial(m);
1771
1772                        // exporter->SetWireframe();
1773                        exporter->SetFilled();
1774
1775                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1776                        // output PVS of view cell
1777                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1778                        {
1779                                Intersectable *intersect = (*it).first;
1780                                if (!intersect->Mailed())
1781                                {
1782                                        exporter->ExportIntersectable(intersect);
1783                                        intersect->Mail();
1784                                }
1785                        }
1786
1787                        DEL_PTR(exporter);
1788                        cout << "finished" << endl;
1789                }
1790
1791                DEL_PTR(rays);
1792        }
1793        else // using kd PVS of objects
1794        {
1795                for (int i = 0; i < limit; ++ i)
1796                {
1797                        VssRay *ray = sampleRays[i];
1798
1799                        // check whether we can add this to the rays
1800                        for (int j = 0; j < pvsOut; j++)
1801                        {
1802                                if (objects[j] == ray->mTerminationObject)
1803                                {
1804                                        rays[j].push_back(ray);
1805                                }
1806                        }
1807                }
1808
1809                if (exportRays)
1810                {
1811                        Exporter *exporter = NULL;
1812                        exporter = Exporter::GetExporter("sample-rays.x3d");
1813                        exporter->SetWireframe();
1814                        exporter->ExportKdTree(*mKdTree);
1815
1816                        for (i=0; i < pvsOut; i++)
1817                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1818
1819                        exporter->SetFilled();
1820
1821                        delete exporter;
1822                }
1823
1824                for (int k=0; k < pvsOut; k++)
1825                {
1826                        Intersectable *object = objects[k];
1827                        char s[64];
1828                        sprintf(s, "sample-pvs%04d.x3d", k);
1829
1830                        Exporter *exporter = Exporter::GetExporter(s);
1831                        exporter->SetWireframe();
1832
1833                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1834                        Intersectable::NewMail();
1835
1836                        // avoid adding the object to the list
1837                        object->Mail();
1838                        ObjectContainer visibleObjects;
1839
1840                        for (; i != object->mKdPvs.mEntries.end(); i++)
1841                        {
1842                                KdNode *node = (*i).first;
1843                                exporter->ExportBox(mKdTree->GetBox(node));
1844
1845                                mKdTree->CollectObjects(node, visibleObjects);
1846                        }
1847
1848                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1849                        exporter->SetFilled();
1850
1851                        for (int j = 0; j < visibleObjects.size(); j++)
1852                                exporter->ExportIntersectable(visibleObjects[j]);
1853
1854                        Material m;
1855                        m.mDiffuseColor = RgbColor(1, 0, 0);
1856                        exporter->SetForcedMaterial(m);
1857                        exporter->ExportIntersectable(object);
1858
1859                        delete exporter;
1860                }
1861        }
1862}
1863
1864
1865void KdViewCellsManager::ExportColor(Exporter *exporter,
1866                                                                         ViewCell *vc) const
1867{
1868        // TODO
1869}
1870
1871ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1872{
1873        return new KdViewCell(mesh);
1874}
1875
1876
1877void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1878                                                                                                ViewCell *vc,
1879                                                                                                const Plane3 *cuttingPlane) const
1880{
1881        ViewCellContainer leaves;
1882
1883        mViewCellsTree->CollectLeaves(vc, leaves);
1884        ViewCellContainer::const_iterator it, it_end = leaves.end();
1885
1886        for (it = leaves.begin(); it != it_end; ++ it)
1887        {
1888                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
1889       
1890                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
1891        }
1892}
1893
1894
1895int KdViewCellsManager::GetType() const
1896{
1897        return ViewCellsManager::KD;
1898}
1899
1900
1901
1902KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1903{
1904        KdNode *node = leaf;
1905
1906        while (node->mParent && node->mDepth > mKdPvsDepth)
1907                node = node->mParent;
1908        return node;
1909}
1910
1911int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1912                                                                                const Vector3 &termination,
1913                                                                                ViewCellContainer &viewcells)
1914{
1915        return mKdTree->CastLineSegment(origin, termination, viewcells);
1916}
1917
1918
1919void KdViewCellsManager::CreateMesh(ViewCell *vc)
1920{
1921        // TODO
1922}
1923
1924
1925
1926void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1927                                                                                                vector<MergeCandidate> &candidates)
1928{
1929        // TODO
1930}
1931
1932
1933/**********************************************************************/
1934/*                   VspKdViewCellsManager implementation             */
1935/**********************************************************************/
1936
1937
1938VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
1939ViewCellsManager(), mVspKdTree(vspKdTree)
1940{
1941        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
1942        mVspKdTree->SetViewCellsManager(this);
1943}
1944
1945float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
1946{
1947        // volume or area substitutes for view point probability
1948#if 0
1949        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1950#else
1951        return GetArea(viewCell) / GetAccVcArea();
1952#endif
1953}
1954
1955
1956float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1957{
1958        return viewCell->GetPvs().GetSize() * objRendercost;
1959}
1960
1961
1962void VspKdViewCellsManager::CollectViewCells()
1963{
1964        mVspKdTree->CollectViewCells(mViewCells);
1965}
1966
1967
1968int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1969                                                                                                const VssRayContainer &rays)
1970{
1971        // if view cells already constructed
1972        if (ViewCellsConstructed())
1973                return 0;
1974
1975        VssRayContainer constructionRays;
1976        VssRayContainer savedRays;
1977
1978        GetRaySets(rays,
1979                           mInitialSamples,
1980                           constructionRays,
1981                           &savedRays);
1982
1983        Debug << "constructing vsp kd tree using "
1984                  << (int)constructionRays.size() << " samples" << endl;
1985
1986        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
1987        Debug << mVspKdTree->GetStatistics() << endl;
1988
1989        // export leaf building blocks
1990        ExportLeaves(objects, rays);
1991
1992        // finally merge kd leaf building blocks to view cells
1993        const int merged = mVspKdTree->MergeViewCells(rays);
1994
1995        // collapse siblings belonging to the same view cell
1996        mVspKdTree->RefineViewCells(rays);
1997
1998        // collapse siblings belonging to the same view cell
1999        mVspKdTree->CollapseTree();
2000
2001        // evaluale view cell stats
2002        ResetViewCells();
2003
2004        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2005
2006        long startTime = GetTime();
2007        // recast rest of rays
2008        ComputeSampleContributions(savedRays, true, false);
2009
2010        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2011                  << " secs" << endl;
2012
2013        return merged;
2014}
2015
2016bool VspKdViewCellsManager::ViewCellsConstructed() const
2017{
2018        return mVspKdTree->GetRoot() != NULL;
2019}
2020
2021
2022ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2023{
2024        return new VspKdViewCell(mesh);
2025}
2026
2027int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
2028                                                                           const VssRayContainer &rays)
2029{
2030        if (!ViewCellsConstructed())
2031                return 0;
2032
2033        // recalculate stats
2034        EvaluateViewCellsStats();
2035
2036        return 0;
2037}
2038
2039
2040void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2041                                                                                 const VssRayContainer &sampleRays)
2042{
2043        if (!ViewCellsConstructed())
2044                return;
2045
2046        //-- export leaf building blocks
2047        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
2048        if (!exporter)
2049                return;
2050
2051        //exporter->SetWireframe();
2052        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2053        exporter->ExportVspKdTree(*mVspKdTree);
2054
2055        if (mExportGeometry)
2056                exporter->ExportGeometry(objects);
2057
2058        if (mExportRays)
2059        {
2060                const float prob = (float)mVisualizationSamples
2061                        / ((float)sampleRays.size() + Limits::Small);
2062
2063                exporter->SetWireframe();
2064
2065                //-- collect uniformly distributed rays
2066                VssRayContainer rays;
2067
2068                for (int i = 0; i < sampleRays.size(); ++ i)
2069                {
2070                        if (RandomValue(0,1) < prob)
2071                                rays.push_back(sampleRays[i]);
2072                }
2073                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2074        }
2075
2076        delete exporter;
2077}
2078
2079void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2080                                                                          const VssRayContainer &sampleRays)
2081{
2082        if (!ViewCellsConstructed())
2083                return;
2084
2085        //-- export single view cells
2086        for (int i = 0; i < 10; ++ i)
2087        {
2088                char s[64];
2089                sprintf(s, "vsp_viewcell%04d.x3d", i);
2090                Exporter *exporter = Exporter::GetExporter(s);
2091                const int idx =
2092                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
2093
2094                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
2095
2096                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
2097                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
2098                //-- export geometry
2099                Material m;
2100                m.mDiffuseColor = RgbColor(0, 1, 1);
2101
2102                exporter->SetForcedMaterial(m);
2103                exporter->SetWireframe();
2104
2105                ExportViewCellGeometry(exporter, vc);
2106
2107                //-- export stored rays
2108               
2109                if (mExportRays)
2110                {
2111                        ViewCellContainer leaves;
2112                        mViewCellsTree->CollectLeaves(vc, leaves);
2113
2114                        ViewCellContainer::const_iterator it,
2115                                it_end = leaves.end();
2116
2117                        for (it = leaves.begin(); it != it_end; ++ it)
2118                        {
2119                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2120                                VspKdLeaf *leaf = vspKdVc->mLeaf;
2121                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
2122
2123                                VssRayContainer vssRays;
2124
2125                                VssRayContainer castRays;
2126                                VssRayContainer initRays;
2127
2128                                leaf->GetRays(vssRays);
2129
2130                                VssRayContainer::const_iterator it, it_end = vssRays.end();
2131                                const float prop = 200.0f / (float)vssRays.size();
2132
2133                                for (it = vssRays.begin(); it != it_end; ++ it)
2134                                {
2135                                        if (Random(1) < prop)
2136                                                if ((*it)->mTerminationObject == NULL)
2137                                                        castRays.push_back(*it);
2138                                                else
2139                                                        initRays.push_back(*it);
2140                                }
2141
2142                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2143                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
2144                        }
2145                }
2146       
2147                //-- output PVS of view cell
2148                m.mDiffuseColor = RgbColor(1, 0, 0);
2149                exporter->SetForcedMaterial(m);
2150
2151                Intersectable::NewMail();
2152
2153                ObjectPvsMap::const_iterator it,
2154                        it_end = vc->GetPvs().mEntries.end();
2155
2156                exporter->SetFilled();
2157
2158                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2159                {
2160                        Intersectable *intersect = (*it).first;
2161
2162                        if (!intersect->Mailed())
2163                        {
2164                                Material m = RandomMaterial();
2165                                exporter->SetForcedMaterial(m);
2166
2167                                exporter->ExportIntersectable(intersect);
2168                                intersect->Mail();
2169                        }
2170                }
2171
2172                delete exporter;
2173        }
2174
2175        //-- export final view cells
2176        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2177
2178        //if (exportGeometry) exporter->SetWireframe();
2179        //else exporter->SetFilled();
2180
2181        ExportViewCellsForViz(exporter);
2182
2183        if (mExportGeometry)
2184        {
2185                exporter->SetFilled();
2186                exporter->ExportGeometry(objects);
2187        }
2188
2189        if (mExportRays)
2190        {
2191                const float prob = (float)mVisualizationSamples
2192                        / ((float)sampleRays.size() + Limits::Small);
2193
2194                exporter->SetWireframe();
2195
2196                VssRayContainer rays;
2197
2198                for (int i = 0; i < sampleRays.size(); ++ i)
2199                {
2200                  if (RandomValue(0,1) < prob)
2201                        rays.push_back(sampleRays[i]);
2202                }
2203                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2204        }
2205
2206        delete exporter;
2207}
2208
2209int VspKdViewCellsManager::GetType() const
2210{
2211        return VSP_KD;
2212}
2213
2214
2215int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2216                                                                                   const Vector3 &termination,
2217                                                                                   ViewCellContainer &viewcells)
2218{
2219        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
2220}
2221
2222
2223void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2224                                                                                ViewCell *vc) const
2225{
2226        if (mColorCode == 0) // Random color
2227                return;
2228
2229        float importance = 0;
2230
2231        switch (mColorCode)
2232        {
2233        case 1: // pvs
2234                {
2235                        importance = (float)vc->GetPvs().GetSize() /
2236                                (float)mViewCellsStats.maxPvs;
2237                }
2238                break;
2239        case 2: // merged leaves
2240                {
2241                int lSize = mViewCellsTree->GetSize(vc);
2242                        importance = (float)lSize /
2243                                (float)mViewCellsStats.maxLeaves;
2244                }
2245                break;
2246        case 3: // merged tree depth difference
2247                {
2248                        //importance = (float)GetMaxTreeDiff(vc) /
2249                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2250                }
2251                break;
2252        default:
2253                break;
2254        }
2255
2256        Material m;
2257        m.mDiffuseColor.b = 1.0f;
2258        m.mDiffuseColor.r = importance;
2259        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2260        //Debug << "importance: " << importance << endl;
2261        exporter->SetForcedMaterial(m);
2262}
2263
2264
2265void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2266                                                                                                   ViewCell *vc,
2267                                                                                                   const Plane3 *cuttingPlane) const
2268{
2269        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2270
2271        Mesh m;
2272
2273        ViewCellContainer leaves;
2274        mViewCellsTree->CollectLeaves(vc, leaves);
2275
2276        ViewCellContainer::const_iterator it, it_end = leaves.end();
2277
2278        for (it = leaves.begin(); it != it_end; ++ it)
2279        {
2280                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2281                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
2282        }
2283
2284        exporter->ExportMesh(&m);
2285}
2286
2287
2288void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2289{
2290        //TODO
2291}
2292
2293
2294void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2295                                                                                                   vector<MergeCandidate> &candidates)
2296{
2297        // TODO
2298}
2299
2300
2301/**************************************************************************/
2302/*                   VspBspViewCellsManager implementation                */
2303/**************************************************************************/
2304
2305
2306VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
2307ViewCellsManager(), mVspBspTree(vspBspTree)
2308{
2309        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
2310        mVspBspTree->SetViewCellsManager(this);
2311        mVspBspTree->mViewCellsTree = mViewCellsTree;
2312}
2313
2314
2315VspBspViewCellsManager::~VspBspViewCellsManager()
2316{
2317}
2318
2319
2320float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
2321{
2322        if (0 && mVspBspTree->mUseAreaForPvs)
2323                return GetArea(viewCell) / GetAccVcArea();
2324        else
2325                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
2326}
2327
2328
2329void VspBspViewCellsManager::CollectViewCells()
2330{
2331        // view cells tree constructed
2332        if (!ViewCellsTreeConstructed())
2333        {
2334                mVspBspTree->CollectViewCells(mViewCells, false);
2335        }
2336        else
2337        {
2338                // we can use the view cells tree hierarchy to get the right set
2339                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumMergedViewCells);
2340        }
2341
2342}
2343
2344
2345float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
2346                                                                                        float objRendercost) const
2347{
2348        return viewCell->GetPvs().GetSize() * objRendercost;
2349}
2350
2351
2352bool VspBspViewCellsManager::ViewCellsConstructed() const
2353{
2354        return mVspBspTree->GetRoot() != NULL;
2355}
2356
2357
2358ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2359{
2360        return new BspViewCell(mesh);
2361}
2362
2363
2364int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2365                                                                          const VssRayContainer &rays)
2366{
2367        // if view cells were already constructed
2368        if (ViewCellsConstructed())
2369                return 0;
2370
2371        Debug << "Constructing bsp view cells" << endl;
2372
2373        int sampleContributions = 0;
2374
2375        VssRayContainer sampleRays;
2376
2377        int limit = min (mInitialSamples, (int)rays.size());
2378
2379        VssRayContainer constructionRays;
2380        VssRayContainer savedRays;
2381
2382        Debug << "samples used for subdivision: " << mInitialSamples
2383                  << " rays: " << (int)rays.size() << endl;
2384
2385        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
2386
2387        Debug << "initial rays: " << (int)constructionRays.size() << endl;
2388        Debug << "saved rays: " << (int)savedRays.size() << endl;
2389
2390        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
2391
2392        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
2393
2394        Debug << mVspBspTree->GetStatistics() << endl;
2395
2396        // collapse invalid regions
2397        cout << "collapsing invalid tree regions ... ";
2398        long startTime = GetTime();
2399        int collapsedLeaves = mVspBspTree->CollapseTree();
2400        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
2401                  << " seconds" << endl;
2402
2403    cout << "finished" << endl;
2404
2405        cout << "reseting view cell stats ... ";
2406        ResetViewCells();
2407        cout << "finished" << endl;
2408
2409        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2410
2411        if (1) // export initial view cells
2412        {
2413                cout << "exporting initial view cells (=leaves) ... ";
2414                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
2415
2416                if (exporter)
2417                {
2418                        //exporter->SetWireframe();
2419                        exporter->SetFilled();
2420                        ExportViewCellsForViz(exporter);
2421
2422                        if (0 && mExportRays)
2423                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
2424
2425                        if (mExportGeometry)
2426                                exporter->ExportGeometry(objects);
2427
2428                        delete exporter;
2429                }
2430                cout << "finished" << endl;
2431        }
2432
2433        startTime = GetTime();
2434
2435        // reset view cells and stats
2436        ResetViewCells();
2437
2438        cout << "Computing remaining ray contributions ... ";
2439        // recast rest of rays
2440        ComputeSampleContributions(savedRays, true, false);
2441        cout << "finished" << endl;
2442
2443        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2444                  << " secs" << endl;
2445
2446        cout << "construction finished" << endl;
2447
2448        return sampleContributions;
2449}
2450
2451
2452void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2453                                                                                        const ObjectContainer &objects)
2454{
2455        //-- post processing of bsp view cells
2456    int vcSize = 0;
2457        int pvsSize = 0;
2458
2459        mRenderer->RenderScene();
2460        SimulationStatistics ss;
2461        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2462    Debug << ss << endl;
2463
2464        //-- merge or subdivide view cells
2465        int merged = 0;
2466
2467        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
2468        long startTime = GetTime();
2469
2470       
2471        // TODO: should be done BEFORE the ray casting
2472        merged = mViewCellsTree->ConstructMergeTree(rays, objects);
2473
2474        //-- stats and visualizations
2475        cout << "finished merging" << endl;
2476        cout << "merged " << merged << " view cells in "
2477                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2478
2479        Debug << "Postprocessing: Merged " << merged << " view cells in "
2480                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2481
2482
2483        //BspLeaf::NewMail();
2484        if (1) // export merged view cells
2485        {
2486
2487                cout << "reseting view cells ... ";
2488                ResetViewCells();
2489
2490                cout << "finished" << endl;
2491
2492                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2493                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
2494
2495                cout << "exporting view cells after merge ... ";
2496
2497                if (exporter)
2498                {
2499                        if (0)
2500                                exporter->SetWireframe();
2501                        else
2502                                exporter->SetFilled();
2503                        ExportViewCellsForViz(exporter);
2504
2505                        if (mExportGeometry)
2506                        {
2507                                Material m;
2508                                m.mDiffuseColor = RgbColor(0, 1, 0);
2509                                exporter->SetForcedMaterial(m);
2510                                exporter->SetFilled();
2511
2512                                exporter->ExportGeometry(objects);
2513                        }
2514
2515                        delete exporter;
2516                }
2517                cout << "finished" << endl;
2518        }
2519}
2520
2521
2522void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2523                                                                                         const ObjectContainer &objects)
2524{
2525        Debug << "render time before refine:" << endl;
2526        mRenderer->RenderScene();
2527        SimulationStatistics ss;
2528        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2529    Debug << ss << endl;
2530
2531        cout << "Refining the merged view cells ... ";
2532        long startTime = GetTime();
2533
2534        // refining the merged view cells
2535        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
2536
2537        //-- stats and visualizations
2538        cout << "finished" << endl;
2539        cout << "refined " << refined << " view cells in "
2540                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2541
2542        Debug << "Postprocessing: refined " << refined << " view cells in "
2543                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2544}
2545
2546
2547int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2548                                                                                const VssRayContainer &rays)
2549{
2550        if (!ViewCellsConstructed())
2551        {
2552                Debug << "postprocess error: no view cells constructed" << endl;
2553                return 0;
2554        }
2555
2556
2557        // view cells already finished before post processing step (i.e. because they were loaded)
2558        if (mViewCellsFinished)
2559        {
2560                FinalizeViewCells(true);
2561                EvaluateViewCellsStats();
2562
2563                return 0;
2564        }
2565
2566
2567        // check if new view cells turned invalid
2568        SetValidity(mMinPvsSize, mMaxPvsSize);
2569        // update valid view space according to valid view cells
2570        mVspBspTree->ValidateTree();
2571
2572        // recompute view cell statistics
2573        mViewCellsStats.Reset();
2574        EvaluateViewCellsStats();
2575
2576        // has to be recomputed
2577        mTotalAreaValid = false;
2578
2579
2580        VssRayContainer postProcessRays;
2581        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2582
2583        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
2584
2585        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2586
2587        // should maybe be done here to allow merge working with area or volume
2588        // and to correct the rendering statistics
2589        if (0)
2590        {
2591                FinalizeViewCells(false);
2592        }
2593
2594        if (mMergeViewCells)
2595        {
2596                //-- merge the individual view cells
2597                MergeViewCells(postProcessRays, objects);
2598       
2599
2600                //-- refines the merged view cells
2601                if (0)
2602                        RefineViewCells(postProcessRays, objects);
2603
2604                if (mCompressViewCells)
2605                {
2606                        int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2607                        Debug << "number of entries before compress: " << pvsEntries << endl;
2608
2609                        mViewCellsTree->CompressViewCellsPvs();
2610
2611                        pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2612                        Debug << "number of entries after compress: " << pvsEntries << endl;
2613                }
2614        }
2615
2616        if (1)
2617        {               
2618                float totalCost, erc, var, dev, avg;
2619                int totalpvs;
2620
2621                mViewCellsStats.Reset();
2622
2623        EvaluateRenderStatistics(totalCost, erc, dev, var, totalpvs, avg);
2624               
2625                Debug << "statistics after merge " 
2626                          << " erc: " << erc
2627                          << " dev: " << dev
2628                          << " totalpvs: " << totalpvs
2629                          << " avg: " << avg << endl;
2630        }
2631
2632
2633        //-- export shuffled view cells
2634        if (0)
2635        {
2636                cout << "exporting shuffled view cells ... ";
2637
2638                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2639                if (exporter)
2640                {
2641                        if (1)
2642                        {
2643                                exporter->SetWireframe();
2644                                exporter->ExportBox(mViewSpaceBox);
2645                                exporter->SetFilled();
2646                        }
2647
2648                        if (mExportGeometry)
2649                        {
2650                                exporter->ExportGeometry(objects);
2651                        }
2652
2653                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2654
2655                        Material vm, lm;
2656
2657                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2658                        {
2659                                ViewCell *vc = *vit;
2660
2661                                vm = RandomMaterial();
2662
2663                                lm = vm;
2664
2665                                vm.mDiffuseColor.r -= 0.45f;
2666                                vm.mDiffuseColor.g -= 0.45f;
2667                                vm.mDiffuseColor.b -= 0.45f;
2668
2669
2670                                ViewCellContainer leaves;
2671                                mViewCellsTree->CollectLeaves(vc, leaves);
2672
2673                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2674
2675                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2676                                {
2677                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2678
2679                                        if (leaf->Mailed())
2680                                                exporter->SetForcedMaterial(lm);
2681                                        else
2682                                                exporter->SetForcedMaterial(vm);
2683
2684                                        BspNodeGeometry geom;
2685                                        mVspBspTree->ConstructGeometry(leaf, geom);
2686                                        exporter->ExportPolygons(geom.mPolys);
2687                                }
2688                        }
2689
2690                        delete exporter;
2691                }
2692
2693
2694                cout << "finished" << endl;
2695        }
2696
2697        // collapse sibling leaves that share the same view cell
2698        if (0)
2699                mVspBspTree->CollapseTree();
2700
2701        // recompute view cell list and statistics
2702        ResetViewCells();
2703
2704        // real meshes are only contructed only at this stage
2705        FinalizeViewCells(true);
2706
2707        // HACK: removes view cells in bsp leaves with active ones
2708        if (0)
2709                AddCurrentViewCellsToHierarchy();
2710
2711
2712        // write view cells to disc
2713        if (mExportViewCells)
2714        {
2715                char buff[100];
2716                environment->GetStringValue("ViewCells.filename", buff);
2717                string vcFilename(buff);
2718
2719                ExportViewCells(buff);
2720        }
2721
2722        return 0;
2723}
2724
2725
2726int VspBspViewCellsManager::GetType() const
2727{
2728        return VSP_BSP;
2729}
2730
2731
2732bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2733{
2734        if (!ViewCellsConstructed())
2735                return ViewCellsManager::GetViewPoint(viewPoint);
2736
2737        // TODO: set reasonable limit
2738        const int limit = 20;
2739
2740        for (int i = 0; i < limit; ++ i)
2741        {
2742                viewPoint = mViewSpaceBox.GetRandomPoint();
2743                if (mVspBspTree->ViewPointValid(viewPoint))
2744                {
2745                        return true;
2746                }
2747        }
2748        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2749        return false;
2750}
2751
2752
2753bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2754{
2755  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2756  // validy update in preprocessor for all managers)
2757  return ViewCellsManager::ViewPointValid(viewPoint);
2758
2759  //    return mViewSpaceBox.IsInside(viewPoint) &&
2760  //               mVspBspTree->ViewPointValid(viewPoint);
2761}
2762
2763
2764void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2765                                                                           const VssRayContainer &sampleRays)
2766{
2767        if (!ViewCellsConstructed())
2768                return;
2769
2770        VssRayContainer visRays;
2771        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2772
2773        if (1) // export view cells
2774        {
2775                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2776
2777                if (exporter)
2778                {
2779                        cout << "exporting view cells after post process ... ";
2780
2781                        if (1)
2782                        {
2783                                exporter->SetWireframe();
2784                                exporter->ExportBox(mViewSpaceBox);
2785                                exporter->SetFilled();
2786                        }
2787
2788                        if (mExportGeometry)
2789                        {
2790                                exporter->ExportGeometry(objects);
2791                        }
2792
2793                        // export rays
2794                        if (mExportRays)
2795                        {
2796                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2797                        }
2798
2799                        ExportViewCellsForViz(exporter);
2800                        delete exporter;
2801                        cout << "finished" << endl;
2802                }
2803        }
2804
2805        if (1)
2806        {
2807                cout << "exporting depth map ... ";
2808
2809                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2810                if (exporter)
2811                {
2812                        if (1)
2813                        {
2814                                exporter->SetWireframe();
2815                                exporter->ExportBox(mViewSpaceBox);
2816                                exporter->SetFilled();
2817                        }
2818
2819                        if (mExportGeometry)
2820                        {
2821                                exporter->ExportGeometry(objects);
2822                        }
2823
2824                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
2825
2826                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2827
2828                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2829                        {
2830                                ViewCell *vc = *vit;
2831
2832                                ViewCellContainer leaves;
2833                                mViewCellsTree->CollectLeaves(vc, leaves);
2834
2835                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2836
2837                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2838                                {
2839                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2840
2841                                        Material m;
2842
2843                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
2844                                        m.mDiffuseColor.r = relDepth;
2845                                        m.mDiffuseColor.g = 0.0f;
2846                                        m.mDiffuseColor.b = 1.0f - relDepth;
2847
2848                    exporter->SetForcedMaterial(m);
2849                               
2850
2851                                        BspNodeGeometry geom;
2852                                        mVspBspTree->ConstructGeometry(leaf, geom);
2853                                        exporter->ExportPolygons(geom.mPolys);
2854                                }
2855                        }
2856
2857                        delete exporter;
2858                }
2859
2860
2861                cout << "finished" << endl;
2862        }
2863
2864        //-- visualization of the BSP splits
2865        bool exportSplits = false;
2866        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2867
2868        if (exportSplits)
2869        {
2870                cout << "exporting splits ... ";
2871                ExportSplits(objects, visRays);
2872                cout << "finished" << endl;
2873        }
2874
2875        //-- export single view cells
2876        ExportBspPvs(objects, visRays);
2877}
2878
2879
2880void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2881                                                                                  const VssRayContainer &rays)
2882{
2883        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2884
2885        if (exporter)
2886        {
2887                Material m;
2888                m.mDiffuseColor = RgbColor(1, 0, 0);
2889                exporter->SetForcedMaterial(m);
2890                exporter->SetWireframe();
2891
2892                exporter->ExportBspSplits(*mVspBspTree, true);
2893
2894                // take forced material, else big scenes cannot be viewed
2895                m.mDiffuseColor = RgbColor(0, 1, 0);
2896                exporter->SetForcedMaterial(m);
2897                exporter->SetFilled();
2898
2899                exporter->ResetForcedMaterial();
2900
2901                // export rays
2902                if (mExportRays)
2903                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
2904
2905                if (mExportGeometry)
2906                        exporter->ExportGeometry(objects);
2907
2908                delete exporter;
2909        }
2910}
2911
2912
2913void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2914                                                                                  const VssRayContainer &rays)
2915{
2916        const int leafOut = 10;
2917
2918        ViewCell::NewMail();
2919
2920        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2921        Debug << "\nOutput view cells: " << endl;
2922
2923        // sort view cells to visualize the largest view cells
2924        if (0)
2925                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2926
2927        int limit = min(leafOut, (int)mViewCells.size());
2928
2929        int raysOut;
2930
2931        //-- some rays for output
2932        if (1)
2933                raysOut = min((int)rays.size(), mVisualizationSamples);
2934
2935        for (int i = 0; i < limit; ++ i)
2936        {
2937                cout << "creating output for view cell " << i << " ... ";
2938
2939                VssRayContainer vcRays;
2940                Intersectable::NewMail();
2941                ViewCell *vc;
2942       
2943                if (0) // largest view cell pvs first
2944                        vc = mViewCells[i];
2945                else
2946                        vc = mViewCells[Random((int)mViewCells.size())];
2947
2948                vector<ViewCell *> leaves;
2949                mViewCellsTree->CollectLeaves(vc, leaves);
2950
2951        if (1)
2952                {
2953                        // check whether we can add the current ray to the output rays
2954                        for (int k = 0; k < raysOut; ++ k)
2955                        {
2956                                VssRay *ray = rays[k];
2957                                for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
2958                                {
2959                                        ViewCell *rayvc = ray->mViewCells[j];
2960
2961                                        if (leaves[0] == rayvc)
2962                                                vcRays.push_back(ray);
2963                                }
2964                        }
2965                }
2966
2967                //bspLeaves[j]->Mail();
2968                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2969                Exporter *exporter = Exporter::GetExporter(s);
2970                exporter->SetWireframe();
2971
2972                Material m;//= RandomMaterial();
2973                m.mDiffuseColor = RgbColor(0, 1, 0);
2974                exporter->SetForcedMaterial(m);
2975
2976                ExportViewCellGeometry(exporter, vc);
2977
2978
2979                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
2980                          << ", piercing rays=" << (int)vcRays.size() << endl;
2981                        //  << ", leaves=" << (int)vc->mLeaves.size() << endl;
2982
2983               
2984                //-- export rays piercing this view cell
2985                if (1)
2986                {
2987                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2988                }
2989                else
2990                {
2991
2992                        ViewCellContainer leaves;
2993                        mViewCellsTree->CollectLeaves(vc, leaves);
2994
2995                        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2996
2997                        for (lit = leaves.begin(); lit != lit_end; ++ lit)
2998                        {
2999                                BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3000                                exporter->ExportRays(l->mVssRays);
3001                        }
3002                }
3003
3004       
3005                m.mDiffuseColor = RgbColor(1, 0, 0);
3006                exporter->SetForcedMaterial(m);
3007
3008                ObjectPvsMap::const_iterator it,
3009                        it_end = vc->GetPvs().mEntries.end();
3010
3011                exporter->SetFilled();
3012
3013       
3014                // output PVS of view cell
3015                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
3016                {
3017               
3018                        Intersectable *intersect = (*it).first;
3019
3020                        if (!intersect->Mailed())
3021                        {
3022                                Material m = RandomMaterial();
3023                                exporter->SetForcedMaterial(m);
3024
3025                                exporter->ExportIntersectable(intersect);
3026                                intersect->Mail();
3027                        }
3028                }
3029
3030               
3031                DEL_PTR(exporter);
3032                cout << "finished" << endl;
3033        }
3034
3035        Debug << endl;
3036}
3037
3038
3039int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3040                                                                                        const Vector3 &termination,
3041                                                                                        ViewCellContainer &viewcells)
3042{
3043        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
3044}
3045
3046
3047void VspBspViewCellsManager::ExportColor(Exporter *exporter,
3048                                                                                 ViewCell *vc) const
3049{
3050        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3051
3052        float importance = 0;
3053        static Material m;
3054
3055        switch (mColorCode)
3056        {
3057        case 0: // Random
3058                {
3059                        if (vcValid)
3060                        {
3061                                m.mDiffuseColor.r = RandomValue(0.3f, 1.0f);
3062                                m.mDiffuseColor.g = RandomValue(0.3f, 1.0f);
3063                                m.mDiffuseColor.b = RandomValue(0.3f, 1.0f);
3064                        }
3065                        else
3066                        {
3067                                m.mDiffuseColor.r = 0.0f;
3068                                m.mDiffuseColor.g = 1.0f;
3069                                m.mDiffuseColor.b = 0.0f;
3070                        }
3071
3072                        exporter->SetForcedMaterial(m);
3073                        return;
3074                }
3075               
3076        case 1: // pvs
3077                {
3078                        importance = (float)vc->GetPvs().GetSize() /
3079                                (float)mViewCellsStats.maxPvs;
3080
3081                }
3082                break;
3083        case 2: // merges
3084                {
3085            int lSize = mViewCellsTree->GetSize(vc);
3086       
3087                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
3088                }
3089                break;
3090        case 3: // merge tree differene
3091                {
3092                        importance = (float)GetMaxTreeDiff(vc) /
3093                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3094
3095                }
3096                break;
3097        default:
3098                break;
3099        }
3100
3101        // special color code for invalid view cells
3102        m.mDiffuseColor.r = importance;
3103        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3104        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
3105
3106        //Debug << "importance: " << importance << endl;
3107        exporter->SetForcedMaterial(m);
3108}
3109
3110
3111void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3112                                                    ViewCell *vc,
3113                                                                                                        const Plane3 *cuttingPlane) const
3114{
3115        if (vc->GetMesh())
3116        {
3117                exporter->ExportMesh(vc->GetMesh());
3118       
3119                return;
3120        }
3121
3122       
3123        if (cuttingPlane)
3124        {
3125                ViewCellContainer leaves;
3126                mViewCellsTree->CollectLeaves(vc, leaves);
3127                ViewCellContainer::const_iterator it, it_end = leaves.end();
3128
3129                for (it = leaves.begin(); it != it_end; ++ it)
3130                {
3131                        BspNodeGeometry geom;
3132
3133                        BspNodeGeometry front;
3134                        BspNodeGeometry back;
3135
3136       
3137                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3138
3139                        mVspBspTree->ConstructGeometry(leaf, geom);
3140                       
3141                        geom.SplitGeometry(front,
3142                                                           back,
3143                                                           *cuttingPlane,
3144                                                           mViewSpaceBox,
3145                                                           0.005);
3146
3147                        exporter->ExportPolygons(back.mPolys);
3148                }
3149        }
3150        else
3151        {
3152                BspNodeGeometry geom;
3153                mVspBspTree->ConstructGeometry(vc, geom);
3154                       
3155                exporter->ExportPolygons(geom.mPolys);
3156        }
3157}
3158
3159
3160int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3161{
3162        ViewCellContainer leaves;
3163        mViewCellsTree->CollectLeaves(vc, leaves);
3164
3165        int maxDist = 0;
3166       
3167        // compute max height difference
3168        for (int i = 0; i < (int)leaves.size(); ++ i)
3169                for (int j = 0; j < (int)leaves.size(); ++ j)
3170        {
3171                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
3172
3173                if (i != j)
3174                {
3175                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
3176                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3177                        if (dist > maxDist)
3178                                maxDist = dist;
3179                }
3180        }
3181
3182        return maxDist;
3183}
3184
3185
3186ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
3187{
3188        if (!mVspBspTree)
3189                return NULL;
3190
3191        if (!mViewSpaceBox.IsInside(point))
3192          return NULL;
3193
3194        return mVspBspTree->GetViewCell(point);
3195}
3196
3197
3198void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3199{
3200        if (vc->GetMesh())
3201                delete vc->GetMesh();
3202
3203       
3204        BspNodeGeometry geom;
3205
3206        mVspBspTree->ConstructGeometry(vc, geom);
3207       
3208        Mesh *mesh = new Mesh();
3209        geom.AddToMesh(*mesh);
3210        vc->SetMesh(mesh);
3211        mMeshContainer.push_back(mesh);
3212}
3213
3214
3215ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3216                                                                                                  ObjectContainer *objects)
3217{
3218        ViewCellsParser parser;
3219
3220        ViewCellsManager *vm = NULL;
3221
3222        if (parser.ParseFile(filename, &vm, objects))
3223        {
3224                //vm->PrepareLoadedViewCells();
3225                vm->ResetViewCells();
3226
3227                vm->mViewCellsFinished = true;
3228                vm->mMaxPvsSize = (int)objects->size();
3229
3230                vm->FinalizeViewCells(true);
3231
3232                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3233        }
3234        else
3235        {
3236                Debug << "failed loading view cells" << endl;
3237                DEL_PTR(vm);
3238        }
3239
3240
3241        return vm;
3242}
3243
3244
3245inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3246{
3247        return obj1->mId < obj2->mId;
3248}
3249
3250
3251bool VspBspViewCellsManager::ExportViewCells(const string filename)
3252{
3253        cout << "exporting view cells to xml ... ";
3254        std::ofstream stream;
3255
3256        // for output we need unique ids for each view cell
3257        CreateUniqueViewCellIds();
3258
3259
3260        stream.open(filename.c_str());
3261        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3262        stream << "<Visibility_Solution>" << endl;
3263
3264        //-- the view space bounding box
3265        stream << "<ViewSpaceBox"
3266                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3267                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3268
3269        //-- the type of the view cells hierarchy
3270        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3271
3272        //-- load the view cells itself, i.e., the ids and the pvs
3273        stream << "<ViewCells>" << endl;
3274        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3275        for (it = mViewCells.begin(); it != it_end; ++ it)
3276                ExportViewCell(*it, stream);
3277
3278        stream << "</ViewCells>" << endl;
3279
3280        //-- load the hierarchy
3281        stream << "<Hierarchy>" << endl;
3282        mVspBspTree->Export(stream);
3283        stream << endl << "</Hierarchy>" << endl;
3284
3285        stream << "</Visibility_Solution>" << endl;
3286        stream.close();
3287
3288        cout << "finished" << endl;
3289
3290        return true;
3291}
3292
3293
3294int VspBspViewCellsManager::CastBeam(Beam &beam)
3295{
3296        return mVspBspTree->CastBeam(beam);
3297}
3298
3299
3300void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
3301                                                                          const bool createMesh)
3302{
3303        CreateMesh(viewCell);
3304
3305        float area = 0;
3306        float volume = 0;
3307
3308        ViewCellContainer leaves;
3309        mViewCellsTree->CollectLeaves(viewCell, leaves);
3310
3311        ViewCellContainer::const_iterator it, it_end = leaves.end();
3312
3313        for (it = leaves.begin(); it != it_end; ++ it)
3314        {
3315                BspNodeGeometry geom;
3316                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3317                mVspBspTree->ConstructGeometry(leaf, geom);
3318
3319                area += geom.GetArea();
3320                volume += geom.GetVolume();
3321        }
3322
3323        viewCell->SetVolume(volume);
3324        viewCell->SetArea(area);
3325}
3326
3327
3328void VspBspViewCellsManager::PrepareLoadedViewCells()
3329{
3330        // TODO: do I still need this here?
3331        if (0)
3332        mVspBspTree->RepairViewCellsLeafLists();
3333}
3334
3335
3336
3337void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3338                                                                                                        vector<MergeCandidate> &candidates)
3339{       
3340        cout << "collecting merge candidates ... " << endl;
3341
3342        if (mUseRaysForMerge)
3343        {
3344                mVspBspTree->CollectMergeCandidates(rays, candidates);
3345        }
3346        else
3347        {
3348                vector<BspLeaf *> leaves;
3349                mVspBspTree->CollectLeaves(leaves);
3350                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3351        }
3352
3353        cout << "fininshed collecting candidates" << endl;
3354}
3355
3356
3357void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
3358{
3359        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3360        for (it = mViewCells.begin(); it != it_end; ++ it)
3361        {
3362        }
3363}
3364
3365//////////////////////////////////
3366ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3367{
3368        //TODO
3369        return NULL;// new VspBspViewCellsManager();
3370}
3371
Note: See TracBrowser for help on using the repository browser.