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

Revision 555, 59.4 KB checked in by mattausch, 18 years ago (diff)

fixed bug in finalizeviewcells when loading view cells

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