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

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