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

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