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

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