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

Revision 495, 54.9 KB checked in by mattausch, 19 years ago (diff)

fixed bug in tree collapse

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
14
15ViewCellsManager::ViewCellsManager():
16mRenderer(NULL),
17mConstructionSamples(0),
18mPostProcessSamples(0),
19mVisualizationSamples(0),
20mTotalAreaValid(false),
21mTotalArea(0.0f)
22{
23        mSceneBox.Initialize();
24        ParseEnvironment();
25}
26
27ViewCellsManager::ViewCellsManager(int constructionSamples):
28mConstructionSamples(constructionSamples),
29mRenderer(NULL),
30mPostProcessSamples(0),
31mVisualizationSamples(0)
32{
33        mSceneBox.Initialize();
34        ParseEnvironment();
35}
36
37void ViewCellsManager::ParseEnvironment()
38{
39        // post processing stuff
40        environment->GetIntValue("ViewCells.PostProcess.minPvsDif", mMinPvsDif);
41        environment->GetIntValue("ViewCells.PostProcess.minPvs", mMinPvs);
42        environment->GetIntValue("ViewCells.PostProcess.maxPvs", mMaxPvs);
43
44        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
45        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
46
47        char buf[50];
48       
49        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
50       
51        if (strcmp(buf, "PVS") == 0)
52                mColorCode = 1;
53        else if (strcmp(buf, "MergedLeaves") == 0)
54                mColorCode = 2;
55        else if (strcmp(buf, "MergedTreeDiff") == 0)
56                mColorCode = 3;
57        else
58                mColorCode = 0;
59
60        Debug << "colorCode: " << mColorCode << endl;
61}
62
63
64ViewCellsManager::~ViewCellsManager()
65{
66        DEL_PTR(mRenderer);
67
68        CLEAR_CONTAINER(mViewCells);
69}
70
71
72bool ViewCellsManager::LoadViewCells(const string filename)
73{
74        X3dParser parser;
75       
76        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
77       
78        bool success = parser.ParseFile(filename, *this);
79        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
80
81        return success;
82}
83
84
85bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
86{
87        viewPoint = mSceneBox.GetRandomPoint();
88
89        return true;
90}
91
92
93bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
94{
95        return mSceneBox.IsInside(viewPoint);
96}
97
98void ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays)
99{
100        // view cells not yet constructed
101        if (!ViewCellsConstructed())
102                return;
103 
104        VssRayContainer::const_iterator it, it_end = rays.end();
105
106        for (it = rays.begin(); it != it_end; ++ it)
107        {       
108                ComputeSampleContributions(*(*it));
109        }
110}
111
112
113void ViewCellsManager::EvaluateViewCellsStats()
114{
115        mViewCellsStats.Reset();
116
117        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
118
119        for (it = mViewCells.begin(); it != it_end; ++ it)
120        {
121                (*it)->UpdateViewCellsStats(mViewCellsStats);
122        }
123}
124
125
126void ViewCellsManager::AddViewCell(ViewCell *viewCell)
127{
128        mViewCells.push_back(viewCell);
129}
130
131
132float ViewCellsManager::GetArea(ViewCell *viewCell) const
133{
134        return viewCell->GetArea();
135}
136
137
138float ViewCellsManager::GetVolume(ViewCell *viewCell) const
139{
140        return viewCell->GetVolume();
141}
142
143
144void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
145                                                                           ViewCellContainer &viewCells,
146                                                                           const int maxViewCells) const
147{
148        // maximal max viewcells
149        int limit = maxViewCells > 0 ?
150                Min((int)objects.size(), maxViewCells) : (int)objects.size();
151
152        for (int i = 0; i < limit; ++ i)
153        {
154                Intersectable *object = objects[i];
155               
156                // extract the mesh instances
157                if (object->Type() == Intersectable::MESH_INSTANCE)
158                {
159                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
160
161                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
162                        viewCells.push_back(viewCell);
163                }
164                //TODO: transformed meshes
165        }
166}
167
168
169ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
170                                                                                        const float height) const
171{
172        // one mesh per view cell
173        Mesh *mesh = new Mesh();
174       
175        //-- construct prism
176
177        // bottom
178        mesh->mFaces.push_back(new Face(2,1,0));
179        // top
180    mesh->mFaces.push_back(new Face(3,4,5));
181        // sides
182        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
183        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
184        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
185
186        //--- extrude new vertices for top of prism
187        Vector3 triNorm = baseTri.GetNormal();
188
189        Triangle3 topTri;       
190
191        // add base vertices and calculate top vertices
192        for (int i = 0; i < 3; ++ i)
193                mesh->mVertices.push_back(baseTri.mVertices[i]);
194       
195        // add top vertices     
196        for (int i = 0; i < 3; ++ i)
197                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
198       
199        mesh->Preprocess();
200
201        return GenerateViewCell(mesh);
202}
203
204
205ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
206{
207        // generate merged view cell
208        ViewCell *vc = GenerateViewCell();
209
210        // merge pvs
211        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
212
213        //-- merge ray sets
214        stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
215        stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
216
217        std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
218                           back.mPiercingRays.begin(), back.mPiercingRays.end(),
219                           vc->mPiercingRays.begin());
220
221        return vc;
222}
223
224
225void ViewCellsManager::SetRenderer(Renderer *renderer)
226{
227        mRenderer = renderer;
228}
229
230
231ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
232{
233        return new ViewCell(mesh);
234}
235
236
237void ViewCellsManager::SetVisualizationSamples(const int visSamples)
238{
239        mVisualizationSamples = visSamples;
240}
241
242
243void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
244{
245        mConstructionSamples = constructionSamples;
246}
247
248
249void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
250{
251        mPostProcessSamples = postProcessSamples;
252}
253
254
255int ViewCellsManager::GetVisualizationSamples() const
256{
257        return mVisualizationSamples;
258}
259
260
261int ViewCellsManager::GetConstructionSamples() const
262{
263        return mConstructionSamples;
264}
265
266
267int ViewCellsManager::GetPostProcessSamples() const
268{
269        return mPostProcessSamples;
270}
271
272
273void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
274{
275  ViewCellContainer::const_iterator it = mViewCells.begin();
276  stat.viewcells = 0;
277  stat.minPvs = 100000000;
278  stat.maxPvs = 0;
279  stat.avgPvs = 0.0f;
280
281  for (; it != mViewCells.end(); ++it) {
282        ViewCell *viewcell = *it;
283        int pvsSize = viewcell->GetPvs().GetSize();
284        if ( pvsSize < stat.minPvs)
285          stat.minPvs = pvsSize;
286        if (pvsSize > stat.maxPvs)
287          stat.maxPvs = pvsSize;
288        stat.avgPvs += pvsSize;
289        stat.viewcells++;
290  }
291  if (stat.viewcells)
292        stat.avgPvs/=stat.viewcells;
293}
294
295
296void ViewCellsManager::PrintPvsStatistics(ostream &s)
297{
298  s<<"############# Viewcell PVS STAT ##################\n";
299  PvsStatistics pvsStat;
300  GetPvsStatistics(pvsStat);
301  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
302  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
303  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
304}
305
306
307ViewCellContainer &ViewCellsManager::GetViewCells()
308{
309        return mViewCells;
310}
311
312
313void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
314{
315        mSceneBox = box;
316}
317
318
319void ViewCellsManager::ResetViewCells()
320{
321        mViewCells.clear();
322        CollectViewCells();
323        mViewCellsStats.Reset();
324        EvaluateViewCellsStats();
325
326        mTotalAreaValid = false;
327}
328
329
330void ViewCellsManager::ComputeSampleContributions(VssRay &ray)
331{
332
333
334
335  ViewCellContainer viewcells;
336               
337  ray.mPvsContribution = 0;
338  ray.mRelativePvsContribution = 0.0f;
339
340  // matt TODO: remove this!!
341  Ray hray(ray);
342  float tmin = 0, tmax = 1.0;
343 
344  //hray.Init(ray.GetOrigin(), ray.GetDir(), Ray::LINE_SEGMENT);
345  if (!GetSceneBbox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
346        return;
347 
348  Vector3 origin = hray.Extrap(tmin);
349  Vector3 termination = hray.Extrap(tmax);
350 
351  CastLineSegment(origin,
352                                  termination,
353                                  viewcells);
354 
355  // copy viewcells memory efficiently
356  const bool storeViewcells = false;
357  if (storeViewcells) {
358        ray.mViewCells.reserve(viewcells.size());
359        ray.mViewCells = viewcells;
360  }
361 
362  ViewCellContainer::const_iterator it = viewcells.begin();
363
364  bool addInPlace = false;
365
366  if (addInPlace) {
367        for (; it != viewcells.end(); ++it) {   
368          ViewCell *viewcell = *it;
369         
370          // if ray not outside of view space
371          float contribution;
372          bool added =
373                viewcell->GetPvs().AddSample(ray.mTerminationObject,
374                                                                         contribution
375                                                                         );
376          if (added)
377                ray.mPvsContribution++;
378         
379          ray.mRelativePvsContribution += contribution;
380        }
381  } else {
382    for (; it != viewcells.end(); ++it) {       
383          ViewCell *viewcell = *it;
384          // if ray not outside of view space
385          float contribution;
386          if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
387                                                                                                   contribution
388                                                                                                   ))
389                ray.mPvsContribution++;
390         
391          ray.mRelativePvsContribution += contribution;
392        }
393
394        for (it = viewcells.begin(); it != viewcells.end(); ++it) {     
395          ViewCell *viewcell = *it;
396          // if ray not outside of view space
397          viewcell->GetPvs().AddSample(ray.mTerminationObject);
398        }
399  }
400}
401
402
403void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
404                                                                  const int maxSize,
405                                                                  VssRayContainer &usedRays,
406                                                                  VssRayContainer *savedRays) const
407{
408        const int limit = min(maxSize, (int)sourceRays.size());
409        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
410
411        VssRayContainer::const_iterator it, it_end = sourceRays.end();
412        for (it = sourceRays.begin(); it != it_end; ++ it)
413        {
414                if (Random(1.0f) < prop)
415                        usedRays.push_back(*it);
416                else if (savedRays)
417                        savedRays->push_back(*it);
418        }
419}
420
421
422float ViewCellsManager::GetAccVcArea()
423{
424        // if already computed
425        if (mTotalAreaValid)
426                return mTotalArea;
427
428        mTotalArea = 0;
429        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
430
431        for (it = mViewCells.begin(); it != it_end; ++ it)
432        {
433                //Debug << "area: " << GetArea(*it);
434        mTotalArea += GetArea(*it);
435        }
436
437        mTotalAreaValid = true;
438
439        return mTotalArea;
440}
441
442
443void ViewCellsManager::PrintStatistics(ostream &s) const
444{
445        s << mViewCellsStats << endl;
446}
447
448
449void ViewCellsManager::ExportViewCells(Exporter *exporter) const
450{
451        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
452
453        for (it = mViewCells.begin(); it != it_end; ++ it)
454        {
455                ExportColor(exporter, *it);
456                ExportVcGeometry(exporter, *it);
457        }
458}
459
460
461/**********************************************************************/
462/*                   BspViewCellsManager implementation               */
463/**********************************************************************/
464
465
466BspViewCellsManager::BspViewCellsManager(BspTree *bspTree,
467                                                                                 int constructionSamples):
468ViewCellsManager(constructionSamples),
469mBspTree(bspTree)
470{
471}
472
473
474bool BspViewCellsManager::ViewCellsConstructed() const
475{
476        return mBspTree->GetRoot() != NULL;
477}
478
479
480ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
481{
482        return new BspViewCell(mesh);
483}
484
485
486int BspViewCellsManager::Construct(const ObjectContainer &objects,
487                                                                   const VssRayContainer &rays)
488{
489        // if view cells were already constructed
490        if (ViewCellsConstructed())
491                return 0;
492
493        int sampleContributions = 0;
494       
495        // construct view cells using the collected samples
496        RayContainer constructionRays;
497        VssRayContainer savedRays;
498
499        const int limit = min(mConstructionSamples, (int)rays.size());
500
501        VssRayContainer::const_iterator it, it_end = rays.end();
502
503        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
504
505        for (it = rays.begin(); it != it_end; ++ it)
506        {
507                if (Random(1.0f) < prop)
508                        constructionRays.push_back(new Ray(*(*it)));
509                else
510                        savedRays.push_back(*it);
511        }
512
513    if (mViewCells.empty())
514        {
515                // no view cells loaded
516                mBspTree->Construct(objects, constructionRays);
517                // collect final view cells
518                mBspTree->CollectViewCells(mViewCells);
519        }
520        else
521        {
522                mBspTree->Construct(mViewCells);
523        }
524
525        // destroy rays created only for construction
526        CLEAR_CONTAINER(constructionRays);
527
528        Debug << mBspTree->GetStatistics() << endl;
529       
530        EvaluateViewCellsStats();
531        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
532
533        // recast rest of the rays
534        ComputeSampleContributions(savedRays);
535
536        return sampleContributions;
537}
538
539void BspViewCellsManager::CollectViewCells()
540{
541        mBspTree->CollectViewCells(mViewCells);
542}
543
544float BspViewCellsManager::GetProbability(ViewCell *viewCell)
545{
546        // compute view cell area as subsititute for probability
547#if 0
548        return GetArea(viewCell) / GetSceneBbox().SurfaceArea();
549#else
550        return GetArea(viewCell) / GetAccVcArea();
551#endif
552}
553 
554
555float BspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
556{
557        return viewCell->GetPvs().GetSize() * objRendercost;
558}
559
560
561AxisAlignedBox3 BspViewCellsManager::GetSceneBbox() const
562{
563        return mBspTree->GetBoundingBox();
564}
565
566
567int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
568                                                                                 const Vector3 &termination,
569                                                                                 ViewCellContainer &viewcells)
570{
571        return mBspTree->CastLineSegment(origin, termination, viewcells);
572}
573
574
575int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
576                                                                         const VssRayContainer &rays)
577{
578        if (!ViewCellsConstructed())
579        {
580                Debug << "view cells not constructed" << endl;
581                return 0;
582        }
583
584        //-- post processing of bsp view cells
585    int vcSize = 0;
586        int pvsSize = 0;
587
588        EvaluateViewCellsStats();
589        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
590
591        mRenderer->RenderScene();
592        SimulationStatistics ss;
593        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
594
595    Debug << ss << endl;
596
597        if (1) // export view cells
598        {
599                cout << "exporting initial view cells (=leaves) ... ";
600                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
601       
602                if (exporter)
603                {
604                        //exporter->SetWireframe();
605                        exporter->SetFilled();
606                        ExportViewCells(exporter);
607                               
608                        if (mExportGeometry)
609                        {
610                                Material m;
611                                m.mDiffuseColor = RgbColor(0, 1, 0);
612                                exporter->SetForcedMaterial(m);
613                                exporter->SetWireframe();
614
615                                exporter->ExportGeometry(objects);
616                        }
617
618                        delete exporter;
619                }
620                cout << "finished" << endl;
621        }
622
623        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
624               
625        long startTime = GetTime();
626
627
628        // $$JB we do not have connectivity information from the ray in the moment
629        // perhaps we could recast the rays or remember the cells traversed inside the
630        // vssray (which would on other hand create some overhead)
631        //-- merge or subdivide view cells
632        int merged = 0;
633
634        vector<BspIntersection>::const_iterator iit;
635        CLEAR_CONTAINER(mBspRays);
636        ConstructBspRays(rays, mPostProcessSamples);
637       
638        for (int i = 0; i < (int)mBspRays.size(); ++ i)
639        { 
640                BspRay *ray = mBspRays[i];
641         
642                // traverse leaves stored in the rays and compare and merge consecutive
643                // leaves (i.e., the neighbors in the tree)
644                if (ray->intersections.size() < 2)
645                        continue;
646         
647                iit = ray->intersections.begin();
648
649                BspLeaf *previousLeaf = (*iit).mLeaf;
650                ++ iit;
651               
652                for (; iit != ray->intersections.end(); ++ iit)
653                {
654                        BspLeaf *leaf = (*iit).mLeaf;
655
656                        if (ShouldMerge(leaf, previousLeaf))
657                        {                       
658                                MergeBspLeafViewCells(leaf, previousLeaf);
659
660                                ++ merged;
661                        }
662               
663                        previousLeaf = leaf;
664                }
665        }
666
667        //-- stats and visualizations
668        cout << "finished" << endl;
669        cout << "merged " << merged << " view cells in "
670                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
671
672        Debug << "Postprocessing: Merged " << merged << " view cells in "
673                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
674                  << "using " << (int)mBspRays.size() << " samples" << endl << endl;
675       
676        CLEAR_CONTAINER(mBspRays);
677
678        // reset view cells and stats
679        ResetViewCells();
680
681        return merged;
682}
683
684
685BspViewCellsManager::~BspViewCellsManager()
686{
687        CLEAR_CONTAINER(mBspRays);
688}
689
690
691int BspViewCellsManager::GetType() const
692{
693        return BSP;
694}
695
696
697void BspViewCellsManager::Visualize(const ObjectContainer &objects,
698                                                                        const VssRayContainer &sampleRays)
699{
700        if (!ViewCellsConstructed())
701                return;
702        CLEAR_CONTAINER(mBspRays);
703        ConstructBspRays(sampleRays, mVisualizationSamples);
704       
705        if (1) // export view cells
706        {
707                cout << "exporting view cells after merge ... ";
708                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
709
710                if (exporter)
711                {
712                        ExportViewCells(exporter);
713                        delete exporter;
714                }
715               
716                cout << "finished" << endl;
717        }       
718
719        //-- visualization of the BSP splits
720        bool exportSplits = false;
721        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
722       
723        if (exportSplits)
724        {
725                cout << "exporting splits ... ";
726                ExportSplits(objects);
727                cout << "finished" << endl;
728        }
729
730        ExportBspPvs(objects);
731}
732
733
734inline bool vc_gt(ViewCell *a, ViewCell *b)
735{
736        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
737}
738
739
740void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
741{
742        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
743
744        if (exporter)
745        {       
746                Material m;
747                m.mDiffuseColor = RgbColor(1, 0, 0);
748                exporter->SetForcedMaterial(m);
749                exporter->SetWireframe();
750               
751                exporter->ExportBspSplits(*mBspTree, true);
752
753                //NOTE: take forced material, else big scenes cannot be viewed
754                m.mDiffuseColor = RgbColor(0, 1, 0);
755                exporter->SetForcedMaterial(m);
756                //exporter->ResetForcedMaterial();
757
758                exporter->SetFilled();
759                               
760                // export rays
761                if (0)
762                {
763                        VssRayContainer outRays;
764               
765                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
766
767                        for (int i = 0; i < raysSize; ++ i)
768                                // only rays piercing geometry
769                                outRays.push_back(mBspRays[i]->vssRay);
770                                               
771                        // export rays
772                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
773                }
774
775                if (mExportGeometry)
776                        exporter->ExportGeometry(objects);
777
778                delete exporter;
779        }
780}
781
782
783void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
784{
785        const int leafOut = 10;
786       
787        ViewCell::NewMail();
788
789        //-- some rays for output
790        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
791       
792        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
793        Debug << "\nOutput view cells: " << endl;
794       
795        // sort view cells to get largest view cells
796#if 0
797        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
798#endif
799        int limit = min(leafOut, (int)mViewCells.size());
800               
801        for (int i = 0; i < limit; ++ i)
802        {
803                cout << "creating output for view cell " << i << " ... ";
804                VssRayContainer vcRays;
805                Intersectable::NewMail();
806#if 0
807                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
808#else
809                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[Random((int)mViewCells.size())]);
810#endif
811                cout << "creating output for view cell " << i << " ... ";
812
813#if 0
814                // check whether we can add the current ray to the output rays
815                for (int k = 0; k < raysOut; ++ k)
816                {
817                        BspRay *ray = mBspRays[k];
818                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
819                        {
820                                BspLeaf *leaf = ray->intersections[j].mLeaf;
821                                if (vc == leaf->GetViewCell())
822                                        vcRays.push_back(ray->vssRay);
823                        }
824                }
825#endif
826                //bspLeaves[j]->Mail();
827                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
828
829                Exporter *exporter = Exporter::GetExporter(s);
830                       
831                exporter->SetWireframe();
832
833                Material m;//= RandomMaterial();
834                m.mDiffuseColor = RgbColor(0, 1, 0);
835                exporter->SetForcedMaterial(m);
836
837                if (vc->GetMesh())
838                        exporter->ExportViewCell(vc);
839                else
840                {
841                        PolygonContainer vcGeom;
842                       
843                        //-- export view cell
844                        mBspTree->ConstructGeometry(vc, vcGeom);
845                        exporter->ExportPolygons(vcGeom);
846                        CLEAR_CONTAINER(vcGeom);
847                }
848                       
849                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
850                          << ", piercing rays=" << (int)vcRays.size()
851                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
852
853                       
854                // export rays piercing this view cell
855#if 0
856                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
857#else
858                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
859                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
860                        exporter->ExportRays((*lit)->mVssRays);
861#endif
862                m.mDiffuseColor = RgbColor(1, 0, 0);
863                exporter->SetForcedMaterial(m);
864
865                ObjectPvsMap::const_iterator it,
866                        it_end = vc->GetPvs().mEntries.end();
867
868                exporter->SetFilled();
869
870                // output PVS of view cell
871                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
872                {
873                        Intersectable *intersect = (*it).first;
874
875                        if (!intersect->Mailed())
876                        {
877                                Material m = RandomMaterial();
878                                exporter->SetForcedMaterial(m);
879
880                                exporter->ExportIntersectable(intersect);
881                                intersect->Mail();
882                        }                       
883                }
884                               
885                DEL_PTR(exporter);
886                cout << "finished" << endl;
887        }
888
889        Debug << endl;
890}
891
892
893bool BspViewCellsManager::MergeBspLeafViewCells(BspLeaf *front, BspLeaf *back) const
894{
895        BspViewCell *viewCell =
896                dynamic_cast<BspViewCell *>(MergeViewCells(*front->GetViewCell(),
897                                                                                                   *back->GetViewCell()));
898       
899        if (!viewCell)
900                return false;
901
902        //-- change pointer to view cells of all leaves associated with the previous view cells
903        BspViewCell *fVc = front->GetViewCell();
904        BspViewCell *bVc = back->GetViewCell();
905
906        vector<BspLeaf *> fLeaves = fVc->mLeaves;
907        vector<BspLeaf *> bLeaves = bVc->mLeaves;
908
909        vector<BspLeaf *>::const_iterator it;
910       
911        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
912        {
913                (*it)->SetViewCell(viewCell);
914                viewCell->mLeaves.push_back(*it);
915        }
916        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
917        {
918                (*it)->SetViewCell(viewCell);
919                viewCell->mLeaves.push_back(*it);
920        }
921       
922        DEL_PTR(fVc);
923        DEL_PTR(bVc);
924
925        return true;
926}
927
928bool BspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
929{
930        ViewCell *fvc = front->GetViewCell();
931        ViewCell *bvc = back->GetViewCell();
932
933        if ((fvc == mBspTree->GetRootCell()) || (bvc == mBspTree->GetRootCell()) || (fvc == bvc))
934                return false;
935
936        int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
937
938        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
939        {
940                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
941                        (bvc->GetPvs().GetSize() < mMinPvs) ||
942                        ((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
943                {
944                        return true;
945                }
946        }
947       
948        return false;
949}
950
951
952void BspViewCellsManager::ConstructBspRays(const VssRayContainer &rays,
953                                                                                   const int numSamples)
954{
955        VssRayContainer::const_iterator it, it_end = rays.end();
956
957        for (it = rays.begin(); it != rays.end() && mBspRays.size() < numSamples; ++ it)
958        {
959                VssRay *vssRay = *it;
960                BspRay *ray = new BspRay(vssRay);
961
962                ViewCellContainer viewCells;
963
964                // cast line segment to get intersections with bsp leaves
965                CastLineSegment(vssRay->mTermination, vssRay->mOrigin, viewCells);
966
967                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
968                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
969                {
970                        BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
971                        ray->intersections.push_back(BspIntersection(0, vc->mLeaves[0]));
972                }
973
974                mBspRays.push_back(ray);
975        }
976}
977
978
979void BspViewCellsManager::ExportColor(Exporter *exporter,
980                                                                          ViewCell *vc) const
981{
982        if (mColorCode == 0) // Random color
983        {
984                exporter->ResetForcedMaterial();
985                return;
986        }
987
988        float importance = 0;
989
990        switch (mColorCode)
991        {
992        case 1: // pvs
993                {
994                        importance = (float)vc->GetPvs().GetSize() /
995                                (float)mViewCellsStats.maxPvs;
996                }
997                break;
998        case 2: // merges
999                {
1000                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
1001
1002                        importance = (float)bspVc->mLeaves.size() /
1003                                (float)mViewCellsStats.maxLeaves;
1004                }
1005                break;
1006        case 3: // merge tree differene
1007                {
1008                        // TODO
1009                }
1010                break;
1011        default:
1012                break;
1013        }
1014
1015        Material m;
1016        m.mDiffuseColor.b = 1.0f;
1017        m.mDiffuseColor.r = importance;
1018        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1019       
1020        exporter->SetForcedMaterial(m);
1021}
1022
1023void BspViewCellsManager::ExportVcGeometry(Exporter *exporter,
1024                                                                                 ViewCell *vc) const
1025{
1026        if (vc->GetMesh())
1027                exporter->ExportViewCell(vc);
1028        else
1029        {
1030                PolygonContainer cell;
1031                mBspTree->ConstructGeometry(
1032                        dynamic_cast<BspViewCell *>(vc), cell);
1033                exporter->ExportPolygons(cell);
1034        }
1035}
1036
1037/**********************************************************************/
1038/*                   KdViewCellsManager implementation               */
1039/**********************************************************************/
1040
1041KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
1042ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
1043{
1044}
1045
1046float KdViewCellsManager::GetProbability(ViewCell *viewCell)
1047{
1048        // compute view cell area / volume as subsititute for probability
1049#if 0
1050        return GetArea(viewCell) / GetSceneBbox().SurfaceArea();
1051#endif
1052#if 1
1053        return GetArea(viewCell) / GetAccVcArea();
1054#endif
1055#if 0
1056        return GetVolume(viewCell) / GetSceneBbox().GetVolume();
1057#endif
1058}
1059
1060
1061float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1062{
1063        return viewCell->GetPvs().GetSize() * objRendercost;
1064}
1065
1066
1067AxisAlignedBox3 KdViewCellsManager::GetSceneBbox() const
1068{
1069        return mKdTree->GetBox();
1070}
1071
1072void KdViewCellsManager::CollectViewCells()
1073{
1074        //mKdTree->CollectViewCells(mViewCells); TODO
1075}
1076
1077int KdViewCellsManager::Construct(const ObjectContainer &objects,
1078                                                                  const VssRayContainer &rays)
1079{
1080        // if view cells already constructed
1081        if (ViewCellsConstructed())
1082                return 0;
1083
1084        mKdTree->Construct();
1085
1086        mTotalAreaValid = false;
1087        // create the view cells
1088        mKdTree->CreateAndCollectViewCells(mViewCells);
1089       
1090        // cast rays
1091        ComputeSampleContributions(rays);
1092
1093        EvaluateViewCellsStats();
1094        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1095
1096        return 0;
1097}
1098
1099bool KdViewCellsManager::ViewCellsConstructed() const
1100{
1101        return mKdTree->GetRoot() != NULL;
1102}
1103
1104int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1105                                                                        const VssRayContainer &rays)
1106{
1107        return 0;
1108}
1109
1110void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1111                                                                   const VssRayContainer &sampleRays)
1112{
1113        if (!ViewCellsConstructed())
1114                return;
1115
1116        // using view cells instead of the kd PVS of objects
1117        const bool useViewCells = true;
1118        bool exportRays = false;
1119
1120        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1121        const int pvsOut = min((int)objects.size(), 10);
1122        VssRayContainer *rays = new VssRayContainer[pvsOut];
1123
1124        if (useViewCells)
1125        {
1126                const int leafOut = 10;
1127               
1128                ViewCell::NewMail();
1129 
1130                //-- some rays for output
1131                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1132                Debug << "visualization using " << raysOut << " samples" << endl;
1133
1134                //-- some random view cells and rays for output
1135                vector<KdLeaf *> kdLeaves;
1136               
1137                for (int i = 0; i < leafOut; ++ i)
1138                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1139               
1140                for (int i = 0; i < kdLeaves.size(); ++ i)
1141                {
1142                        KdLeaf *leaf = kdLeaves[i];
1143                        RayContainer vcRays;
1144                       
1145                        cout << "creating output for view cell " << i << " ... ";
1146#if 0                   
1147                        // check whether we can add the current ray to the output rays
1148                        for (int k = 0; k < raysOut; ++ k)
1149                        {
1150                                Ray *ray = sampleRays[k];
1151                               
1152                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1153                                {
1154                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1155                                       
1156                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1157                                        {
1158                                                vcRays.push_back(ray);
1159                                        }
1160                                }
1161                        }
1162#endif                 
1163                        Intersectable::NewMail();
1164                       
1165                        ViewCell *vc = leaf->mViewCell;
1166                       
1167                        //bspLeaves[j]->Mail();
1168                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1169                       
1170                        Exporter *exporter = Exporter::GetExporter(s);
1171                        exporter->SetFilled();
1172
1173                        exporter->SetWireframe();
1174                        //exporter->SetFilled();
1175                       
1176                        Material m;//= RandomMaterial();
1177                        m.mDiffuseColor = RgbColor(1, 1, 0);
1178                        exporter->SetForcedMaterial(m);
1179                       
1180                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1181                        exporter->ExportBox(box);
1182
1183                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1184                                << ", piercing rays=" << (int)vcRays.size() << endl;
1185                       
1186                        // export rays piercing this view cell
1187                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0)); 
1188                       
1189                        m.mDiffuseColor = RgbColor(1, 0, 0);
1190                        exporter->SetForcedMaterial(m);
1191                       
1192                        // exporter->SetWireframe();
1193                        exporter->SetFilled();
1194                       
1195                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1196                        // output PVS of view cell
1197                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1198                        {
1199                                Intersectable *intersect = (*it).first;
1200                                if (!intersect->Mailed())
1201                                {
1202                                        exporter->ExportIntersectable(intersect);
1203                                        intersect->Mail();
1204                                }                       
1205                        }
1206                       
1207                        DEL_PTR(exporter);
1208                        cout << "finished" << endl;
1209                }
1210
1211                DEL_PTR(rays);
1212        }
1213        else // using kd PVS of objects
1214        {
1215                for (int i = 0; i < limit; ++ i)
1216                {
1217                        VssRay *ray = sampleRays[i];
1218               
1219                        // check whether we can add this to the rays
1220                        for (int j = 0; j < pvsOut; j++)
1221                        {
1222                                if (objects[j] == ray->mTerminationObject)
1223                                {
1224                                        rays[j].push_back(ray);
1225                                }
1226                        }
1227                }
1228
1229                if (exportRays)
1230                {
1231                        Exporter *exporter = NULL;
1232                        exporter = Exporter::GetExporter("sample-rays.x3d");
1233                        exporter->SetWireframe();
1234                        exporter->ExportKdTree(*mKdTree);
1235               
1236                        for (i=0; i < pvsOut; i++)
1237                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1238
1239                        exporter->SetFilled();
1240               
1241                        delete exporter;
1242                }
1243
1244                for (int k=0; k < pvsOut; k++)
1245                {
1246                        Intersectable *object = objects[k];
1247                        char s[64];     
1248                        sprintf(s, "sample-pvs%04d.x3d", k);
1249
1250                        Exporter *exporter = Exporter::GetExporter(s);
1251                        exporter->SetWireframe();
1252               
1253                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1254                        Intersectable::NewMail();
1255                       
1256                        // avoid adding the object to the list
1257                        object->Mail();
1258                        ObjectContainer visibleObjects;
1259           
1260                        for (; i != object->mKdPvs.mEntries.end(); i++)
1261                        {
1262                                KdNode *node = (*i).first;
1263                                exporter->ExportBox(mKdTree->GetBox(node));
1264               
1265                                mKdTree->CollectObjects(node, visibleObjects);
1266                        }
1267               
1268                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1269                        exporter->SetFilled();
1270                       
1271                        for (int j = 0; j < visibleObjects.size(); j++)
1272                                exporter->ExportIntersectable(visibleObjects[j]);
1273                       
1274                        Material m;
1275                        m.mDiffuseColor = RgbColor(1, 0, 0);
1276                        exporter->SetForcedMaterial(m);
1277                        exporter->ExportIntersectable(object);
1278               
1279                        delete exporter;
1280                }
1281        }               
1282}
1283
1284
1285void KdViewCellsManager::ExportColor(Exporter *exporter,
1286                                                                         ViewCell *vc) const
1287{
1288        // TODO
1289}
1290
1291
1292void KdViewCellsManager::ExportVcGeometry(Exporter *exporter,
1293                                                                                  ViewCell *vc) const
1294{
1295        KdViewCell *kdVc = dynamic_cast<KdViewCell *>(vc);
1296        vector<KdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1297
1298        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
1299                exporter->ExportBox(mKdTree->GetBox(*it));
1300}
1301
1302
1303int KdViewCellsManager::GetType() const
1304{
1305        return ViewCellsManager::KD;
1306}
1307
1308
1309
1310KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1311{
1312        KdNode *node = leaf;
1313
1314        while (node->mParent && node->mDepth > mKdPvsDepth)
1315                node = node->mParent;
1316        return node;
1317}
1318
1319int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1320                                                                                const Vector3 &termination,
1321                                                                                ViewCellContainer &viewcells)
1322{
1323        return mKdTree->CastLineSegment(origin, termination, viewcells);
1324}
1325
1326
1327/**********************************************************************/
1328/*                   VspKdViewCellsManager implementation             */
1329/**********************************************************************/
1330
1331
1332VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
1333                                                                                         int constructionSamples):
1334ViewCellsManager(constructionSamples),
1335mVspKdTree(vspKdTree)
1336{
1337        mVspKdTree->SetViewCellsManager(this);
1338}
1339
1340float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
1341{
1342        // volume or area substitutes for view point probability
1343#if 0
1344        return GetArea(viewCell) / GetSceneBbox().SurfaceArea();
1345#else
1346        return GetArea(viewCell) / GetAccVcArea();
1347#endif
1348}
1349
1350
1351float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1352{
1353        return viewCell->GetPvs().GetSize() * objRendercost;
1354}
1355
1356void VspKdViewCellsManager::CollectViewCells()
1357{
1358        mVspKdTree->CollectViewCells(mViewCells);
1359}
1360
1361int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
1362                                                                         const VssRayContainer &rays)
1363{
1364        // if view cells already constructed
1365        if (ViewCellsConstructed())
1366                return 0;
1367               
1368        VssRayContainer constructionRays;
1369        VssRayContainer savedRays;
1370
1371        GetRaySets(rays,
1372                           mConstructionSamples,
1373                           constructionRays,
1374                           &savedRays);
1375       
1376        Debug << "constructing vsp kd tree using "
1377                  << (int)constructionRays.size() << " samples" << endl;
1378
1379        mVspKdTree->Construct(constructionRays, &mSceneBox);
1380        Debug << mVspKdTree->GetStatistics() << endl;
1381
1382        // export leaf building blocks
1383        ExportLeaves(objects, rays);
1384
1385        // finally merge kd leaf building blocks to view cells
1386        const int merged = mVspKdTree->MergeViewCells(rays);
1387
1388        // collapse siblings belonging to the same view cell
1389        mVspKdTree->CollapseTree();
1390
1391        // collapse siblings belonging to the same view cell
1392        mVspKdTree->RefineViewCells(rays);
1393
1394        // evaluale view cell stats
1395        ResetViewCells();
1396
1397        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1398
1399        long startTime = GetTime();
1400        // recast rest of rays
1401        ComputeSampleContributions(savedRays);
1402       
1403        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
1404                  << " secs" << endl;
1405
1406        return merged;
1407}
1408
1409bool VspKdViewCellsManager::ViewCellsConstructed() const
1410{
1411        return mVspKdTree->GetRoot() != NULL;
1412}
1413
1414
1415ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1416{
1417        return new VspKdViewCell(mesh);
1418}
1419
1420int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
1421                                                                           const VssRayContainer &rays)
1422{
1423        if (!ViewCellsConstructed())
1424                return 0;
1425
1426        // recalculate stats
1427        EvaluateViewCellsStats();
1428
1429        return 0;
1430}
1431
1432
1433AxisAlignedBox3 VspKdViewCellsManager::GetSceneBbox() const
1434{
1435        return mVspKdTree->GetBBox(mVspKdTree->GetRoot());
1436}
1437
1438
1439void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
1440                                                                                 const VssRayContainer &sampleRays)
1441{
1442        if (!ViewCellsConstructed())
1443                return;
1444
1445        //-- export leaf building blocks
1446        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
1447        if (!exporter)
1448                return;
1449
1450        //exporter->SetWireframe();
1451        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1452        exporter->ExportVspKdTree(*mVspKdTree);
1453
1454        if (mExportGeometry)
1455                exporter->ExportGeometry(objects);
1456
1457        if (mExportRays)
1458        {
1459                const float prob = (float)mVisualizationSamples
1460                        / ((float)sampleRays.size() + Limits::Small);
1461
1462                exporter->SetWireframe();
1463
1464                //-- collect uniformly distributed rays
1465                VssRayContainer rays;
1466
1467                for (int i = 0; i < sampleRays.size(); ++ i)
1468                {
1469                        if (RandomValue(0,1) < prob)
1470                                rays.push_back(sampleRays[i]);
1471                }
1472                exporter->ExportRays(rays, RgbColor(1, 0, 0));
1473        }
1474
1475        delete exporter;
1476}
1477
1478void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1479                                                                          const VssRayContainer &sampleRays)
1480{
1481        if (!ViewCellsConstructed())
1482                return;
1483       
1484        //-- export single view cells
1485        for (int i = 0; i < 10; ++ i)
1486        {
1487                char s[64];
1488                sprintf(s, "vsp_viewcell%04d.x3d", i);
1489                Exporter *exporter = Exporter::GetExporter(s);
1490                const int idx =
1491                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
1492
1493                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
1494
1495                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
1496                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
1497                //-- export geometry
1498                Material m;
1499                m.mDiffuseColor = RgbColor(0, 1, 1);
1500                               
1501                exporter->SetForcedMaterial(m);
1502                exporter->SetWireframe();
1503
1504                ExportVcGeometry(exporter, vc);
1505
1506                //-- export stored rays
1507                if (mExportRays)
1508                {
1509                        vector<VspKdLeaf *>::const_iterator it,
1510                                it_end = vc->mLeaves.end();
1511
1512                        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
1513                        {
1514                                VspKdLeaf *leaf = *it;
1515                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
1516
1517                                VssRayContainer vssRays;
1518
1519                                VssRayContainer castRays;
1520                                VssRayContainer initRays;
1521
1522                                leaf->GetRays(vssRays);
1523
1524                                VssRayContainer::const_iterator it, it_end = vssRays.end();
1525                                const float prop = 200.0f / (float)vssRays.size();
1526
1527                                for (it = vssRays.begin(); it != it_end; ++ it)
1528                                {
1529                                        if (Random(1) < prop)
1530                                                if ((*it)->mTerminationObject == NULL)
1531                                                        castRays.push_back(*it);
1532                                                else
1533                                                        initRays.push_back(*it);
1534                                }
1535
1536                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
1537                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
1538                        }
1539                }
1540
1541                //-- output PVS of view cell
1542                m.mDiffuseColor = RgbColor(1, 0, 0);
1543                exporter->SetForcedMaterial(m);
1544
1545                Intersectable::NewMail();
1546
1547                ObjectPvsMap::const_iterator it,
1548                        it_end = vc->GetPvs().mEntries.end();
1549
1550                exporter->SetFilled();
1551
1552                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1553                {
1554                        Intersectable *intersect = (*it).first;
1555
1556                        if (!intersect->Mailed())
1557                        {
1558                                Material m = RandomMaterial();
1559                                exporter->SetForcedMaterial(m);
1560
1561                                exporter->ExportIntersectable(intersect);
1562                                intersect->Mail();
1563                        }                       
1564                }
1565
1566                delete exporter;
1567        }
1568
1569        //-- export final view cells
1570        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
1571       
1572        //if (exportGeometry) exporter->SetWireframe();
1573        //else exporter->SetFilled();
1574
1575        ExportViewCells(exporter);
1576
1577        if (mExportGeometry)
1578        {
1579                exporter->SetFilled();
1580                exporter->ExportGeometry(objects);
1581        }
1582
1583        if (mExportRays)
1584        {
1585                const float prob = (float)mVisualizationSamples
1586                        / ((float)sampleRays.size() + Limits::Small);
1587               
1588                exporter->SetWireframe();
1589                       
1590                VssRayContainer rays;
1591               
1592                for (int i = 0; i < sampleRays.size(); ++ i)
1593                {
1594                  if (RandomValue(0,1) < prob)
1595                        rays.push_back(sampleRays[i]);
1596                }
1597                exporter->ExportRays(rays, RgbColor(1, 0, 0)); 
1598        }
1599
1600        delete exporter;
1601}
1602
1603int VspKdViewCellsManager::GetType() const
1604{
1605        return VSP_KD;
1606}
1607
1608
1609int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1610                                                                                   const Vector3 &termination,
1611                                                                                   ViewCellContainer &viewcells)
1612{
1613        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
1614}
1615
1616
1617void VspKdViewCellsManager::ExportColor(Exporter *exporter,
1618                                                                                ViewCell *vc) const
1619{
1620        if (mColorCode == 0) // Random color
1621                return;
1622       
1623        float importance = 0;
1624
1625        switch (mColorCode)
1626        {
1627        case 1: // pvs
1628                {
1629                        importance = (float)vc->GetPvs().GetSize() /
1630                                (float)mViewCellsStats.maxPvs;
1631                }
1632                break;
1633        case 2: // merges
1634                {
1635            VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(vc);
1636
1637                        importance = (float)vspKdVc->mLeaves.size() /
1638                                (float)mViewCellsStats.maxLeaves;
1639                }
1640                break;
1641        case 3: // merged tree depth difference
1642                {
1643                        //importance = (float)GetMaxTreeDiff(vc) /
1644                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
1645                }
1646                break;
1647        default:
1648                break;
1649        }
1650
1651        Material m;
1652        m.mDiffuseColor.b = 1.0f;
1653        m.mDiffuseColor.r = importance;
1654        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1655        //Debug << "importance: " << importance << endl;
1656        exporter->SetForcedMaterial(m);
1657}
1658
1659
1660void VspKdViewCellsManager::ExportVcGeometry(Exporter *exporter,
1661                                                                                   ViewCell *vc) const
1662{
1663        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
1664        vector<VspKdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1665
1666        Mesh m;
1667        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
1668        {
1669                mVspKdTree->GetBBox(*it).AddBoxToMesh(&m);
1670        }
1671
1672        exporter->ExportMesh(&m);
1673}
1674
1675
1676/************************************************************************/
1677/*                 VspBspViewCellsManager implementation                */
1678/************************************************************************/
1679
1680
1681VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
1682                                                                                           int constructionSamples):
1683ViewCellsManager(constructionSamples),
1684mVspBspTree(vspBspTree)
1685{
1686        mVspBspTree->SetViewCellsManager(this);
1687}
1688
1689
1690VspBspViewCellsManager::~VspBspViewCellsManager()
1691{
1692}
1693
1694
1695float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
1696{
1697#if 0
1698        return GetArea(viewCell) / GetSceneBbox().SurfaceArea();
1699#else
1700        return GetArea(viewCell) / GetAccVcArea();
1701#endif
1702}
1703
1704
1705void VspBspViewCellsManager::CollectViewCells()
1706{
1707        mVspBspTree->CollectViewCells(mViewCells);
1708}
1709
1710
1711float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
1712                                                                                        float objRendercost) const
1713{
1714        return viewCell->GetPvs().GetSize() * objRendercost;
1715}
1716
1717
1718AxisAlignedBox3 VspBspViewCellsManager::GetSceneBbox() const
1719{
1720        return mVspBspTree->GetBoundingBox();
1721}
1722
1723
1724bool VspBspViewCellsManager::ViewCellsConstructed() const
1725{
1726        return mVspBspTree->GetRoot() != NULL;
1727}
1728
1729
1730ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1731{
1732        return new BspViewCell(mesh);
1733}
1734
1735int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
1736                                                                          const VssRayContainer &rays)
1737{
1738  // if view cells were already constructed
1739  if (ViewCellsConstructed())
1740        return 0;
1741 
1742  Debug << "Constructing bsp view cells" << endl;
1743 
1744  int sampleContributions = 0;
1745 
1746  VssRayContainer sampleRays;
1747 
1748  int limit = min (mConstructionSamples, (int)rays.size());
1749
1750       
1751        VssRayContainer constructionRays;
1752        VssRayContainer savedRays;
1753
1754        GetRaySets(rays, mConstructionSamples, constructionRays, &savedRays);
1755
1756        Debug << "construction rays: " << (int)savedRays.size() << endl;
1757        Debug << "saved rays: " << (int)constructionRays.size() << endl;
1758
1759        mVspBspTree->Construct(constructionRays, &mSceneBox);
1760       
1761        Debug << mVspBspTree->GetStatistics() << endl;
1762
1763        // collapse invalid regions
1764        cout << "collapsing invalid tree regions ... ";
1765        long startTime = GetTime();
1766        mVspBspTree->CollapseTree();
1767        Debug << "tree collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3 << " seconds" << endl;
1768    cout << "finished" << endl;
1769       
1770        cout << "reseting view cell stats ... ";
1771        ResetViewCells();
1772        cout << "finished" << endl;
1773       
1774        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1775
1776        if (1) // export initial view cells
1777        {
1778                cout << "exporting initial view cells (=leaves) ... ";
1779                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
1780       
1781                if (exporter)
1782                {
1783                        //exporter->SetWireframe();
1784                        exporter->SetFilled();
1785                        ExportViewCells(exporter);
1786
1787                        if (0 && mExportRays)
1788                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
1789                       
1790                        if (mExportGeometry)
1791                                exporter->ExportGeometry(objects);
1792                       
1793                        delete exporter;
1794                }
1795                cout << "finished" << endl;
1796        }
1797
1798        startTime = GetTime();
1799        cout << "Computing remaining ray contributions ... ";
1800        // recast rest of rays
1801        ComputeSampleContributions(savedRays);
1802        cout << "finished" << endl;
1803
1804        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
1805                  << " secs" << endl;
1806
1807        cout << "construction finished" << endl;
1808        return sampleContributions;
1809}
1810
1811
1812// matt TODO: remove
1813int VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays) const
1814{
1815        vector<BspIntersection>::const_iterator iit;
1816        vector<BspRay *>bspRays;
1817        int merged = 0;
1818
1819        mVspBspTree->ConstructBspRays(bspRays, rays);
1820
1821        for (int i = 0; i < (int)bspRays.size(); ++ i)
1822        {
1823                BspRay *ray = bspRays[i];
1824         
1825                // traverse leaves stored in the rays and compare and merge consecutive
1826                // leaves (i.e., the neighbors in the tree)
1827                if (ray->intersections.size() < 2)
1828                        continue;
1829         
1830                iit = ray->intersections.begin();
1831
1832                BspLeaf *previousLeaf = (*iit).mLeaf;
1833                ++ iit;
1834               
1835                for (; iit != ray->intersections.end(); ++ iit)
1836                {
1837                        BspLeaf *leaf = (*iit).mLeaf;
1838
1839                        if (ShouldMerge(leaf, previousLeaf))
1840                        {                       
1841                                mVspBspTree->MergeViewCells(leaf, previousLeaf);
1842                                ++ merged;
1843                        }
1844                        previousLeaf = leaf;
1845                }
1846        }
1847        CLEAR_CONTAINER(bspRays);
1848
1849        return merged;
1850}
1851       
1852
1853int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
1854                                                                                const VssRayContainer &rays)
1855{
1856        if (!ViewCellsConstructed())
1857        {
1858                Debug << "view cells not constructed" << endl;
1859                return 0;
1860        }
1861
1862        //-- post processing of bsp view cells
1863    int vcSize = 0;
1864        int pvsSize = 0;
1865
1866        VssRayContainer postProcessRays;
1867        GetRaySets(rays, mPostProcessSamples, postProcessRays);
1868
1869        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
1870        EvaluateViewCellsStats();
1871        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl << endl;
1872
1873        mRenderer->RenderScene();
1874        SimulationStatistics ss;
1875        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1876    Debug << ss << endl;
1877
1878        //-- merge or subdivide view cells
1879        int merged = 0;
1880       
1881        cout << "starting merge using " << mPostProcessSamples << " samples ... ";
1882        long startTime = GetTime();
1883
1884        merged = mVspBspTree->MergeViewCells(postProcessRays);
1885
1886        //-- stats and visualizations
1887        cout << "finished" << endl;
1888        cout << "merged " << merged << " view cells in "
1889                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1890
1891        Debug << "Postprocessing: Merged " << merged << " view cells in "
1892                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1893       
1894        cout << "reseting view cell stats ... ";
1895        ResetViewCells();
1896        cout << "finished" << endl;
1897
1898        //BspLeaf::NewMail();
1899        if (1) // export merged view cells
1900        {
1901                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1902                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
1903
1904                cout << "exporting view cells after merge ... ";
1905
1906                if (exporter)
1907                {
1908                        //exporter->SetWireframe();
1909                        exporter->SetFilled();
1910                        ExportViewCells(exporter);
1911
1912                        if (mExportGeometry)
1913                        {
1914                                Material m;
1915                                m.mDiffuseColor = RgbColor(0, 1, 0);
1916                                exporter->SetForcedMaterial(m);
1917                                exporter->SetFilled();
1918
1919                                exporter->ExportGeometry(objects);
1920                        }
1921
1922                        delete exporter;
1923                }
1924                cout << "finished" << endl;
1925        }
1926
1927        Debug << "render time before refine:" << endl;
1928        mRenderer->RenderScene();
1929        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1930    Debug << ss << endl;
1931
1932        cout << "Refining the merged view cells ... ";
1933        startTime = GetTime();
1934
1935        // refining the merged view cells
1936        const int refined = mVspBspTree->RefineViewCells(rays);
1937
1938        //-- stats and visualizations
1939        cout << "finished" << endl;
1940        cout << "refined " << refined << " view cells in "
1941                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1942
1943        Debug << "Postprocessing: refined " << refined << " view cells in "
1944                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1945       
1946        // collapse sibling leaves that share the same view cell
1947        mVspBspTree->CollapseTree();
1948
1949        // reset view cells and stats
1950        ResetViewCells();
1951
1952        return merged;
1953}
1954
1955
1956int VspBspViewCellsManager::GetType() const
1957{
1958        return VSP_BSP;
1959}
1960
1961
1962bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
1963{
1964        if (!ViewCellsConstructed())
1965                return ViewCellsManager::GetViewPoint(viewPoint);
1966
1967        // TODO: set reasonable limit
1968        const int limit = 20;
1969
1970        for (int i = 0; i < limit; ++ i)
1971        {
1972                viewPoint = mSceneBox.GetRandomPoint();
1973                if (mVspBspTree->ViewPointValid(viewPoint))
1974                {
1975                        return true;
1976                }
1977        }
1978        Debug << "failed to find valid view point, taking " << viewPoint << endl;
1979        return false;
1980}
1981
1982
1983bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
1984{
1985        return mSceneBox.IsInside(viewPoint) &&
1986                   mVspBspTree->ViewPointValid(viewPoint);
1987}
1988
1989
1990void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
1991                                                                           const VssRayContainer &sampleRays)
1992{
1993        if (!ViewCellsConstructed())
1994                return;
1995
1996        VssRayContainer visRays;
1997        GetRaySets(sampleRays, mVisualizationSamples, visRays);
1998
1999        if (1) // export view cells
2000        {
2001                cout << "exporting view cells after post process ... ";
2002                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2003
2004                if (exporter)
2005                {
2006                        if (mExportGeometry)
2007                                exporter->ExportGeometry(objects);
2008
2009                        // export rays
2010                        if (mExportRays)
2011                        {
2012                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2013                        }
2014
2015                        ExportViewCells(exporter);
2016                        delete exporter;
2017                }
2018               
2019                cout << "finished" << endl;
2020        }       
2021
2022        //-- visualization of the BSP splits
2023        bool exportSplits = false;
2024        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2025       
2026        if (exportSplits)
2027        {
2028                cout << "exporting splits ... ";
2029                ExportSplits(objects, visRays);
2030                cout << "finished" << endl;
2031        }
2032
2033        // export single view cells
2034        ExportBspPvs(objects, visRays);
2035}
2036       
2037
2038void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2039                                                                                  const VssRayContainer &rays)
2040{
2041        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2042
2043        if (exporter)
2044        {       
2045                Material m;
2046                m.mDiffuseColor = RgbColor(1, 0, 0);
2047                exporter->SetForcedMaterial(m);
2048                exporter->SetWireframe();
2049               
2050                exporter->ExportBspSplits(*mVspBspTree, true);
2051
2052                // take forced material, else big scenes cannot be viewed
2053                m.mDiffuseColor = RgbColor(0, 1, 0);
2054                exporter->SetForcedMaterial(m);
2055                exporter->SetFilled();
2056
2057                exporter->ResetForcedMaterial();
2058               
2059                // export rays
2060                if (mExportRays)
2061                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
2062       
2063                if (mExportGeometry)
2064                        exporter->ExportGeometry(objects);
2065
2066                delete exporter;
2067        }
2068}
2069
2070void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2071                                                                                  const VssRayContainer &rays)
2072{
2073        const int leafOut = 10;
2074       
2075        ViewCell::NewMail();
2076       
2077        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2078        Debug << "\nOutput view cells: " << endl;
2079       
2080        // sort view cells to visualize the largest view cells
2081#if 0
2082        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2083#endif
2084        int limit = min(leafOut, (int)mViewCells.size());
2085
2086#if 1
2087        //-- some rays for output
2088        vector<BspRay *> bspRays;
2089        mVspBspTree->ConstructBspRays(bspRays, rays);
2090
2091        const int raysOut = min((int)bspRays.size(), mVisualizationSamples);
2092#endif
2093
2094        for (int i = 0; i < limit; ++ i)
2095        {
2096                cout << "creating output for view cell " << i << " ... ";
2097               
2098                VssRayContainer vcRays;
2099                Intersectable::NewMail();
2100#if 0
2101                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
2102#else
2103                BspViewCell *vc = dynamic_cast<BspViewCell *>
2104                        (mViewCells[Random((int)mViewCells.size())]);
2105#endif
2106
2107#if 1
2108                // check whether we can add the current ray to the output rays
2109                for (int k = 0; k < raysOut; ++ k)
2110                {
2111                        BspRay *ray = bspRays[k];
2112                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
2113                        {
2114                                BspLeaf *leaf = ray->intersections[j].mLeaf;
2115                                if (vc == leaf->GetViewCell())
2116                                        vcRays.push_back(ray->vssRay);
2117                        }
2118                }
2119#endif
2120                //bspLeaves[j]->Mail();
2121                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2122                Exporter *exporter = Exporter::GetExporter(s);
2123                exporter->SetWireframe();
2124
2125                Material m;//= RandomMaterial();
2126                m.mDiffuseColor = RgbColor(0, 1, 0);
2127                exporter->SetForcedMaterial(m);
2128
2129                ExportVcGeometry(exporter, vc);
2130                       
2131                               
2132                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
2133                          << ", piercing rays=" << (int)vcRays.size()
2134                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
2135               
2136                //-- export rays piercing this view cell
2137#if 1
2138                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2139#endif
2140#if 0
2141                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
2142
2143                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2144                        exporter->ExportRays((*lit)->mVssRays);
2145#endif
2146                m.mDiffuseColor = RgbColor(1, 0, 0);
2147                exporter->SetForcedMaterial(m);
2148
2149                ObjectPvsMap::const_iterator it,
2150                        it_end = vc->GetPvs().mEntries.end();
2151
2152                exporter->SetFilled();
2153
2154                // output PVS of view cell
2155                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2156                {
2157                        Intersectable *intersect = (*it).first;
2158
2159                        if (!intersect->Mailed())
2160                        {
2161                                Material m = RandomMaterial();
2162                                exporter->SetForcedMaterial(m);
2163
2164                                exporter->ExportIntersectable(intersect);
2165                                intersect->Mail();
2166                        }                       
2167                }
2168                               
2169                DEL_PTR(exporter);
2170                cout << "finished" << endl;
2171        }
2172
2173#if 1
2174        CLEAR_CONTAINER(bspRays);
2175#endif
2176        Debug << endl;
2177}
2178
2179
2180bool VspBspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
2181{
2182        ViewCell *fvc = front->GetViewCell();
2183        ViewCell *bvc = back->GetViewCell();
2184
2185        if (fvc == bvc)
2186                return false;
2187
2188        const int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
2189
2190        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
2191        {
2192                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
2193                        (bvc->GetPvs().GetSize() < mMinPvs) ||
2194                        ((fdiff < mMinPvsDif) &&
2195                         (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
2196                {
2197                        return true;
2198                }
2199        }
2200       
2201        return false;
2202}
2203
2204
2205int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2206                                                                                        const Vector3 &termination,
2207                                                                                        ViewCellContainer &viewcells)
2208{
2209        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
2210}
2211
2212
2213void VspBspViewCellsManager::ExportColor(Exporter *exporter,
2214                                                                                 ViewCell *vc) const
2215{
2216        if (mColorCode == 0) // Random color
2217                return;
2218       
2219        float importance = 0;
2220
2221        switch (mColorCode)
2222        {
2223        case 1: // pvs
2224                {
2225                        importance = (float)vc->GetPvs().GetSize() /
2226                                (float)mViewCellsStats.maxPvs;
2227                }
2228                break;
2229        case 2: // merges
2230                {
2231            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2232
2233                        importance = (float)bspVc->mLeaves.size() /
2234                                (float)mViewCellsStats.maxLeaves;
2235                }
2236                break;
2237        case 3: // merge tree differene
2238                {
2239                        importance = (float)GetMaxTreeDiff(vc) /
2240                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2241                }
2242                break;
2243        default:
2244                break;
2245        }
2246
2247        Material m;
2248        m.mDiffuseColor.b = 1.0f;
2249        m.mDiffuseColor.r = importance;
2250        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2251        //Debug << "importance: " << importance << endl;
2252        exporter->SetForcedMaterial(m);
2253}
2254
2255
2256void VspBspViewCellsManager::ExportVcGeometry(Exporter *exporter,
2257                                                                                          ViewCell *vc) const
2258{
2259#if 1
2260        BspNodeGeometry geom;
2261        mVspBspTree->
2262                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom.mPolys);
2263        exporter->ExportPolygons(geom.mPolys);
2264#else
2265       
2266        Material m2;
2267        m2.mDiffuseColor.b = 0.3f + Random(0.7f);
2268        m2.mDiffuseColor.r = 0.0f;//0.3f + Random(0.7f);
2269        m2.mDiffuseColor.g = 0.3f + Random(0.7f);
2270        Material m;
2271        m.mDiffuseColor.b = 0.0f;
2272        m.mDiffuseColor.r = 1.0f;
2273        m.mDiffuseColor.g = 0.0f;
2274
2275        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2276        vector<BspLeaf *>::const_iterator it, it_end = bspVc->mLeaves.end();
2277
2278        for (it = bspVc->mLeaves.begin(); it != it_end; ++ it)
2279        {
2280                if ((*it)->Mailed())
2281                        exporter->SetForcedMaterial(m);
2282                else
2283                        exporter->SetForcedMaterial(m2);
2284                        //exporter->ResetForcedMaterial();
2285                BspNodeGeometry geom;
2286                mVspBspTree->ConstructGeometry(*it, geom);
2287                exporter->ExportPolygons(geom.mPolys);
2288        }
2289#endif
2290}
2291
2292
2293int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
2294{
2295        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2296
2297        int maxDist = 0;
2298        // compute max height difference
2299        for (int i = 0; i < (int)bspVc->mLeaves.size(); ++ i)
2300                for (int j = 0; j < (int)bspVc->mLeaves.size(); ++ j)
2301        {
2302                BspLeaf *leaf = bspVc->mLeaves[i];
2303
2304                if (i != j)
2305                {
2306                        BspLeaf *leaf2 = bspVc->mLeaves[j];
2307                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
2308                        if (dist > maxDist)
2309                                maxDist = dist;
2310                }
2311        }
2312        return maxDist;
2313}
2314
2315
2316
2317
2318ViewCell *
2319VspBspViewCellsManager::GetViewCell(const Vector3 &point)
2320{
2321  if (!mVspBspTree)
2322        return NULL;
2323  return mVspBspTree->GetViewCell(point);
2324}
Note: See TracBrowser for help on using the repository browser.