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

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