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

Revision 508, 56.5 KB checked in by mattausch, 19 years ago (diff)

implemented view cells exporting / loading
improved vsp bsp tree (only axis aligbed until a level), reuse results from Plane
testing, collectmergeneighbors
implemented view cell meshes

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