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

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