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

Revision 475, 47.9 KB checked in by mattausch, 18 years ago (diff)

bsp merging possible again

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