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

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