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

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