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

Revision 503, 54.3 KB checked in by mattausch, 19 years ago (diff)

added mesh creation function

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