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

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

bsp merging possible again

RevLine 
[440]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"
[442]12#include "VspBspTree.h"
[440]13
14
15ViewCellsManager::ViewCellsManager():
16mRenderSimulator(NULL),
17mConstructionSamples(0),
18mPostProcessSamples(0),
[470]19mVisualizationSamples(0),
20mTotalAreaValid(false),
21mTotalArea(0.0f)
[440]22{
[463]23        // post processing stuff
24        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
25        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
[441]26        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
[440]27}
28
29ViewCellsManager::ViewCellsManager(int constructionSamples):
30mConstructionSamples(constructionSamples),
31mRenderSimulator(NULL),
32mPostProcessSamples(0),
33mVisualizationSamples(0)
34{
[463]35        // post processing stuff
36        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
37        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
[441]38        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
[440]39}
40
41ViewCellsManager::~ViewCellsManager()
42{
43        DEL_PTR(mRenderSimulator);
44
[469]45        CLEAR_CONTAINER(mViewCells);
[440]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
[469]60void ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays)
[440]61{
[469]62        // view cells not yet constructed
63        if (!ViewCellsConstructed())
64                return;
[466]65 
[469]66        VssRayContainer::const_iterator it, it_end = rays.end();
67       
68        for (it = rays.begin(); it != it_end; ++ it)
69        {
70                ComputeSampleContributions(*(*it));
71        }
[440]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
[441]138ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
[440]139{
[462]140        // generate merged view cell
[440]141        ViewCell *vc = GenerateViewCell();
[462]142
[440]143        // merge pvs
144        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
145
[462]146        //-- merge ray sets
[440]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
[441]157
[440]158ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
159{
160        return new ViewCell(mesh);
161}
162
163
164void ViewCellsManager::SetVisualizationSamples(const int visSamples)
165{
[444]166        mVisualizationSamples = visSamples;
[440]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
[467]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
[468]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)
[475]257                        ++ ray.mPvsContribution;
[468]258               
259                ray.mRelativePvsContribution += contribution;
260        }
261}
262
263
[469]264void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
265                                                                  VssRayContainer &constructionRays,
266                                                                  VssRayContainer &savedRays) const
267{
[473]268        const int limit = min(mConstructionSamples, (int)sourceRays.size());
[469]269
270        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[473]271       
272        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]273
274        for (it = sourceRays.begin(); it != it_end; ++ it)
275        {
[473]276                if (Random(1.0f) < prop)
[469]277                        constructionRays.push_back(*it);
278                else
279                        savedRays.push_back(*it);
280        }
281}
282
[470]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
[475]314void ViewCellsManager::PrintStatistics(ostream &s) const
315{
316        s << mViewCellsStats << endl;
317}
318
[440]319/**********************************************************************/
320/*                   BspViewCellsManager implementation               */
321/**********************************************************************/
322
[469]323BspViewCellsManager::BspViewCellsManager(BspTree *bspTree,
324                                                                                 int constructionSamples):
[440]325ViewCellsManager(constructionSamples),
326mBspTree(bspTree)
327{
328}
329
[462]330
[440]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{
[441]345        // if view cells were already constructed
[440]346        if (ViewCellsConstructed())
347                return 0;
348
349        int sampleContributions = 0;
350       
[469]351        // construct view cells using the collected samples
352        RayContainer constructionRays;
353        VssRayContainer savedRays;
[440]354
[469]355        const int limit = min(mConstructionSamples, (int)rays.size());
[440]356
[469]357        VssRayContainer::const_iterator it, it_end = rays.end();
[448]358
[473]359        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
360
[469]361        for (it = rays.begin(); it != it_end; ++ it)
362        {
[473]363                if (Random(1.0f) < prop)
[469]364                        constructionRays.push_back(new Ray(*(*it)));
365                else
366                        savedRays.push_back(*it);
367        }
[440]368
[469]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
[475]381        mBspTree->EvaluateViewCellsStats(mViewCellsStats);
382
[469]383        // destroy rays created only for construction
384        CLEAR_CONTAINER(constructionRays);
385
[440]386        Debug << mBspTree->GetStatistics() << endl;
[444]387       
[469]388        // recast rest of the rays
389        ComputeSampleContributions(savedRays);
390
[440]391        return sampleContributions;
392}
393
[470]394float BspViewCellsManager::GetArea(ViewCell *viewCell) const
395{
396        PolygonContainer geom;
[468]397
[470]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
[471]408float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]409{
[471]410        // compute view cell area as subsititute for probability
411        return GetArea(viewCell) / mBspTree->GetBoundingBox().SurfaceArea();
412        //return GetArea(viewCell) / GetTotalArea();
[466]413}
[440]414
[469]415float BspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[466]416{
[468]417        return viewCell->GetPvs().GetSize() * objRendercost;
[440]418}
419
[468]420
421int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
422                                                                                 const Vector3 &termination,
423                                                                                 ViewCellContainer &viewcells)
[440]424{
[468]425        return mBspTree->CastLineSegment(origin, termination, viewcells);
426}
427
428
429int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
430                                                                         const VssRayContainer &rays)
431{
[469]432        if (!ViewCellsConstructed())
[441]433        {
434                Debug << "view cells not constructed" << endl;
435                return 0;
436        }
437
[440]438        //-- post processing of bsp view cells
439    int vcSize = 0;
440        int pvsSize = 0;
441
[475]442        Debug << "original view cell partition:\n" << mViewCellsStats << endl;
[440]443               
[448]444        if (1) // export view cells before merge
[440]445        {
446                cout << "exporting initial view cells (=leaves) ... ";
447                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
448       
449                if (exporter)
450                {
451                        exporter->SetWireframe();
[475]452                        exporter->ExportBspLeaves(*mBspTree, mViewCellsStats.maxPvs);
[440]453                        //exporter->ExportBspViewCellPartition(*mBspTree, 0);
454                               
[441]455                        if (0)
[440]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;
[448]468
[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
[440]480        }
481
482        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
[448]483
[440]484        long startTime = GetTime();
485
[466]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)
[440]489        //-- merge or subdivide view cells
490        int merged = 0;
[466]491#if 0
[440]492
493        RayContainer::const_iterator rit, rit_end = rays.end();
[475]494        vector<BspIntersection>::const_iterator iit;
[440]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
[441]516                        if (ShouldMerge(leaf, previousLeaf))
[440]517                        {                       
[441]518                                MergeBspLeafViewCells(leaf, previousLeaf);
[440]519
520                                ++ merged;
521                        }
522               
523                        previousLeaf = leaf;
524                }
525        }
[466]526#endif
[440]527        //-- stats and visualizations
528        cout << "finished" << endl;
529        cout << "merged " << merged << " view cells in "
530                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
531
[475]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
[440]539        return merged;
540}
541
542int BspViewCellsManager::GetType() const
543{
544        return BSP;
545}
546
547
548void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]549                                                                        const VssRayContainer &sampleRays)
[440]550{
[469]551        if (!ViewCellsConstructed())
552                return;
[466]553 
[469]554        //-- recount pvs
555        ViewCellsStatistics vcStats;
556        mBspTree->EvaluateViewCellsStats(vcStats);
[466]557 
[469]558        if (1) // export view cells
[440]559        {
[469]560                cout << "exporting view cells after merge ... ";
561                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[466]562         
[469]563                if (exporter)
[440]564                {
[469]565                        exporter->ExportBspViewCellPartition(*mBspTree, vcStats.maxPvs);
566                        //exporter->ExportBspViewCellPartition(*mBspTree, 0);
567                        delete exporter;
[440]568                }
[466]569         
[469]570                cout << "finished" << endl;
[440]571        }       
[466]572 
[469]573        //-- visualization of the BSP splits
574        bool exportSplits = false;
575        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[466]576 
[469]577        if (exportSplits)
[440]578        {
[469]579                cout << "exporting splits ... ";
580                ExportSplits(objects, sampleRays);
581                cout << "finished" << endl;
[440]582        }
[466]583 
[469]584        ExportBspPvs(objects, sampleRays);
[440]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,
[466]594                                                                           const VssRayContainer &sampleRays)
[440]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               
[469]613                bool exportRays = false;
614                bool exportGeometry = false;
615
[473]616                environment->GetBoolValue("BspTree.Visualization.exportRays", exportRays);
617                environment->GetBoolValue("BspTree.Visualization.exportGeometry", exportGeometry);
[469]618
[440]619                // export rays
[469]620                if (exportRays)
[440]621                {
[469]622                        VssRayContainer outRays;
[466]623                 
[469]624                        int raysSize = min((int)sampleRays.size(), mVisualizationSamples);
625                        for (int i = 0; i < raysSize; ++ i)
[440]626                        {
[469]627                                // only rays piercing geometry
628                                outRays.push_back(sampleRays[i]);                       
[440]629                        }
[469]630                       
631                        // export rays
632                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
[440]633                }
[466]634               
[469]635                if (exportGeometry)
636                        exporter->ExportGeometry(objects);
[466]637               
[440]638                delete exporter;
639        }
640}
641
642void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
[466]643                                                                           const VssRayContainer &sampleRays)
[440]644{
[466]645  const int leafOut = 10;
646 
647  ViewCell::NewMail();
648 
649  //-- some rays for output
650  const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
[440]651
[475]652  Debug << "Output view cells:" << endl;
653
[466]654  if (1)
[469]655  {
[466]656          //-- some random view cells and rays for output
657          vector<BspLeaf *> bspLeaves;
658         
659          for (int i = 0; i < leafOut; ++ i)
[469]660                  bspLeaves.push_back(mBspTree->GetRandomLeaf());       
[440]661
[466]662          for (int i = 0; i < bspLeaves.size(); ++ i)
[469]663          {
[466]664                  BspLeaf *leaf = bspLeaves[i];
665                  RayContainer vcRays;
666                 
667                  cout << "creating output for view cell " << i << " ... ";
668                 
[469]669                  // TODO matt
[466]670                  // check whether we can add the current ray to the output rays
[469]671                  /*for (int k = 0; k < raysOut; ++ k)
672                  {
[466]673                          Ray *ray = sampleRays[k];
674                         
[469]675                          for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
676                          {
[466]677                                  BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
678                                 
679                                  if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]680                                  {
[466]681                                          vcRays.push_back(ray);
[469]682                                  }
683                          }
684                  }*/
[466]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();
[440]695
[466]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())
[469]704                          exporter->ExportViewCell(vc);
[466]705                  else
[469]706                  {
[466]707                          PolygonContainer vcGeom;
708                          // export view cell geometry
709                          mBspTree->ConstructGeometry(vc, vcGeom);
710                          exporter->ExportPolygons(vcGeom);
[469]711                          CLEAR_CONTAINER(vcGeom);
712                  }               
713
[466]714                  Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
715                                << ", piercing rays=" << (int)vcRays.size() << endl;
716                 
717                  // export rays piercing this view cell
[469]718                  //exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));     
[466]719                 
720                  m.mDiffuseColor = RgbColor(1, 0, 0);
721                  exporter->SetForcedMaterial(m);
722                 
723                  // exporter->SetWireframe();
724                  exporter->SetFilled();
725                 
[469]726                  ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
[466]727                  // output PVS of view cell
728                  for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]729                  {
[466]730                          Intersectable *intersect = (*it).first;
731                          if (!intersect->Mailed())
[469]732                          {
[466]733                                  exporter->ExportIntersectable(intersect);
734                                  intersect->Mail();
[469]735                          }                     
736                  }
[466]737                 
738                  DEL_PTR(exporter);
739                  cout << "finished" << endl;
[469]740          }
741  }
[466]742  else
[469]743  {
[466]744          ViewCellContainer viewCells;
745          RayContainer vcRays;
746         
747          mBspTree->CollectViewCells(viewCells);
748          stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
749         
[469]750          const int limit = min(leafOut, (int)viewCells.size());
[466]751         
752          for (int i = 0; i < limit; ++ i)
[469]753          {
[466]754                  cout << "creating output for view cell " << i << " ... ";
[440]755                       
[469]756                  Intersectable::NewMail();
757                  BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
[440]758
[469]759                  cout << "creating output for view cell " << i << " ... ";
[440]760
[469]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];
[440]766
[469]767                          for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
768                          {
769                                  BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
[440]770
[469]771                                  if (vc == leaf->GetViewCell())
772                                          vcRays.push_back(ray);
773                          }
774                  }*/
[440]775
[469]776                  //bspLeaves[j]->Mail();
777                  char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[440]778
[469]779                  Exporter *exporter = Exporter::GetExporter(s);       
780                  exporter->SetWireframe();
[440]781
[469]782                  Material m;//= RandomMaterial();
783                  m.mDiffuseColor = RgbColor(0, 1, 0);
784                  exporter->SetForcedMaterial(m);
[440]785
[469]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;
[440]798
[469]799                  // export rays piercing this view cell
800                  exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
[440]801       
[469]802                  m.mDiffuseColor = RgbColor(1, 0, 0);
803                  exporter->SetForcedMaterial(m);
[440]804
[469]805                  ObjectPvsMap::const_iterator it, it_end = vc->GetPvs().mEntries.end();
[440]806
[469]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);
[440]818                       
[469]819                                  intersect->Mail();
820                          }                     
821                  }
[440]822                               
[469]823                  DEL_PTR(exporter);
824                  cout << "finished" << endl;
825          }
826  }
[440]827}
828
[441]829
[463]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
[469]842        vector<BspLeaf *> fLeaves = fVc->mLeaves;
843        vector<BspLeaf *> bLeaves = bVc->mLeaves;
[463]844
845        vector<BspLeaf *>::const_iterator it;
846       
847        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
848        {
849                (*it)->SetViewCell(viewCell);
[469]850                viewCell->mLeaves.push_back(*it);
[463]851        }
852        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
853        {
854                (*it)->SetViewCell(viewCell);
[469]855                viewCell->mLeaves.push_back(*it);
[463]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
[441]887
[467]888
[440]889/**********************************************************************/
890/*                   KdViewCellsManager implementation               */
891/**********************************************************************/
892
893KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]894ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]895{
896}
897
[471]898float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]899{
[471]900        // compute view cell area as subsititute for probability
901        AxisAlignedBox3 box = mKdTree->GetBox(mKdTree->GetRoot());
[469]902
[471]903        return GetArea(viewCell) / box.SurfaceArea();
904        //return GetArea(viewCell) / GetTotalArea();
[468]905}
906
907
[469]908float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]909{
[469]910        return viewCell->GetPvs().GetSize() * objRendercost;
[468]911}
912
[440]913int KdViewCellsManager::Construct(const ObjectContainer &objects,
914                                                                  const VssRayContainer &rays,
915                                                                  AxisAlignedBox3 *sceneBbox)
916{
[441]917        // if view cells already constructed
[440]918        if (ViewCellsConstructed())
919                return 0;
[441]920
[440]921        mKdTree->Construct();
922
[469]923        // create the view cells
924        mKdTree->CreateAndCollectViewCells(mViewCells);
[475]925        //mKdTree->EvaluateViewCellsStats(mViewCellsStats);
[469]926
[440]927        return 0;
928}
929
930bool KdViewCellsManager::ViewCellsConstructed() const
931{
932        return mKdTree->GetRoot() != NULL;
933}
934
935int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]936                                                                        const VssRayContainer &rays)
[440]937{
938        return 0;
939}
940
941void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]942                                                                   const VssRayContainer &sampleRays)
[440]943{
[441]944        if (!ViewCellsConstructed())
945                return;
946
[469]947        // using view cells instead of the kd PVS of objects
948        const bool useViewCells = true;
949        bool exportRays = false;
[440]950
951        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]952        const int pvsOut = min((int)objects.size(), 10);
[466]953        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]954
[469]955  //$$ JB
956//#if 0
957
958        if (useViewCells)
[440]959        {
[469]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)
[440]975                {
[469]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)
[440]983                        {
[469]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                                }                       
[440]1039                        }
[469]1040                       
1041                        DEL_PTR(exporter);
1042                        cout << "finished" << endl;
[440]1043                }
[469]1044
1045                DEL_PTR(rays);
[440]1046        }
[469]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                }
[440]1062
[469]1063                if (exportRays)
1064                {
1065                        Exporter *exporter = NULL;
1066                        exporter = Exporter::GetExporter("sample-rays.x3d");
1067                        exporter->SetWireframe();
1068                        exporter->ExportKdTree(*mKdTree);
[440]1069               
[469]1070                        for (i=0; i < pvsOut; i++)
1071                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1072
1073                        exporter->SetFilled();
[440]1074               
[469]1075                        delete exporter;
1076                }
[440]1077
[469]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);
[440]1083
[469]1084                        Exporter *exporter = Exporter::GetExporter(s);
1085                        exporter->SetWireframe();
1086               
1087                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1088                        Intersectable::NewMail();
[440]1089                       
[469]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;
[440]1114                }
[469]1115        }               
[440]1116}
1117
[469]1118
[440]1119int KdViewCellsManager::GetType() const
1120{
1121        return ViewCellsManager::KD;
1122}
1123
1124
[441]1125
[440]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
[469]1135int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1136                                                                                const Vector3 &termination,
1137                                                                                ViewCellContainer &viewcells)
[466]1138{
[469]1139        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]1140}
1141
[469]1142
1143
[440]1144/**********************************************************************/
1145/*                   VspKdViewCellsManager implementation             */
1146/**********************************************************************/
1147
[462]1148VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
1149                                                                                         int constructionSamples):
[440]1150ViewCellsManager(constructionSamples),
1151mVspKdTree(vspKdTree)
1152{
[468]1153        mVspKdTree->SetViewCellsManager(this);
1154}
[462]1155
[471]1156float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1157{
1158        // volume or area substitutes for view point probability
[471]1159        AxisAlignedBox3 box = mVspKdTree->GetBBox(mVspKdTree->GetRoot());
1160
1161        return GetArea(viewCell) / box.SurfaceArea();
1162        //return GetArea(viewCell) / GetTotalArea();
[440]1163}
1164
[462]1165
[469]1166float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1167{
[469]1168        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1169}
1170
[462]1171
[440]1172int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
1173                                                                         const VssRayContainer &rays,
1174                                                                         AxisAlignedBox3 *sceneBbox)
1175{
[441]1176        // if view cells already constructed
[440]1177        if (ViewCellsConstructed())
1178                return 0;
[452]1179               
[469]1180        VssRayContainer constructionRays;
1181        VssRayContainer savedRays;
[440]1182
[469]1183        GetRaySets(rays, constructionRays, savedRays);
1184       
1185        Debug << "constructing vsp kd tree using "
1186                  << (int)constructionRays.size() << " samples" << endl;
[452]1187
[469]1188        mVspKdTree->Construct(constructionRays, sceneBbox);
1189        mVspKdTree->CollectViewCells(mViewCells);
[475]1190        //mVspBspTree->EvaluateViewCellsStats(mViewCellsStats);
[452]1191
1192        Debug << mVspKdTree->GetStatistics() << endl;
1193
[469]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;
[440]1201}
1202
1203bool VspKdViewCellsManager::ViewCellsConstructed() const
1204{
1205        return mVspKdTree->GetRoot() != NULL;
1206}
1207
[441]1208
[462]1209ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1210{
1211        return new VspKdViewCell(mesh);
1212}
1213
[440]1214int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1215                                                                           const VssRayContainer &rays)
[440]1216{
[441]1217        if (!ViewCellsConstructed())
1218                return 0;
1219
[469]1220        return 0;
[440]1221}
1222
1223void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1224                                                                          const VssRayContainer &sampleRays)
[440]1225{
[469]1226        bool exportRays = false;
1227        bool exportGeometry = false;
1228
[473]1229        environment->GetBoolValue("VspKdTree.Visualization.exportRays", exportRays);
1230        environment->GetBoolValue("VspKdTree.Visualization.exportGeometry", exportGeometry);
[469]1231
[441]1232        if (!ViewCellsConstructed())
1233                return;
1234
[452]1235        //-- export tree leaves
[440]1236        if (1)
1237        {
1238                Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
1239                //exporter->SetWireframe();
[462]1240                //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1241                exporter->ExportVspKdTree(*mVspKdTree);
[440]1242
[465]1243                if (1)
[440]1244                        exporter->ExportGeometry(objects);
1245
1246                if (exportRays)
[466]1247                  {
[440]1248                        int raysSize = 2000;
1249                        float prob = raysSize / (float)sampleRays.size();
1250               
1251                        exporter->SetWireframe();
1252                       
[466]1253                        VssRayContainer rays;
[440]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
[466]1261                        exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]1262                }
1263
1264                delete exporter;
1265        }
1266
[462]1267        //-- export single leaves
[440]1268        if (1)
1269        {
[462]1270                vector<VspKdLeaf *> leafContainer;
[440]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
[473]1280                        VspKdLeaf *leaf = leafContainer[(int)RandomValue(0.0, (Real)((int)leafContainer.size() - 1))];
[440]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)
[452]1297                                rays.push_back(*it);
1298                       
[440]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        }
[462]1310
1311        //-- export final view cells
1312        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
[465]1313        exporter->SetWireframe();
[462]1314        //exporter->ExportVspKdTreeViewCells(*mVspKdTree, vcStats.maxPvs);
1315        exporter->ExportVspKdTreeViewCells(*mVspKdTree);
1316
[465]1317        if (1)
1318        {
1319                exporter->SetFilled();
[462]1320                exporter->ExportGeometry(objects);
[465]1321        }
[469]1322
[462]1323        if (exportRays)
1324        {
1325                int raysSize = 2000;
1326                float prob = raysSize / (float)sampleRays.size();
1327               
1328                exporter->SetWireframe();
1329                       
[466]1330                VssRayContainer rays;
[462]1331               
1332                for (int i = 0; i < sampleRays.size(); ++ i)
1333                {
[466]1334                  if (RandomValue(0,1) < prob)
1335                        rays.push_back(sampleRays[i]);
[462]1336                }
[466]1337                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]1338        }
1339
1340        delete exporter;
[440]1341}
1342
1343int VspKdViewCellsManager::GetType() const
1344{
1345        return VSP_KD;
1346}
[442]1347
[462]1348
[469]1349int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1350                                                                                   const Vector3 &termination,
1351                                                                                   ViewCellContainer &viewcells)
[466]1352{
[469]1353        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]1354}
1355
[442]1356/**********************************************************************/
1357/*                 VspBspViewCellsManager implementation              */
1358/**********************************************************************/
1359
1360VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
1361                                                                                           int constructionSamples):
1362ViewCellsManager(constructionSamples),
1363mVspBspTree(vspBspTree)
1364{
1365}
1366
[475]1367VspBspViewCellsManager::~VspBspViewCellsManager()
1368{
1369        CLEAR_CONTAINER(mBspRays);
1370}
1371
[471]1372float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1373{
[471]1374        return GetArea(viewCell) / mVspBspTree->GetBoundingBox().SurfaceArea();
1375        //return GetArea(viewCell) / GetTotalArea();
[468]1376}
1377
[475]1378float VspBspViewCellsManager::GetArea(ViewCell *viewCell) const
1379{
1380        PolygonContainer geom;
[468]1381
[475]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
[469]1391float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1392{
1393        return viewCell->GetPvs().GetSize() * objRendercost;
1394}
1395
[462]1396
[442]1397bool VspBspViewCellsManager::ViewCellsConstructed() const
1398{
1399        return mVspBspTree->GetRoot() != NULL;
1400}
1401
[462]1402
[442]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       
[469]1418        VssRayContainer constructionRays;
1419        VssRayContainer savedRays;
[442]1420
[469]1421        GetRaySets(rays, constructionRays, savedRays);
[473]1422       
[474]1423        mVspBspTree->Construct(constructionRays);
[467]1424        mVspBspTree->CollectViewCells(mViewCells);
[475]1425        mVspBspTree->EvaluateViewCellsStats(mViewCellsStats);
[442]1426       
1427        Debug << mVspBspTree->GetStatistics() << endl;
[469]1428       
1429        // recast rest of rays
1430        ComputeSampleContributions(savedRays);
[442]1431
1432        return sampleContributions;
1433}
1434
1435
[475]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
[442]1463int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1464                                                                                const VssRayContainer &rays)
[442]1465{
[475]1466        if (mBspRays.empty())
1467                ConstructBspRays(rays, mConstructionSamples);
1468       
[442]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
[475]1479        Debug << "original view cell partition:\n" << mViewCellsStats << endl;
[442]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                {
[475]1488                        //exporter->SetWireframe();
1489                        exporter->SetFilled();
1490                        exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
[442]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
[466]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)
[442]1515        //-- merge or subdivide view cells
1516        int merged = 0;
1517
[475]1518        vector<BspIntersection>::const_iterator iit;
[442]1519
[475]1520        for (int i = 0; i < (int)mBspRays.size(); ++ i)
[442]1521        { 
[475]1522                BspRay *ray = mBspRays[i];
[466]1523         
[475]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;
[466]1528         
[475]1529                iit = ray->intersections.begin();
[442]1530
[448]1531                BspLeaf *previousLeaf = (*iit).mLeaf;
[442]1532                ++ iit;
1533               
[475]1534                for (; iit != ray->intersections.end(); ++ iit)
[442]1535                {
[448]1536                        BspLeaf *leaf = (*iit).mLeaf;
[442]1537
1538                        if (ShouldMerge(leaf, previousLeaf))
1539                        {                       
[443]1540                                MergeVspBspLeafViewCells(leaf, previousLeaf);
[442]1541
1542                                ++ merged;
1543                        }
1544               
1545                        previousLeaf = leaf;
1546                }
1547        }
[475]1548
[442]1549        //-- stats and visualizations
1550        cout << "finished" << endl;
1551        cout << "merged " << merged << " view cells in "
1552                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1553
[475]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);
[448]1562
[442]1563        return merged;
1564}
1565
1566int VspBspViewCellsManager::GetType() const
1567{
1568        return VSP_BSP;
1569}
1570
1571
1572void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1573                                                                           const VssRayContainer &sampleRays)
[442]1574{
1575        if (!ViewCellsConstructed())
1576                return;
1577
[475]1578        if (mBspRays.empty())
1579                ConstructBspRays(sampleRays, mConstructionSamples);
1580       
[442]1581        if (1) // export view cells
1582        {
1583                cout << "exporting view cells after merge ... ";
[448]1584                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[442]1585
1586                if (exporter)
1587                {
[475]1588                        exporter->ExportBspViewCellPartition(*mVspBspTree, mViewCellsStats.maxPvs);
[442]1589                        delete exporter;
1590                }
[448]1591               
[442]1592                cout << "finished" << endl;
1593        }       
1594
1595        //-- visualization of the BSP splits
1596        bool exportSplits = false;
[448]1597        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[442]1598       
1599        if (exportSplits)
1600        {
1601                cout << "exporting splits ... ";
[475]1602                ExportSplits(objects);
[442]1603                cout << "finished" << endl;
1604        }
1605
[475]1606        ExportBspPvs(objects);
[442]1607}
1608
1609
[475]1610void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[442]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();
[448]1620               
1621                exporter->ExportBspSplits(*mVspBspTree, true);
[442]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                {
[475]1633                        VssRayContainer outRays;
[442]1634               
[475]1635                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
[442]1636
1637                        for (int i = 0; i < raysSize; ++ i)
1638                                // only rays piercing geometry
[475]1639                                outRays.push_back(mBspRays[i]->vssRay);
1640                                               
[442]1641                        // export rays
[466]1642                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
[442]1643                }
1644
1645                if (0)
1646                        exporter->ExportGeometry(objects);
1647
1648                delete exporter;
1649        }
1650}
1651
[475]1652void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[442]1653{
[469]1654        bool exportRays = false;
1655        bool exportGeometry = false;
1656
[473]1657        environment->GetBoolValue("VspBspTree.Visualization.exportRays", exportRays);
1658        environment->GetBoolValue("VspBspTree.Visualization.exportGeometry", exportGeometry);
[469]1659
[442]1660        const int leafOut = 10;
1661       
1662        ViewCell::NewMail();
1663
1664        //-- some rays for output
[475]1665        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[442]1666        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
[475]1667        Debug << "\nOutput view cells: " << endl;
1668
[448]1669        if (1)
[442]1670        {
1671                //-- some random view cells and rays for output
[448]1672                vector<BspLeaf *> vspBspLeaves;
[442]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                {
[469]1679                        VssRayContainer vcRays;
1680                        cout << "creating output for view cell " << i << " ... ";
[466]1681
[442]1682                        // check whether we can add the current ray to the output rays
[452]1683                        for (int k = 0; k < raysOut; ++ k)
[442]1684                        {
[475]1685                                BspRay *ray = mBspRays[k];
[442]1686
[475]1687                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[442]1688                                {
[475]1689                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
[442]1690
1691                                        if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell())
1692                                        {
[475]1693                                                vcRays.push_back(ray->vssRay);
[442]1694                                        }
1695                                }
1696                        }
[475]1697
[442]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
[469]1709                        ObjectPvsMap::iterator it = vc->GetPvs().mEntries.begin();
[442]1710
[475]1711                        exporter->SetWireframe();
1712                        //exporter->SetFilled();
[442]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                        {
[443]1722                                PolygonContainer vcGeom;
1723
[442]1724                                // export view cell geometry
[443]1725                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1726                                exporter->ExportPolygons(vcGeom);
1727                                CLEAR_CONTAINER(vcGeom);
[442]1728                        }
1729
1730                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[448]1731                                        << ", piercing rays=" << (int)vcRays.size() << endl;
[442]1732
1733                        // export rays piercing this view cell
[469]1734                        if (exportRays)
1735                        {
1736                                //exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
1737                                exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1));
1738                        }
1739
[448]1740                        m.mDiffuseColor = RgbColor(0, 1, 1);
[442]1741                        exporter->SetForcedMaterial(m);
1742
[469]1743                        //exporter->SetWireframe();
1744                        exporter->SetFilled();
[442]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                        }
[475]1756                        Debug << "here1 exportgeom: " << exportGeometry << endl;
[442]1757                        // output rest of the objects
[469]1758                        if (exportGeometry)
[442]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 << " ... ";
[466]1788                        VssRayContainer vcRays;
[442]1789            Intersectable::NewMail();
1790                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
1791
1792                        cout << "creating output for view cell " << i << " ... ";
[475]1793
[442]1794                        // check whether we can add the current ray to the output rays
1795                        for (int k = 0; k < raysOut; ++ k)
1796                        {
[475]1797                                BspRay *ray = mBspRays[k];
[442]1798
[475]1799                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[442]1800                                {
[475]1801                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
[442]1802
1803                                        if (vc == leaf->GetViewCell())
1804                                        {
[475]1805                                                vcRays.push_back(ray->vssRay);
[442]1806                                        }
1807                                }
1808                        }
[475]1809
[442]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                        {
[443]1825                                PolygonContainer vcGeom;
[442]1826                                // export view cell
[443]1827                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1828                                exporter->ExportPolygons(vcGeom);
1829                                CLEAR_CONTAINER(vcGeom);
[442]1830                        }
1831
1832                       
1833                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[475]1834                                  << ", piercing rays=" << (int)vcRays.size() << endl;
[442]1835
1836                       
1837                        // export rays piercing this view cell
[466]1838                        exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
[442]1839       
1840                        m.mDiffuseColor = RgbColor(1, 0, 0);
1841                        exporter->SetForcedMaterial(m);
1842
[469]1843                        ObjectPvsMap::const_iterator it,
[442]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        }
[475]1866
1867        Debug << endl;
[442]1868}
1869
1870
[463]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
[475]1881        // change view cells of all leaves
1882        // associated with the previous view cells
[463]1883        BspViewCell *fVc = front->GetViewCell();
1884        BspViewCell *bVc = back->GetViewCell();
1885
[469]1886        vector<BspLeaf *> fLeaves = fVc->mLeaves;
1887        vector<BspLeaf *> bLeaves = bVc->mLeaves;
[463]1888
1889        vector<BspLeaf *>::const_iterator it;
1890       
1891        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
1892        {
1893                (*it)->SetViewCell(viewCell);
[469]1894                viewCell->mLeaves.push_back(*it);
[463]1895        }
1896        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
1897        {
1898                (*it)->SetViewCell(viewCell);
[469]1899                viewCell->mLeaves.push_back(*it);
[463]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
[466]1933
[469]1934int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
1935                                                                                        const Vector3 &termination,
1936                                                                                        ViewCellContainer &viewcells)
[466]1937{
[469]1938        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]1939}
Note: See TracBrowser for help on using the repository browser.