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

Revision 551, 59.2 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
2074        if (1)
2075        {
2076                FinalizeViewCells(false);
2077        }
2078
2079        //-- merge the individual view cells
2080        MergeViewCells(postProcessRays, objects);
2081        //-- refines the merged view cells
2082        RefineViewCells(postProcessRays);
2083        // collapse sibling leaves that share the same view cell
2084        mVspBspTree->CollapseTree();
2085
2086        ResetViewCells();
2087
2088        // real meshes are only contructed only at this stage
2089        //CreateViewCellMeshes();
2090        FinalizeViewCells(true);
2091
2092        // write view cells to disc
2093        if (mExportViewCells)
2094        {
2095                char buff[100];
2096                environment->GetStringValue("ViewCells.filename", buff);
2097                string vcFilename(buff);
2098
2099                ExportViewCells(buff);
2100        }
2101
2102        return 0;
2103}
2104
2105
2106int VspBspViewCellsManager::GetType() const
2107{
2108        return VSP_BSP;
2109}
2110
2111
2112bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2113{
2114        if (!ViewCellsConstructed())
2115                return ViewCellsManager::GetViewPoint(viewPoint);
2116
2117        // TODO: set reasonable limit
2118        const int limit = 20;
2119
2120        for (int i = 0; i < limit; ++ i)
2121        {
2122                viewPoint = mViewSpaceBox.GetRandomPoint();
2123                if (mVspBspTree->ViewPointValid(viewPoint))
2124                {
2125                        return true;
2126                }
2127        }
2128        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2129        return false;
2130}
2131
2132
2133bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2134{
2135        return mViewSpaceBox.IsInside(viewPoint) &&
2136                   mVspBspTree->ViewPointValid(viewPoint);
2137}
2138
2139
2140void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2141                                                                           const VssRayContainer &sampleRays)
2142{
2143        if (!ViewCellsConstructed())
2144                return;
2145
2146        VssRayContainer visRays;
2147        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2148
2149        if (1) // export view cells
2150        {
2151                cout << "exporting view cells after post process ... ";
2152                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2153
2154                if (exporter)
2155                {
2156                        if (1)
2157                        {
2158                                exporter->SetWireframe();
2159                                exporter->ExportBox(mViewSpaceBox);
2160                                exporter->SetFilled();
2161                        }
2162
2163                        if (mExportGeometry)
2164                        {
2165                                exporter->ExportGeometry(objects);
2166                        }
2167
2168                        // export rays
2169                        if (mExportRays)
2170                        {
2171                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2172                        }
2173
2174                        ExportViewCellsForViz(exporter);
2175                        delete exporter;
2176                }
2177
2178                cout << "finished" << endl;
2179        }
2180
2181        //-- visualization of the BSP splits
2182        bool exportSplits = false;
2183        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2184
2185        if (exportSplits)
2186        {
2187                cout << "exporting splits ... ";
2188                ExportSplits(objects, visRays);
2189                cout << "finished" << endl;
2190        }
2191
2192        //-- export single view cells
2193        ExportBspPvs(objects, visRays);
2194}
2195
2196
2197void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2198                                                                                  const VssRayContainer &rays)
2199{
2200        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2201
2202        if (exporter)
2203        {
2204                Material m;
2205                m.mDiffuseColor = RgbColor(1, 0, 0);
2206                exporter->SetForcedMaterial(m);
2207                exporter->SetWireframe();
2208
2209                exporter->ExportBspSplits(*mVspBspTree, true);
2210
2211                // take forced material, else big scenes cannot be viewed
2212                m.mDiffuseColor = RgbColor(0, 1, 0);
2213                exporter->SetForcedMaterial(m);
2214                exporter->SetFilled();
2215
2216                exporter->ResetForcedMaterial();
2217
2218                // export rays
2219                if (mExportRays)
2220                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
2221
2222                if (mExportGeometry)
2223                        exporter->ExportGeometry(objects);
2224
2225                delete exporter;
2226        }
2227}
2228
2229
2230void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2231                                                                                  const VssRayContainer &rays)
2232{
2233        const int leafOut = 10;
2234
2235        ViewCell::NewMail();
2236
2237        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2238        Debug << "\nOutput view cells: " << endl;
2239
2240        // sort view cells to visualize the largest view cells
2241#if 0
2242        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2243#endif
2244        int limit = min(leafOut, (int)mViewCells.size());
2245
2246#if 1
2247        //-- some rays for output
2248        vector<BspRay *> bspRays;
2249        mVspBspTree->ConstructBspRays(bspRays, rays);
2250
2251        const int raysOut = min((int)bspRays.size(), mVisualizationSamples);
2252#endif
2253
2254        for (int i = 0; i < limit; ++ i)
2255        {
2256                cout << "creating output for view cell " << i << " ... ";
2257
2258                VssRayContainer vcRays;
2259                Intersectable::NewMail();
2260#if 0 // largest view cell pvs first
2261                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
2262#else
2263                BspViewCell *vc = dynamic_cast<BspViewCell *>
2264                        (mViewCells[Random((int)mViewCells.size())]);
2265#endif
2266
2267#if 1
2268                // check whether we can add the current ray to the output rays
2269                for (int k = 0; k < raysOut; ++ k)
2270                {
2271                        BspRay *ray = bspRays[k];
2272                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
2273                        {
2274                                BspLeaf *leaf = ray->intersections[j].mLeaf;
2275                                if (vc == leaf->GetViewCell())
2276                                        vcRays.push_back(ray->vssRay);
2277                        }
2278                }
2279#endif
2280                //bspLeaves[j]->Mail();
2281                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2282                Exporter *exporter = Exporter::GetExporter(s);
2283                exporter->SetWireframe();
2284
2285                Material m;//= RandomMaterial();
2286                m.mDiffuseColor = RgbColor(0, 1, 0);
2287                exporter->SetForcedMaterial(m);
2288
2289                ExportVcGeometry(exporter, vc);
2290
2291
2292                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
2293                          << ", piercing rays=" << (int)vcRays.size()
2294                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
2295
2296                //-- export rays piercing this view cell
2297#if 1
2298                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2299#endif
2300#if 0
2301                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
2302
2303                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2304                        exporter->ExportRays((*lit)->mVssRays);
2305#endif
2306                m.mDiffuseColor = RgbColor(1, 0, 0);
2307                exporter->SetForcedMaterial(m);
2308
2309                ObjectPvsMap::const_iterator it,
2310                        it_end = vc->GetPvs().mEntries.end();
2311
2312                exporter->SetFilled();
2313
2314                // output PVS of view cell
2315                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2316                {
2317                        Intersectable *intersect = (*it).first;
2318
2319                        if (!intersect->Mailed())
2320                        {
2321                                Material m = RandomMaterial();
2322                                exporter->SetForcedMaterial(m);
2323
2324                                exporter->ExportIntersectable(intersect);
2325                                intersect->Mail();
2326                        }
2327                }
2328
2329                DEL_PTR(exporter);
2330                cout << "finished" << endl;
2331        }
2332
2333#if 1
2334        CLEAR_CONTAINER(bspRays);
2335#endif
2336        Debug << endl;
2337}
2338
2339
2340int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2341                                                                                        const Vector3 &termination,
2342                                                                                        ViewCellContainer &viewcells)
2343{
2344        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
2345}
2346
2347
2348void VspBspViewCellsManager::ExportColor(Exporter *exporter,
2349                                                                                 ViewCell *vc) const
2350{
2351        if (CheckValid(vc) && (mColorCode == 0)) // Random color
2352                return;
2353
2354        float importance = 0;
2355       
2356        Material m;
2357       
2358        switch (mColorCode)
2359        {
2360        case 1: // pvs
2361                {
2362                        importance = (float)vc->GetPvs().GetSize() /
2363                                (float)mViewCellsStats.maxPvs;
2364                }
2365                break;
2366        case 2: // merges
2367                {
2368            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2369
2370                        importance = (float)bspVc->mLeaves.size() /
2371                                (float)mViewCellsStats.maxLeaves;
2372
2373                        if (CheckValid(vc))
2374                                m.mDiffuseColor.b = 1.0f;
2375                        m.mDiffuseColor.r = importance;
2376                        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2377                }
2378                break;
2379        case 3: // merge tree differene
2380                {
2381                        importance = (float)GetMaxTreeDiff(vc) /
2382                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2383
2384                        if (CheckValid(vc))
2385                                m.mDiffuseColor.b = 1.0f;
2386                        m.mDiffuseColor.r = importance;
2387                        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2388                }
2389                break;
2390        default:
2391                break;
2392        }
2393
2394        m.mDiffuseColor.b = CheckValid(vc) ? 1.0f : 0.0f;
2395        m.mDiffuseColor.r = importance;
2396        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2397
2398        //Debug << "importance: " << importance << endl;
2399        exporter->SetForcedMaterial(m);
2400}
2401
2402
2403void VspBspViewCellsManager::ExportVcGeometry(Exporter *exporter,
2404                                                                                          ViewCell *vc) const
2405{
2406        if (vc->GetMesh())
2407        {
2408                exporter->ExportMesh(vc->GetMesh());
2409                return;
2410        }
2411
2412        BspNodeGeometry geom;
2413        mVspBspTree->
2414                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom);
2415        exporter->ExportPolygons(geom.mPolys);
2416}
2417
2418
2419int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
2420{
2421        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2422
2423        int maxDist = 0;
2424        // compute max height difference
2425        for (int i = 0; i < (int)bspVc->mLeaves.size(); ++ i)
2426                for (int j = 0; j < (int)bspVc->mLeaves.size(); ++ j)
2427        {
2428                BspLeaf *leaf = bspVc->mLeaves[i];
2429
2430                if (i != j)
2431                {
2432                        BspLeaf *leaf2 = bspVc->mLeaves[j];
2433                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
2434                        if (dist > maxDist)
2435                                maxDist = dist;
2436                }
2437        }
2438        return maxDist;
2439}
2440
2441
2442ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point)
2443{
2444        if (!mVspBspTree)
2445                return NULL;
2446        return mVspBspTree->GetViewCell(point);
2447}
2448
2449
2450void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
2451{
2452        BspNodeGeometry geom;
2453        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2454        mVspBspTree->ConstructGeometry(bspVc, geom);
2455
2456        Mesh *mesh = new Mesh();
2457        geom.AddToMesh(*mesh);
2458        vc->SetMesh(mesh);
2459        mMeshContainer.push_back(mesh);
2460}
2461
2462
2463bool VspBspViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
2464{
2465        ViewCellsParser parser;
2466       
2467        DEL_PTR(mVspBspTree);
2468        mVspBspTree = new VspBspTree();
2469       
2470        bool success = parser.ParseFile(filename, mVspBspTree, this, objects);
2471        mVspBspTree->RepairViewCellsLeafLists();
2472        mVspBspTree->mBox = GetViewSpaceBox();
2473        ResetViewCells();
2474        CreateViewCellMeshes();
2475
2476        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
2477
2478        mViewCellsFinished = true;
2479
2480        return success;
2481}
2482
2483
2484inline bool ilt(Intersectable *obj1, Intersectable *obj2)
2485{
2486        return obj1->mId < obj2->mId;
2487}
2488
2489
2490bool VspBspViewCellsManager::ExportViewCells(const string filename)
2491{
2492        cout << "exporting view cells to xml ... ";
2493        std::ofstream stream;
2494
2495        // for output we need unique ids
2496        CreateUniqueViewCellIds();
2497
2498        stream.open(filename.c_str());
2499        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2500        stream << "<Visibility_Solution>" << endl;
2501       
2502        //-- load the view cells itself, i.e., the ids and the pvs
2503        stream << "<ViewCells>" << endl;
2504        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2505        for (it = mViewCells.begin(); it != it_end; ++ it)
2506                ExportViewCell(*it, stream);
2507   
2508        stream << "</ViewCells>" << endl;
2509       
2510        //-- load the hierarchy
2511        stream << "<BspTree>" << endl;
2512        mVspBspTree->Export(stream);
2513        stream << endl << "</BspTree>" << endl;
2514       
2515        stream << "</Visibility_Solution>" << endl;
2516        stream.close();
2517
2518        cout << "finished" << endl;
2519
2520        return true;
2521}
2522
2523
2524int VspBspViewCellsManager::CastBeam(Beam &beam)
2525{
2526        return mVspBspTree->CastBeam(beam);
2527}
2528
2529
2530void VspBspViewCellsManager::Finalize(ViewCell *viewCell)
2531{
2532        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCell);
2533        CreateMesh(vc);
2534
2535        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
2536
2537        float area = 0;
2538        float volume = 0;
2539
2540        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
2541        {
2542                BspNodeGeometry geom;
2543                BspLeaf *leaf = *it;
2544                mVspBspTree->ConstructGeometry(leaf, geom);
2545
2546                area += geom.GetArea();
2547                volume += geom.GetVolume();
2548        }
2549
2550        viewCell->SetVolume(volume);
2551        viewCell->SetArea(area);
2552}
Note: See TracBrowser for help on using the repository browser.