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

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