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

Revision 480, 45.0 KB checked in by mattausch, 19 years ago (diff)

axis aligned split for vsp bsp view cells

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