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

Revision 477, 49.2 KB checked in by mattausch, 19 years ago (diff)

changed render simulator (probability that view cell is crossed)

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
14
15ViewCellsManager::ViewCellsManager():
16mRenderSimulator(NULL),
17mConstructionSamples(0),
18mPostProcessSamples(0),
19mVisualizationSamples(0),
20mTotalAreaValid(false),
21mTotalArea(0.0f)
22{
23        // post processing stuff
24        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
25        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
26        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
27}
28
29ViewCellsManager::ViewCellsManager(int constructionSamples):
30mConstructionSamples(constructionSamples),
31mRenderSimulator(NULL),
32mPostProcessSamples(0),
33mVisualizationSamples(0)
34{
35        // post processing stuff
36        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
37        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
38        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
39}
40
41ViewCellsManager::~ViewCellsManager()
42{
43        DEL_PTR(mRenderSimulator);
44
45        CLEAR_CONTAINER(mViewCells);
46}
47
48bool ViewCellsManager::LoadViewCells(const string filename)
49{
50        X3dParser parser;
51       
52        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
53       
54        bool success = parser.ParseFile(filename, *this);
55        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
56
57        return success;
58}
59
60void ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays)
61{
62        // view cells not yet constructed
63        if (!ViewCellsConstructed())
64                return;
65 
66        VssRayContainer::const_iterator it, it_end = rays.end();
67       
68        for (it = rays.begin(); it != it_end; ++ it)
69        {
70                ComputeSampleContributions(*(*it));
71        }
72}
73
74void ViewCellsManager::AddViewCell(ViewCell *viewCell)
75{
76        mViewCells.push_back(viewCell);
77}
78
79void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
80                                                                           ViewCellContainer &viewCells,
81                                                                           const int maxViewCells) const
82{
83        // maximal max viewcells
84        int limit = maxViewCells > 0 ?
85                Min((int)objects.size(), maxViewCells) : (int)objects.size();
86
87        for (int i = 0; i < limit; ++ i)
88        {
89                Intersectable *object = objects[i];
90               
91                // extract the mesh instances
92                if (object->Type() == Intersectable::MESH_INSTANCE)
93                {
94                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
95
96                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
97                        viewCells.push_back(viewCell);
98                }
99                //TODO: transformed meshes
100        }
101}
102
103ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
104                                                                                        const float height) const
105{
106        // one mesh per view cell
107        Mesh *mesh = new Mesh();
108       
109        //-- construct prism
110
111        // bottom
112        mesh->mFaces.push_back(new Face(2,1,0));
113        // top
114    mesh->mFaces.push_back(new Face(3,4,5));
115        // sides
116        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
117        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
118        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
119
120        //--- extrude new vertices for top of prism
121        Vector3 triNorm = baseTri.GetNormal();
122
123        Triangle3 topTri;       
124
125        // add base vertices and calculate top vertices
126        for (int i = 0; i < 3; ++ i)
127                mesh->mVertices.push_back(baseTri.mVertices[i]);
128       
129        // add top vertices     
130        for (int i = 0; i < 3; ++ i)
131                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
132       
133        mesh->Preprocess();
134
135        return GenerateViewCell(mesh);
136}
137
138ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
139{
140        // generate merged view cell
141        ViewCell *vc = GenerateViewCell();
142
143        // merge pvs
144        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
145
146        //-- merge ray sets
147        stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
148        stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
149
150        std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
151                           back.mPiercingRays.begin(), back.mPiercingRays.end(),
152                           vc->mPiercingRays.begin());
153
154        return vc;
155}
156
157
158ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
159{
160        return new ViewCell(mesh);
161}
162
163
164void ViewCellsManager::SetVisualizationSamples(const int visSamples)
165{
166        mVisualizationSamples = visSamples;
167}
168
169void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
170{
171        mConstructionSamples = constructionSamples;
172}
173
174void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
175{
176        mPostProcessSamples = postProcessSamples;
177}
178
179int ViewCellsManager::GetVisualizationSamples() const
180{
181        return mVisualizationSamples;
182}
183
184int ViewCellsManager::GetConstructionSamples() const
185{
186        return mConstructionSamples;
187}
188
189int ViewCellsManager::GetPostProcessSamples() const
190{
191        return mPostProcessSamples;
192}
193
194void
195ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
196{
197  ViewCellContainer::const_iterator it = mViewCells.begin();
198  stat.viewcells = 0;
199  stat.minPvs = 100000000;
200  stat.maxPvs = 0;
201  stat.avgPvs = 0.0f;
202
203  for (; it != mViewCells.end(); ++it) {
204        ViewCell *viewcell = *it;
205        int pvsSize = viewcell->GetPvs().GetSize();
206        if ( pvsSize < stat.minPvs)
207          stat.minPvs = pvsSize;
208        if (pvsSize > stat.maxPvs)
209          stat.maxPvs = pvsSize;
210        stat.avgPvs += pvsSize;
211        stat.viewcells++;
212  }
213  if (stat.viewcells)
214        stat.avgPvs/=stat.viewcells;
215}
216
217void
218ViewCellsManager::PrintPvsStatistics(ostream &s)
219{
220  s<<"############# Viewcell PVS STAT ##################\n";
221  PvsStatistics pvsStat;
222  GetPvsStatistics(pvsStat);
223  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
224  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
225  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
226}
227
228ViewCellContainer &ViewCellsManager::GetViewCells()
229{
230        return mViewCells;
231}
232
233void ViewCellsManager::ComputeSampleContributions(VssRay &ray)
234{
235        ViewCellContainer viewcells;
236       
237        CastLineSegment(ray.mOrigin,
238                                        ray.mTermination,
239                                        viewcells);
240       
241        ray.mPvsContribution = 0;
242        ray.mRelativePvsContribution = 0.0f;
243 
244        ViewCellContainer::const_iterator it = viewcells.begin();
245       
246        for (; it != viewcells.end(); ++it)
247        {       
248                ViewCell *viewcell = *it;
249       
250                // if ray not outside of view space
251                float contribution;
252                bool added =
253                        viewcell->GetPvs().AddSample(ray.mTerminationObject,
254                                                                                 contribution);
255               
256                if (added)
257                        ++ ray.mPvsContribution;
258               
259                ray.mRelativePvsContribution += contribution;
260        }
261}
262
263
264void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
265                                                                  VssRayContainer &constructionRays,
266                                                                  VssRayContainer &savedRays) const
267{
268        const int limit = min(mConstructionSamples, (int)sourceRays.size());
269
270        VssRayContainer::const_iterator it, it_end = sourceRays.end();
271       
272        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
273
274        for (it = sourceRays.begin(); it != it_end; ++ it)
275        {
276                if (Random(1.0f) < prop)
277                        constructionRays.push_back(*it);
278                else
279                        savedRays.push_back(*it);
280        }
281}
282
283
284float ViewCellsManager::GetVolume(ViewCell *viewCell) const
285{
286        return viewCell->GetVolume();
287}
288
289
290float ViewCellsManager::GetArea(ViewCell *viewCell) const
291{
292        return 0.0f;
293}
294
295
296float ViewCellsManager::GetAccVcArea()
297{
298        // if already computed
299        if (mTotalAreaValid)
300                return mTotalArea;
301
302        mTotalArea = 0;
303        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
304
305        for (it = mViewCells.begin(); it != it_end; ++ it)
306        mTotalArea += GetArea(*it);
307       
308        mTotalAreaValid = true;
309
310        return mTotalArea;
311}
312
313void ViewCellsManager::PrintStatistics(ostream &s) const
314{
315        s << mViewCellsStats << endl;
316}
317
318
319/**********************************************************************/
320/*                   BspViewCellsManager implementation               */
321/**********************************************************************/
322
323BspViewCellsManager::BspViewCellsManager(BspTree *bspTree,
324                                                                                 int constructionSamples):
325ViewCellsManager(constructionSamples),
326mBspTree(bspTree)
327{
328}
329
330
331bool BspViewCellsManager::ViewCellsConstructed() const
332{
333        return mBspTree->GetRoot() != NULL;
334}
335
336ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
337{
338        return new BspViewCell(mesh);
339}
340
341int BspViewCellsManager::Construct(const ObjectContainer &objects,
342                                                                   const VssRayContainer &rays,
343                                                                   AxisAlignedBox3 *sceneBbox)
344{
345        // if view cells were already constructed
346        if (ViewCellsConstructed())
347                return 0;
348
349        int sampleContributions = 0;
350       
351        // construct view cells using the collected samples
352        RayContainer constructionRays;
353        VssRayContainer savedRays;
354
355        const int limit = min(mConstructionSamples, (int)rays.size());
356
357        VssRayContainer::const_iterator it, it_end = rays.end();
358
359        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
360
361        for (it = rays.begin(); it != it_end; ++ it)
362        {
363                if (Random(1.0f) < prop)
364                        constructionRays.push_back(new Ray(*(*it)));
365                else
366                        savedRays.push_back(*it);
367        }
368
369    if (mViewCells.empty())
370        {
371                // no view cells loaded
372                mBspTree->Construct(objects, constructionRays);
373                // collect final view cells
374                mBspTree->CollectViewCells(mViewCells);
375        }
376        else
377        {
378                mBspTree->Construct(mViewCells);
379        }
380
381        mBspTree->EvaluateViewCellsStats(mViewCellsStats);
382
383        // destroy rays created only for construction
384        CLEAR_CONTAINER(constructionRays);
385
386        Debug << mBspTree->GetStatistics() << endl;
387       
388        // recast rest of the rays
389        ComputeSampleContributions(savedRays);
390
391        return sampleContributions;
392}
393
394float BspViewCellsManager::GetArea(ViewCell *viewCell) const
395{
396        PolygonContainer geom;
397
398        // compute view cell area
399        mBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(viewCell), geom);
400       
401        const float area = Polygon3::GetArea(geom);
402        CLEAR_CONTAINER(geom);
403
404        return area;
405}
406
407
408float BspViewCellsManager::GetProbability(ViewCell *viewCell)
409{
410        // compute view cell area as subsititute for probability
411#if 0
412        return GetArea(viewCell) / mBspTree->GetBoundingBox().SurfaceArea();
413#else
414        return GetArea(viewCell) / GetAccVcArea();
415#endif
416}
417
418
419float BspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
420{
421        return viewCell->GetPvs().GetSize() * objRendercost;
422}
423
424
425AxisAlignedBox3 BspViewCellsManager::GetSceneBbox() const
426{
427        return mBspTree->GetBoundingBox();
428}
429
430
431int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
432                                                                                 const Vector3 &termination,
433                                                                                 ViewCellContainer &viewcells)
434{
435        return mBspTree->CastLineSegment(origin, termination, viewcells);
436}
437
438
439int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
440                                                                         const VssRayContainer &rays)
441{
442        if (mBspRays.empty())
443                ConstructBspRays(rays, mConstructionSamples);
444       
445        if (!ViewCellsConstructed())
446        {
447                Debug << "view cells not constructed" << endl;
448                return 0;
449        }
450
451        //-- post processing of bsp view cells
452    int vcSize = 0;
453        int pvsSize = 0;
454
455        Debug << "original view cell partition:\n" << mViewCellsStats << endl;
456               
457        if (1) // export view cells
458        {
459                cout << "exporting initial view cells (=leaves) ... ";
460                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
461       
462                if (exporter)
463                {
464                        //exporter->SetWireframe();
465                        exporter->SetFilled();
466                        exporter->ExportBspViewCellPartition(*mBspTree,
467                                mViewCellsStats.maxPvs);
468                               
469                        if (0)
470                        {
471                                Material m;
472                                m.mDiffuseColor = RgbColor(0, 1, 0);
473                                exporter->SetForcedMaterial(m);
474                                exporter->SetWireframe();
475
476                                exporter->ExportGeometry(objects);
477                        }
478
479                        delete exporter;
480                }
481                cout << "finished" << endl;
482        }
483
484        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
485               
486        long startTime = GetTime();
487
488
489        // $$JB we do not have connectivity information from the ray in the moment
490        // perhaps we could recast the rays or rember the cells traversed inside the
491        // vssray (which would on other hand create some overhead)
492        //-- merge or subdivide view cells
493        int merged = 0;
494
495        vector<BspIntersection>::const_iterator iit;
496
497        for (int i = 0; i < (int)mBspRays.size(); ++ i)
498        { 
499                BspRay *ray = mBspRays[i];
500         
501                // traverse leaves stored in the rays and compare and merge consecutive
502                // leaves (i.e., the neighbors in the tree)
503                if (ray->intersections.size() < 2)
504                        continue;
505         
506                iit = ray->intersections.begin();
507
508                BspLeaf *previousLeaf = (*iit).mLeaf;
509                ++ iit;
510               
511                for (; iit != ray->intersections.end(); ++ iit)
512                {
513                        BspLeaf *leaf = (*iit).mLeaf;
514
515                        if (ShouldMerge(leaf, previousLeaf))
516                        {                       
517                                MergeBspLeafViewCells(leaf, previousLeaf);
518
519                                ++ merged;
520                        }
521               
522                        previousLeaf = leaf;
523                }
524        }
525
526        //-- stats and visualizations
527        cout << "finished" << endl;
528        cout << "merged " << merged << " view cells in "
529                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
530
531        Debug << "Postprocessing: Merged " << merged << " view cells in "
532                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
533       
534        // reset view cells and stats
535        mViewCells.clear();
536        mBspTree->CollectViewCells(mViewCells);
537        mViewCellsStats.Reset();
538        mBspTree->EvaluateViewCellsStats(mViewCellsStats);
539
540        return merged;
541}
542
543
544BspViewCellsManager::~BspViewCellsManager()
545{
546        CLEAR_CONTAINER(mBspRays);
547}
548
549
550int BspViewCellsManager::GetType() const
551{
552        return BSP;
553}
554
555
556void BspViewCellsManager::Visualize(const ObjectContainer &objects,
557                                                                        const VssRayContainer &sampleRays)
558{
559        if (!ViewCellsConstructed())
560                return;
561
562        if (mBspRays.empty())
563                ConstructBspRays(sampleRays, mConstructionSamples);
564       
565        if (1) // export view cells
566        {
567                cout << "exporting view cells after merge ... ";
568                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
569
570                if (exporter)
571                {
572                        exporter->ExportBspViewCellPartition(*mBspTree,
573                                mViewCellsStats.maxPvs);
574                        delete exporter;
575                }
576               
577                cout << "finished" << endl;
578        }       
579
580        //-- visualization of the BSP splits
581        bool exportSplits = false;
582        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
583       
584        if (exportSplits)
585        {
586                cout << "exporting splits ... ";
587                ExportSplits(objects);
588                cout << "finished" << endl;
589        }
590
591        ExportBspPvs(objects);
592}
593
594
595inline bool vc_gt(ViewCell *a, ViewCell *b)
596{
597        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
598}
599
600
601void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
602{
603        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
604
605        if (exporter)
606        {       
607                Material m;
608                m.mDiffuseColor = RgbColor(1, 0, 0);
609                exporter->SetForcedMaterial(m);
610                exporter->SetWireframe();
611               
612                exporter->ExportBspSplits(*mBspTree, true);
613
614                // take forced material, else big scenes cannot be viewed
615                m.mDiffuseColor = RgbColor(0, 1, 0);
616                exporter->SetForcedMaterial(m);
617                exporter->SetFilled();
618
619                exporter->ResetForcedMaterial();
620               
621                // export rays
622                if (0)
623                {
624                        VssRayContainer outRays;
625               
626                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
627
628                        for (int i = 0; i < raysSize; ++ i)
629                                // only rays piercing geometry
630                                outRays.push_back(mBspRays[i]->vssRay);
631                                               
632                        // export rays
633                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
634                }
635
636                if (0)
637                        exporter->ExportGeometry(objects);
638
639                delete exporter;
640        }
641}
642
643
644void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
645{
646        bool exportRays = false;
647        bool exportGeometry = false;
648
649        environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
650        environment->GetBoolValue("VspBspTree.Visualization.exportGeometry", exportGeometry);
651
652        const int leafOut = 10;
653       
654        ViewCell::NewMail();
655
656        //-- some rays for output
657        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
658        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
659        Debug << "\nOutput view cells: " << endl;
660
661        if (1)
662        {
663                //-- some random view cells and rays for output
664                vector<BspLeaf *> vspBspLeaves;
665
666                for (int i = 0; i < leafOut; ++ i)
667                        vspBspLeaves.push_back(mBspTree->GetRandomLeaf());     
668               
669                for (int i = 0; i < (int)vspBspLeaves.size(); ++ i)
670                {
671                        VssRayContainer vcRays;
672                        cout << "creating output for view cell " << i << " ... ";
673
674                        // check whether we can add the current ray to the output rays
675                        for (int k = 0; k < raysOut; ++ k)
676                        {
677                                BspRay *ray = mBspRays[k];
678
679                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
680                                {
681                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
682
683                                        if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell())
684                                        {
685                                                vcRays.push_back(ray->vssRay);
686                                        }
687                                }
688                        }
689
690                        Intersectable::NewMail();
691
692                        BspViewCell *vc = dynamic_cast<BspViewCell *>
693                                (vspBspLeaves[i]->GetViewCell());
694
695                        //bspLeaves[j]->Mail();
696                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
697
698                        Exporter *exporter = Exporter::GetExporter(s);
699                        exporter->SetFilled();
700
701                        ObjectPvsMap::iterator it = vc->GetPvs().mEntries.begin();
702
703                        exporter->SetWireframe();
704                        //exporter->SetFilled();
705
706                        Material m;//= RandomMaterial();
707                        m.mDiffuseColor = RgbColor(0, 1, 0);
708                        exporter->SetForcedMaterial(m);
709
710                        if (vc->GetMesh())
711                                exporter->ExportViewCell(vc);
712                        else
713                        {
714                                PolygonContainer vcGeom;
715
716                                // export view cell geometry
717                                mBspTree->ConstructGeometry(vc, vcGeom);
718                                exporter->ExportPolygons(vcGeom);
719                                CLEAR_CONTAINER(vcGeom);
720                        }
721
722                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
723                                        << ", piercing rays=" << (int)vcRays.size() << endl;
724
725                        // export rays piercing this view cell
726                        if (exportRays)
727                        {
728                                //exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
729                                exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1));
730                        }
731
732                        m.mDiffuseColor = RgbColor(0, 1, 1);
733                        exporter->SetForcedMaterial(m);
734
735                        //exporter->SetWireframe();
736                        exporter->SetFilled();
737
738                        // output PVS of view cell
739                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
740                        {
741                                Intersectable *intersect = (*it).first;
742                                if (!intersect->Mailed())
743                                {
744                                        exporter->ExportIntersectable(intersect);
745                                        intersect->Mail();
746                                }                       
747                        }
748                        Debug << "here1 exportgeom: " << exportGeometry << endl;
749                        // output rest of the objects
750                        if (exportGeometry)
751                        {
752                                Material m;//= RandomMaterial();
753                                m.mDiffuseColor = RgbColor(0, 0, 1);
754                                exporter->SetForcedMaterial(m);
755
756                                for (int j = 0; j < objects.size(); ++ j)
757                                        if (!objects[j]->Mailed())
758                                        {
759                                                exporter->SetForcedMaterial(m);
760                                                exporter->ExportIntersectable(objects[j]);
761                                                objects[j]->Mail();
762                                        }
763                        }
764                        DEL_PTR(exporter);
765                        cout << "finished" << endl;
766                }
767        }
768        else
769        {
770                ViewCellContainer viewCells;
771
772                mBspTree->CollectViewCells(viewCells);
773                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
774
775                int limit = min(leafOut, (int)viewCells.size());
776               
777                for (int i = 0; i < limit; ++ i)
778                {
779                        cout << "creating output for view cell " << i << " ... ";
780                        VssRayContainer vcRays;
781            Intersectable::NewMail();
782                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
783
784                        cout << "creating output for view cell " << i << " ... ";
785
786                        // check whether we can add the current ray to the output rays
787                        for (int k = 0; k < raysOut; ++ k)
788                        {
789                                BspRay *ray = mBspRays[k];
790
791                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
792                                {
793                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
794
795                                        if (vc == leaf->GetViewCell())
796                                        {
797                                                vcRays.push_back(ray->vssRay);
798                                        }
799                                }
800                        }
801
802                        //bspLeaves[j]->Mail();
803                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
804
805                        Exporter *exporter = Exporter::GetExporter(s);
806                       
807                        exporter->SetWireframe();
808
809                        Material m;//= RandomMaterial();
810                        m.mDiffuseColor = RgbColor(0, 1, 0);
811                        exporter->SetForcedMaterial(m);
812
813                        if (vc->GetMesh())
814                                exporter->ExportViewCell(vc);
815                        else
816                        {
817                                PolygonContainer vcGeom;
818                                // export view cell
819                                mBspTree->ConstructGeometry(vc, vcGeom);
820                                exporter->ExportPolygons(vcGeom);
821                                CLEAR_CONTAINER(vcGeom);
822                        }
823
824                       
825                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
826                                  << ", piercing rays=" << (int)vcRays.size() << endl;
827
828                       
829                        // export rays piercing this view cell
830                        exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
831       
832                        m.mDiffuseColor = RgbColor(1, 0, 0);
833                        exporter->SetForcedMaterial(m);
834
835                        ObjectPvsMap::const_iterator it,
836                                it_end = vc->GetPvs().mEntries.end();
837
838                        // output PVS of view cell
839                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
840                        {
841                                Intersectable *intersect = (*it).first;
842
843                                if (!intersect->Mailed())
844                                {
845                                        Material m = RandomMaterial();
846                       
847                                        exporter->SetForcedMaterial(m);
848
849                                        exporter->ExportIntersectable(intersect);
850                                        intersect->Mail();
851                                }                       
852                        }
853                               
854                        DEL_PTR(exporter);
855                        cout << "finished" << endl;
856                }
857        }
858
859        Debug << endl;
860}
861
862
863bool BspViewCellsManager::MergeBspLeafViewCells(BspLeaf *front, BspLeaf *back) const
864{
865        BspViewCell *viewCell =
866                dynamic_cast<BspViewCell *>(MergeViewCells(*front->GetViewCell(), *back->GetViewCell()));
867       
868        if (!viewCell)
869                return false;
870
871        //-- change pointer to view cells of all leaves associated with the previous view cells
872        BspViewCell *fVc = front->GetViewCell();
873        BspViewCell *bVc = back->GetViewCell();
874
875        vector<BspLeaf *> fLeaves = fVc->mLeaves;
876        vector<BspLeaf *> bLeaves = bVc->mLeaves;
877
878        vector<BspLeaf *>::const_iterator it;
879       
880        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
881        {
882                (*it)->SetViewCell(viewCell);
883                viewCell->mLeaves.push_back(*it);
884        }
885        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
886        {
887                (*it)->SetViewCell(viewCell);
888                viewCell->mLeaves.push_back(*it);
889        }
890       
891        DEL_PTR(fVc);
892        DEL_PTR(bVc);
893
894        return true;
895}
896
897bool BspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
898{
899        ViewCell *fvc = front->GetViewCell();
900        ViewCell *bvc = back->GetViewCell();
901
902        if ((fvc == mBspTree->GetRootCell()) || (bvc == mBspTree->GetRootCell()) || (fvc == bvc))
903                return false;
904
905        int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
906
907        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
908        {
909                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
910                        (bvc->GetPvs().GetSize() < mMinPvs) ||
911                        ((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
912                {
913                        return true;
914                }
915        }
916       
917        return false;
918}
919
920
921void BspViewCellsManager::ConstructBspRays(const VssRayContainer &rays,
922                                                                                   const int numSamples)
923{
924        VssRayContainer::const_iterator it, it_end = rays.end();
925
926        for (it = rays.begin(); it != rays.end() && mBspRays.size() < numSamples; ++ it)
927        {
928                VssRay *vssRay = *it;
929                BspRay *ray = new BspRay(vssRay);
930
931                ViewCellContainer viewCells;
932
933                CastLineSegment(vssRay->mTermination, vssRay->mOrigin, viewCells);
934
935                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
936               
937                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
938                {
939                        BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
940                        ray->intersections.push_back(BspIntersection(0, vc->mLeaves[0]));
941                }
942
943                mBspRays.push_back(ray);
944        }
945}
946
947
948/**********************************************************************/
949/*                   KdViewCellsManager implementation               */
950/**********************************************************************/
951
952KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
953ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
954{
955}
956
957float KdViewCellsManager::GetProbability(ViewCell *viewCell)
958{
959        // compute view cell area as subsititute for probability
960        AxisAlignedBox3 box = mKdTree->GetBox(mKdTree->GetRoot());
961#if 0
962        return GetArea(viewCell) / box.SurfaceArea();
963#else
964        return GetArea(viewCell) / GetAccVcArea();
965#endif
966}
967
968
969float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
970{
971        return viewCell->GetPvs().GetSize() * objRendercost;
972}
973
974AxisAlignedBox3 KdViewCellsManager::GetSceneBbox() const
975{
976        return mKdTree->GetBox();
977}
978
979int KdViewCellsManager::Construct(const ObjectContainer &objects,
980                                                                  const VssRayContainer &rays,
981                                                                  AxisAlignedBox3 *sceneBbox)
982{
983        // if view cells already constructed
984        if (ViewCellsConstructed())
985                return 0;
986
987        mKdTree->Construct();
988
989        // create the view cells
990        mKdTree->CreateAndCollectViewCells(mViewCells);
991        //mKdTree->EvaluateViewCellsStats(mViewCellsStats);
992
993        return 0;
994}
995
996bool KdViewCellsManager::ViewCellsConstructed() const
997{
998        return mKdTree->GetRoot() != NULL;
999}
1000
1001int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1002                                                                        const VssRayContainer &rays)
1003{
1004        return 0;
1005}
1006
1007void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1008                                                                   const VssRayContainer &sampleRays)
1009{
1010        if (!ViewCellsConstructed())
1011                return;
1012
1013        // using view cells instead of the kd PVS of objects
1014        const bool useViewCells = true;
1015        bool exportRays = false;
1016
1017        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1018        const int pvsOut = min((int)objects.size(), 10);
1019        VssRayContainer *rays = new VssRayContainer[pvsOut];
1020
1021  //$$ JB
1022//#if 0
1023
1024        if (useViewCells)
1025        {
1026                const int leafOut = 10;
1027               
1028                ViewCell::NewMail();
1029 
1030                //-- some rays for output
1031                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1032                Debug << "visualization using " << raysOut << " samples" << endl;
1033
1034                //-- some random view cells and rays for output
1035                vector<KdLeaf *> kdLeaves;
1036               
1037                for (int i = 0; i < leafOut; ++ i)
1038                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1039               
1040                for (int i = 0; i < kdLeaves.size(); ++ i)
1041                {
1042                        KdLeaf *leaf = kdLeaves[i];
1043                        RayContainer vcRays;
1044                       
1045                        cout << "creating output for view cell " << i << " ... ";
1046                       
1047                        // check whether we can add the current ray to the output rays
1048                        /*for (int k = 0; k < raysOut; ++ k)
1049                        {
1050                                Ray *ray = sampleRays[k];
1051                               
1052                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1053                                {
1054                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1055                                       
1056                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1057                                        {
1058                                                vcRays.push_back(ray);
1059                                        }
1060                                }
1061                        }*/
1062                       
1063                        Intersectable::NewMail();
1064                       
1065                        ViewCell *vc = leaf->mViewCell;
1066                       
1067                        //bspLeaves[j]->Mail();
1068                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1069                       
1070                        Exporter *exporter = Exporter::GetExporter(s);
1071                        exporter->SetFilled();
1072
1073                        exporter->SetWireframe();
1074                        //exporter->SetFilled();
1075                       
1076                        Material m;//= RandomMaterial();
1077                        m.mDiffuseColor = RgbColor(1, 1, 0);
1078                        exporter->SetForcedMaterial(m);
1079                       
1080                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1081                        exporter->ExportBox(box);
1082
1083                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1084                                << ", piercing rays=" << (int)vcRays.size() << endl;
1085                       
1086                        // export rays piercing this view cell
1087                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0)); 
1088                       
1089                        m.mDiffuseColor = RgbColor(1, 0, 0);
1090                        exporter->SetForcedMaterial(m);
1091                       
1092                        // exporter->SetWireframe();
1093                        exporter->SetFilled();
1094                       
1095                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1096                        // output PVS of view cell
1097                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1098                        {
1099                                Intersectable *intersect = (*it).first;
1100                                if (!intersect->Mailed())
1101                                {
1102                                        exporter->ExportIntersectable(intersect);
1103                                        intersect->Mail();
1104                                }                       
1105                        }
1106                       
1107                        DEL_PTR(exporter);
1108                        cout << "finished" << endl;
1109                }
1110
1111                DEL_PTR(rays);
1112        }
1113        else // using kd PVS of objects
1114        {
1115                for (int i = 0; i < limit; ++ i)
1116                {
1117                        VssRay *ray = sampleRays[i];
1118               
1119                        // check whether we can add this to the rays
1120                        for (int j = 0; j < pvsOut; j++)
1121                        {
1122                                if (objects[j] == ray->mTerminationObject)
1123                                {
1124                                        rays[j].push_back(ray);
1125                                }
1126                        }
1127                }
1128
1129                if (exportRays)
1130                {
1131                        Exporter *exporter = NULL;
1132                        exporter = Exporter::GetExporter("sample-rays.x3d");
1133                        exporter->SetWireframe();
1134                        exporter->ExportKdTree(*mKdTree);
1135               
1136                        for (i=0; i < pvsOut; i++)
1137                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1138
1139                        exporter->SetFilled();
1140               
1141                        delete exporter;
1142                }
1143
1144                for (int k=0; k < pvsOut; k++)
1145                {
1146                        Intersectable *object = objects[k];
1147                        char s[64];     
1148                        sprintf(s, "sample-pvs%04d.x3d", k);
1149
1150                        Exporter *exporter = Exporter::GetExporter(s);
1151                        exporter->SetWireframe();
1152               
1153                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1154                        Intersectable::NewMail();
1155                       
1156                        // avoid adding the object to the list
1157                        object->Mail();
1158                        ObjectContainer visibleObjects;
1159           
1160                        for (; i != object->mKdPvs.mEntries.end(); i++)
1161                        {
1162                                KdNode *node = (*i).first;
1163                                exporter->ExportBox(mKdTree->GetBox(node));
1164               
1165                                mKdTree->CollectObjects(node, visibleObjects);
1166                        }
1167               
1168                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1169                        exporter->SetFilled();
1170                       
1171                        for (int j = 0; j < visibleObjects.size(); j++)
1172                                exporter->ExportIntersectable(visibleObjects[j]);
1173                       
1174                        Material m;
1175                        m.mDiffuseColor = RgbColor(1, 0, 0);
1176                        exporter->SetForcedMaterial(m);
1177                        exporter->ExportIntersectable(object);
1178               
1179                        delete exporter;
1180                }
1181        }               
1182}
1183
1184
1185int KdViewCellsManager::GetType() const
1186{
1187        return ViewCellsManager::KD;
1188}
1189
1190
1191
1192KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1193{
1194        KdNode *node = leaf;
1195
1196        while (node->mParent && node->mDepth > mKdPvsDepth)
1197                node = node->mParent;
1198        return node;
1199}
1200
1201int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1202                                                                                const Vector3 &termination,
1203                                                                                ViewCellContainer &viewcells)
1204{
1205        return mKdTree->CastLineSegment(origin, termination, viewcells);
1206}
1207
1208
1209
1210/**********************************************************************/
1211/*                   VspKdViewCellsManager implementation             */
1212/**********************************************************************/
1213
1214VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
1215                                                                                         int constructionSamples):
1216ViewCellsManager(constructionSamples),
1217mVspKdTree(vspKdTree)
1218{
1219        mVspKdTree->SetViewCellsManager(this);
1220}
1221
1222float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
1223{
1224        // volume or area substitutes for view point probability
1225        AxisAlignedBox3 box = mVspKdTree->GetBBox(mVspKdTree->GetRoot());
1226
1227        return GetArea(viewCell) / box.SurfaceArea();
1228        //return GetArea(viewCell) / GetAccVcArea();
1229}
1230
1231
1232float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1233{
1234        return viewCell->GetPvs().GetSize() * objRendercost;
1235}
1236
1237
1238int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
1239                                                                         const VssRayContainer &rays,
1240                                                                         AxisAlignedBox3 *sceneBbox)
1241{
1242        // if view cells already constructed
1243        if (ViewCellsConstructed())
1244                return 0;
1245               
1246        VssRayContainer constructionRays;
1247        VssRayContainer savedRays;
1248
1249        GetRaySets(rays, constructionRays, savedRays);
1250       
1251        Debug << "constructing vsp kd tree using "
1252                  << (int)constructionRays.size() << " samples" << endl;
1253
1254        mVspKdTree->Construct(constructionRays, sceneBbox);
1255        mVspKdTree->CollectViewCells(mViewCells);
1256        //mVspBspTree->EvaluateViewCellsStats(mViewCellsStats);
1257
1258        Debug << mVspKdTree->GetStatistics() << endl;
1259
1260        // finally merge kd leaf building blocks to view cells
1261        const int merged = mVspKdTree->MergeLeaves();
1262
1263        // recast rest of rays
1264        ComputeSampleContributions(savedRays);
1265
1266        return merged;
1267}
1268
1269bool VspKdViewCellsManager::ViewCellsConstructed() const
1270{
1271        return mVspKdTree->GetRoot() != NULL;
1272}
1273
1274
1275ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1276{
1277        return new VspKdViewCell(mesh);
1278}
1279
1280int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
1281                                                                           const VssRayContainer &rays)
1282{
1283        if (!ViewCellsConstructed())
1284                return 0;
1285
1286        return 0;
1287}
1288
1289AxisAlignedBox3 VspKdViewCellsManager::GetSceneBbox() const
1290{
1291        return mVspKdTree->GetBBox(mVspKdTree->GetRoot());
1292}
1293
1294void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1295                                                                          const VssRayContainer &sampleRays)
1296{
1297        bool exportRays = false;
1298        bool exportGeometry = false;
1299
1300        environment->GetBoolValue("VspKdTree.Visualization.exportRays", exportRays);
1301        environment->GetBoolValue("VspKdTree.Visualization.exportGeometry", exportGeometry);
1302
1303        if (!ViewCellsConstructed())
1304                return;
1305
1306        //-- export tree leaves
1307        if (1)
1308        {
1309                Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
1310                //exporter->SetWireframe();
1311                //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1312                exporter->ExportVspKdTree(*mVspKdTree);
1313
1314                if (1)
1315                        exporter->ExportGeometry(objects);
1316
1317                if (exportRays)
1318                  {
1319                        int raysSize = 2000;
1320                        float prob = raysSize / (float)sampleRays.size();
1321               
1322                        exporter->SetWireframe();
1323                       
1324                        VssRayContainer rays;
1325               
1326                        for (int i = 0; i < sampleRays.size(); ++ i)
1327                        {
1328                                if (RandomValue(0,1) < prob)
1329                                        rays.push_back(sampleRays[i]);
1330                        }
1331
1332                        exporter->ExportRays(rays, RgbColor(1, 0, 0));
1333                }
1334
1335                delete exporter;
1336        }
1337
1338        //-- export single leaves
1339        if (1)
1340        {
1341                vector<VspKdLeaf *> leafContainer;
1342                mVspKdTree->CollectLeaves(leafContainer);
1343
1344                for (int i = 0; i < 10; ++ i)
1345                {
1346                        char s[64];
1347                        sprintf(s, "vsp_leaves%04d.x3d", i);
1348                        Exporter *exporter = Exporter::GetExporter(s);
1349
1350                        // export geometry
1351                        VspKdLeaf *leaf = leafContainer[(int)RandomValue(0.0, (Real)((int)leafContainer.size() - 1))];
1352                        AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
1353
1354                        Material m;
1355                        m.mDiffuseColor = RgbColor(0, 1, 1);
1356                        exporter->SetForcedMaterial(m);
1357                        exporter->SetWireframe();
1358                        exporter->ExportBox(box);
1359
1360                        //-- export stored rays
1361                        VssRayContainer vssRays;
1362                        leaf->GetRays(vssRays);
1363
1364                        VssRayContainer rays;
1365                        VssRayContainer::const_iterator it, it_end = vssRays.end();
1366
1367                        for (it = vssRays.begin(); it != it_end; ++ it)
1368                                rays.push_back(*it);
1369                       
1370                        exporter->ExportRays(rays, RgbColor(1, 0, 0));
1371
1372                        //-- export stored PVS
1373                        ObjectContainer pvsObj;
1374                        leaf->ExtractPvs(pvsObj);
1375                               
1376                        exporter->ExportGeometry(pvsObj);
1377
1378                        delete exporter;
1379                }                       
1380        }
1381
1382        //-- export final view cells
1383        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
1384        exporter->SetWireframe();
1385        //exporter->ExportVspKdTreeViewCells(*mVspKdTree, vcStats.maxPvs);
1386        exporter->ExportVspKdTreeViewCells(*mVspKdTree);
1387
1388        if (1)
1389        {
1390                exporter->SetFilled();
1391                exporter->ExportGeometry(objects);
1392        }
1393
1394        if (exportRays)
1395        {
1396                int raysSize = 2000;
1397                float prob = raysSize / (float)sampleRays.size();
1398               
1399                exporter->SetWireframe();
1400                       
1401                VssRayContainer rays;
1402               
1403                for (int i = 0; i < sampleRays.size(); ++ i)
1404                {
1405                  if (RandomValue(0,1) < prob)
1406                        rays.push_back(sampleRays[i]);
1407                }
1408                exporter->ExportRays(rays, RgbColor(1, 0, 0));
1409        }
1410
1411        delete exporter;
1412}
1413
1414int VspKdViewCellsManager::GetType() const
1415{
1416        return VSP_KD;
1417}
1418
1419
1420int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1421                                                                                   const Vector3 &termination,
1422                                                                                   ViewCellContainer &viewcells)
1423{
1424        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
1425}
1426
1427
1428
1429/**********************************************************************/
1430/*                 VspBspViewCellsManager implementation              */
1431/**********************************************************************/
1432
1433VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
1434                                                                                           int constructionSamples):
1435ViewCellsManager(constructionSamples),
1436mVspBspTree(vspBspTree)
1437{
1438}
1439
1440
1441VspBspViewCellsManager::~VspBspViewCellsManager()
1442{
1443        CLEAR_CONTAINER(mBspRays);
1444}
1445
1446
1447float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
1448{
1449#if 0
1450        return GetArea(viewCell) / mVspBspTree->GetBbox().SurfaceArea();
1451#else
1452        return GetArea(viewCell) / GetAccVcArea();
1453#endif
1454}
1455
1456
1457float VspBspViewCellsManager::GetArea(ViewCell *viewCell) const
1458{
1459        PolygonContainer geom;
1460
1461        // compute view cell area
1462        mVspBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(viewCell), geom);
1463       
1464        const float area = Polygon3::GetArea(geom);
1465        CLEAR_CONTAINER(geom);
1466
1467        return area;
1468}
1469
1470
1471float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
1472                                                                                        float objRendercost) const
1473{
1474        return viewCell->GetPvs().GetSize() * objRendercost;
1475}
1476
1477
1478AxisAlignedBox3 VspBspViewCellsManager::GetSceneBbox() const
1479{
1480        return mVspBspTree->GetBoundingBox();
1481}
1482
1483
1484bool VspBspViewCellsManager::ViewCellsConstructed() const
1485{
1486        return mVspBspTree->GetRoot() != NULL;
1487}
1488
1489
1490ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1491{
1492        return new BspViewCell(mesh);
1493}
1494
1495int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
1496                                                                          const VssRayContainer &rays,
1497                                                                          AxisAlignedBox3 *sceneBbox)
1498{
1499        // if view cells were already constructed
1500        if (ViewCellsConstructed())
1501                return 0;
1502
1503        int sampleContributions = 0;
1504       
1505        VssRayContainer constructionRays;
1506        VssRayContainer savedRays;
1507
1508        GetRaySets(rays, constructionRays, savedRays);
1509       
1510        mVspBspTree->Construct(constructionRays);
1511        mVspBspTree->CollectViewCells(mViewCells);
1512        mVspBspTree->EvaluateViewCellsStats(mViewCellsStats);
1513       
1514        Debug << mVspBspTree->GetStatistics() << endl;
1515       
1516        // recast rest of rays
1517        ComputeSampleContributions(savedRays);
1518
1519        return sampleContributions;
1520}
1521
1522
1523void VspBspViewCellsManager::ConstructBspRays(const VssRayContainer &rays,
1524                                                                                          const int numSamples)
1525{
1526        VssRayContainer::const_iterator it, it_end = rays.end();
1527
1528        for (it = rays.begin(); it != rays.end() && mBspRays.size() < numSamples; ++ it)
1529        {
1530                VssRay *vssRay = *it;
1531                BspRay *ray = new BspRay(vssRay);
1532
1533                ViewCellContainer viewCells;
1534
1535                CastLineSegment(vssRay->mTermination, vssRay->mOrigin, viewCells);
1536
1537                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
1538               
1539                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
1540                {
1541                        BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
1542                        ray->intersections.push_back(BspIntersection(0, vc->mLeaves[0]));
1543                }
1544
1545                mBspRays.push_back(ray);
1546        }
1547}
1548
1549
1550int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
1551                                                                                const VssRayContainer &rays)
1552{
1553        if (mBspRays.empty())
1554                ConstructBspRays(rays, mConstructionSamples);
1555       
1556        if (!ViewCellsConstructed())
1557        {
1558                Debug << "view cells not constructed" << endl;
1559                return 0;
1560        }
1561
1562        //-- post processing of bsp view cells
1563    int vcSize = 0;
1564        int pvsSize = 0;
1565
1566        Debug << "original view cell partition:\n" << mViewCellsStats << endl;
1567               
1568        if (1) // export view cells
1569        {
1570                cout << "exporting initial view cells (=leaves) ... ";
1571                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
1572       
1573                if (exporter)
1574                {
1575                        //exporter->SetWireframe();
1576                        exporter->SetFilled();
1577                        exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
1578                               
1579                        if (0)
1580                        {
1581                                Material m;
1582                                m.mDiffuseColor = RgbColor(0, 1, 0);
1583                                exporter->SetForcedMaterial(m);
1584                                exporter->SetWireframe();
1585
1586                                exporter->ExportGeometry(objects);
1587                        }
1588
1589                        delete exporter;
1590                }
1591                cout << "finished" << endl;
1592        }
1593
1594        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1595               
1596        long startTime = GetTime();
1597
1598
1599        // $$JB we do not have connectivity information from the ray in the moment
1600        // perhaps we could recast the rays or rember the cells traversed inside the
1601        // vssray (which would on other hand create some overhead)
1602        //-- merge or subdivide view cells
1603        int merged = 0;
1604
1605        vector<BspIntersection>::const_iterator iit;
1606
1607        for (int i = 0; i < (int)mBspRays.size(); ++ i)
1608        { 
1609                BspRay *ray = mBspRays[i];
1610         
1611                // traverse leaves stored in the rays and compare and merge consecutive
1612                // leaves (i.e., the neighbors in the tree)
1613                if (ray->intersections.size() < 2)
1614                        continue;
1615         
1616                iit = ray->intersections.begin();
1617
1618                BspLeaf *previousLeaf = (*iit).mLeaf;
1619                ++ iit;
1620               
1621                for (; iit != ray->intersections.end(); ++ iit)
1622                {
1623                        BspLeaf *leaf = (*iit).mLeaf;
1624
1625                        if (ShouldMerge(leaf, previousLeaf))
1626                        {                       
1627                                MergeVspBspLeafViewCells(leaf, previousLeaf);
1628
1629                                ++ merged;
1630                        }
1631               
1632                        previousLeaf = leaf;
1633                }
1634        }
1635
1636        //-- stats and visualizations
1637        cout << "finished" << endl;
1638        cout << "merged " << merged << " view cells in "
1639                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1640
1641        Debug << "Postprocessing: Merged " << merged << " view cells in "
1642                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1643       
1644        // reset view cells and stats
1645        mViewCells.clear();
1646        mVspBspTree->CollectViewCells(mViewCells);
1647        mViewCellsStats.Reset();
1648        mVspBspTree->EvaluateViewCellsStats(mViewCellsStats);
1649
1650        return merged;
1651}
1652
1653int VspBspViewCellsManager::GetType() const
1654{
1655        return VSP_BSP;
1656}
1657
1658
1659void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
1660                                                                           const VssRayContainer &sampleRays)
1661{
1662        if (!ViewCellsConstructed())
1663                return;
1664
1665        if (mBspRays.empty())
1666                ConstructBspRays(sampleRays, mConstructionSamples);
1667       
1668        if (1) // export view cells
1669        {
1670                cout << "exporting view cells after merge ... ";
1671                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1672
1673                if (exporter)
1674                {
1675                        exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
1676                        delete exporter;
1677                }
1678               
1679                cout << "finished" << endl;
1680        }       
1681
1682        //-- visualization of the BSP splits
1683        bool exportSplits = false;
1684        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1685       
1686        if (exportSplits)
1687        {
1688                cout << "exporting splits ... ";
1689                ExportSplits(objects);
1690                cout << "finished" << endl;
1691        }
1692
1693        ExportBspPvs(objects);
1694}
1695
1696
1697void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects)
1698{
1699        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1700
1701        if (exporter)
1702        {       
1703                Material m;
1704                m.mDiffuseColor = RgbColor(1, 0, 0);
1705                exporter->SetForcedMaterial(m);
1706                exporter->SetWireframe();
1707               
1708                exporter->ExportBspSplits(*mVspBspTree, true);
1709
1710                // take forced material, else big scenes cannot be viewed
1711                m.mDiffuseColor = RgbColor(0, 1, 0);
1712                exporter->SetForcedMaterial(m);
1713                exporter->SetFilled();
1714
1715                exporter->ResetForcedMaterial();
1716               
1717                // export rays
1718                if (0)
1719                {
1720                        VssRayContainer outRays;
1721               
1722                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
1723
1724                        for (int i = 0; i < raysSize; ++ i)
1725                                // only rays piercing geometry
1726                                outRays.push_back(mBspRays[i]->vssRay);
1727                                               
1728                        // export rays
1729                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
1730                }
1731
1732                if (0)
1733                        exporter->ExportGeometry(objects);
1734
1735                delete exporter;
1736        }
1737}
1738
1739void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
1740{
1741        bool exportRays = false;
1742        bool exportGeometry = false;
1743
1744        environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
1745        environment->GetBoolValue("VspBspTree.Visualization.exportGeometry", exportGeometry);
1746
1747        const int leafOut = 10;
1748       
1749        ViewCell::NewMail();
1750
1751        //-- some rays for output
1752        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
1753        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1754        Debug << "\nOutput view cells: " << endl;
1755
1756        if (1)
1757        {
1758                //-- some random view cells and rays for output
1759                vector<BspLeaf *> vspBspLeaves;
1760
1761                for (int i = 0; i < leafOut; ++ i)
1762                        vspBspLeaves.push_back(mVspBspTree->GetRandomLeaf());   
1763               
1764                for (int i = 0; i < (int)vspBspLeaves.size(); ++ i)
1765                {
1766                        VssRayContainer vcRays;
1767                        cout << "creating output for view cell " << i << " ... ";
1768
1769                        // check whether we can add the current ray to the output rays
1770                        for (int k = 0; k < raysOut; ++ k)
1771                        {
1772                                BspRay *ray = mBspRays[k];
1773
1774                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1775                                {
1776                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1777
1778                                        if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell())
1779                                        {
1780                                                vcRays.push_back(ray->vssRay);
1781                                        }
1782                                }
1783                        }
1784
1785                        Intersectable::NewMail();
1786
1787                        BspViewCell *vc = dynamic_cast<BspViewCell *>
1788                                (vspBspLeaves[i]->GetViewCell());
1789
1790                        //bspLeaves[j]->Mail();
1791                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1792
1793                        Exporter *exporter = Exporter::GetExporter(s);
1794                        exporter->SetFilled();
1795
1796                        ObjectPvsMap::iterator it = vc->GetPvs().mEntries.begin();
1797
1798                        exporter->SetWireframe();
1799                        //exporter->SetFilled();
1800
1801                        Material m;//= RandomMaterial();
1802                        m.mDiffuseColor = RgbColor(0, 1, 0);
1803                        exporter->SetForcedMaterial(m);
1804
1805                        if (vc->GetMesh())
1806                                exporter->ExportViewCell(vc);
1807                        else
1808                        {
1809                                PolygonContainer vcGeom;
1810
1811                                // export view cell geometry
1812                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1813                                exporter->ExportPolygons(vcGeom);
1814                                CLEAR_CONTAINER(vcGeom);
1815                        }
1816
1817                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1818                                        << ", piercing rays=" << (int)vcRays.size() << endl;
1819
1820                        // export rays piercing this view cell
1821                        if (exportRays)
1822                        {
1823                                //exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
1824                                exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1));
1825                        }
1826
1827                        m.mDiffuseColor = RgbColor(0, 1, 1);
1828                        exporter->SetForcedMaterial(m);
1829
1830                        //exporter->SetWireframe();
1831                        exporter->SetFilled();
1832
1833                        // output PVS of view cell
1834                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
1835                        {
1836                                Intersectable *intersect = (*it).first;
1837                                if (!intersect->Mailed())
1838                                {
1839                                        exporter->ExportIntersectable(intersect);
1840                                        intersect->Mail();
1841                                }                       
1842                        }
1843                        Debug << "here1 exportgeom: " << exportGeometry << endl;
1844                        // output rest of the objects
1845                        if (exportGeometry)
1846                        {
1847                                Material m;//= RandomMaterial();
1848                                m.mDiffuseColor = RgbColor(0, 0, 1);
1849                                exporter->SetForcedMaterial(m);
1850
1851                                for (int j = 0; j < objects.size(); ++ j)
1852                                        if (!objects[j]->Mailed())
1853                                        {
1854                                                exporter->SetForcedMaterial(m);
1855                                                exporter->ExportIntersectable(objects[j]);
1856                                                objects[j]->Mail();
1857                                        }
1858                        }
1859                        DEL_PTR(exporter);
1860                        cout << "finished" << endl;
1861                }
1862        }
1863        else
1864        {
1865                ViewCellContainer viewCells;
1866
1867                mVspBspTree->CollectViewCells(viewCells);
1868                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
1869
1870                int limit = min(leafOut, (int)viewCells.size());
1871               
1872                for (int i = 0; i < limit; ++ i)
1873                {
1874                        cout << "creating output for view cell " << i << " ... ";
1875                        VssRayContainer vcRays;
1876            Intersectable::NewMail();
1877                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
1878
1879                        cout << "creating output for view cell " << i << " ... ";
1880
1881                        // check whether we can add the current ray to the output rays
1882                        for (int k = 0; k < raysOut; ++ k)
1883                        {
1884                                BspRay *ray = mBspRays[k];
1885
1886                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1887                                {
1888                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1889
1890                                        if (vc == leaf->GetViewCell())
1891                                        {
1892                                                vcRays.push_back(ray->vssRay);
1893                                        }
1894                                }
1895                        }
1896
1897                        //bspLeaves[j]->Mail();
1898                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1899
1900                        Exporter *exporter = Exporter::GetExporter(s);
1901                       
1902                        exporter->SetWireframe();
1903
1904                        Material m;//= RandomMaterial();
1905                        m.mDiffuseColor = RgbColor(0, 1, 0);
1906                        exporter->SetForcedMaterial(m);
1907
1908                        if (vc->GetMesh())
1909                                exporter->ExportViewCell(vc);
1910                        else
1911                        {
1912                                PolygonContainer vcGeom;
1913                                // export view cell
1914                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1915                                exporter->ExportPolygons(vcGeom);
1916                                CLEAR_CONTAINER(vcGeom);
1917                        }
1918
1919                       
1920                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1921                                  << ", piercing rays=" << (int)vcRays.size() << endl;
1922
1923                       
1924                        // export rays piercing this view cell
1925                        exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1926       
1927                        m.mDiffuseColor = RgbColor(1, 0, 0);
1928                        exporter->SetForcedMaterial(m);
1929
1930                        ObjectPvsMap::const_iterator it,
1931                                it_end = vc->GetPvs().mEntries.end();
1932
1933                        // output PVS of view cell
1934                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1935                        {
1936                                Intersectable *intersect = (*it).first;
1937
1938                                if (!intersect->Mailed())
1939                                {
1940                                        Material m = RandomMaterial();
1941                       
1942                                        exporter->SetForcedMaterial(m);
1943
1944                                        exporter->ExportIntersectable(intersect);
1945                                        intersect->Mail();
1946                                }                       
1947                        }
1948                               
1949                        DEL_PTR(exporter);
1950                        cout << "finished" << endl;
1951                }
1952        }
1953
1954        Debug << endl;
1955}
1956
1957
1958bool VspBspViewCellsManager::MergeVspBspLeafViewCells(BspLeaf *front,
1959                                                                                                          BspLeaf *back) const
1960{
1961        BspViewCell *viewCell =
1962                dynamic_cast<BspViewCell *>(MergeViewCells(*front->GetViewCell(),
1963                                                                                                   *back->GetViewCell()));
1964       
1965        if (!viewCell)
1966                return false;
1967
1968        // change view cells of all leaves
1969        // associated with the previous view cells
1970        BspViewCell *fVc = front->GetViewCell();
1971        BspViewCell *bVc = back->GetViewCell();
1972
1973        vector<BspLeaf *> fLeaves = fVc->mLeaves;
1974        vector<BspLeaf *> bLeaves = bVc->mLeaves;
1975
1976        vector<BspLeaf *>::const_iterator it;
1977       
1978        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
1979        {
1980                (*it)->SetViewCell(viewCell);
1981                viewCell->mLeaves.push_back(*it);
1982        }
1983        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
1984        {
1985                (*it)->SetViewCell(viewCell);
1986                viewCell->mLeaves.push_back(*it);
1987        }
1988       
1989        DEL_PTR(fVc);
1990        DEL_PTR(bVc);
1991
1992        return true;
1993}
1994
1995bool VspBspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
1996{
1997        ViewCell *fvc = front->GetViewCell();
1998        ViewCell *bvc = back->GetViewCell();
1999
2000        if ((fvc == mVspBspTree->GetRootCell()) ||
2001                (bvc == mVspBspTree->GetRootCell()) ||
2002                (fvc == bvc))
2003                return false;
2004
2005        const int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
2006
2007        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
2008        {
2009                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
2010                        (bvc->GetPvs().GetSize() < mMinPvs) ||
2011                        ((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
2012                {
2013                        return true;
2014                }
2015        }
2016       
2017        return false;
2018}
2019
2020
2021int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2022                                                                                        const Vector3 &termination,
2023                                                                                        ViewCellContainer &viewcells)
2024{
2025        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
2026}
Note: See TracBrowser for help on using the repository browser.