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

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