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

Revision 556, 59.4 KB checked in by bittner, 18 years ago (diff)

debug version looking for glrenderer bug...

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