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

Revision 563, 60.3 KB checked in by bittner, 18 years ago (diff)

rss sampling changes, preprocessor::GenerateRays?

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"
[508]13#include "ViewCellsParser.h"
[532]14#include "Beam.h"
[540]15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
[440]17
[517]18
[532]19
[440]20ViewCellsManager::ViewCellsManager():
[480]21mRenderer(NULL),
[440]22mConstructionSamples(0),
23mPostProcessSamples(0),
[470]24mVisualizationSamples(0),
25mTotalAreaValid(false),
[517]26mTotalArea(0.0f),
[547]27mViewCellsFinished(false),
[562]28mMaxPvsSize(9999999),
29mMinPvsSize(1), // only empty view cells are invalid
[561]30mMaxPvsRatio(1.0)
[440]31{
[542]32        mViewSpaceBox.Initialize();
[482]33        ParseEnvironment();
[440]34}
35
[517]36
[440]37ViewCellsManager::ViewCellsManager(int constructionSamples):
38mConstructionSamples(constructionSamples),
[480]39mRenderer(NULL),
[440]40mPostProcessSamples(0),
[517]41mVisualizationSamples(0),
[562]42mTotalAreaValid(false),
43mTotalArea(0.0f),
44mViewCellsFinished(false),
45mMaxPvsSize(9999999),
46mMinPvsSize(1), // only empty view cells are invalid
47mMaxPvsRatio(1.0)
[440]48{
[542]49        mViewSpaceBox.Initialize();
[482]50        ParseEnvironment();
51}
52
[517]53
[482]54void ViewCellsManager::ParseEnvironment()
55{
[503]56        // visualization stuff
[485]57        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
58        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
[547]59        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[485]60
[482]61        char buf[50];
[503]62
[482]63        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
[503]64
[482]65        if (strcmp(buf, "PVS") == 0)
66                mColorCode = 1;
67        else if (strcmp(buf, "MergedLeaves") == 0)
68                mColorCode = 2;
69        else if (strcmp(buf, "MergedTreeDiff") == 0)
70                mColorCode = 3;
71        else
72                mColorCode = 0;
73
74        Debug << "colorCode: " << mColorCode << endl;
[440]75}
76
[485]77
[440]78ViewCellsManager::~ViewCellsManager()
79{
[480]80        DEL_PTR(mRenderer);
[469]81        CLEAR_CONTAINER(mViewCells);
[503]82        CLEAR_CONTAINER(mMeshContainer);
[440]83}
84
[485]85
[527]86int ViewCellsManager::Construct(VssRayContainer &rays)
87{
[542]88/*      VssPreprocessor preprocessor;
[540]89
[542]90        VssRayContainer vssRays;
91        preprocessor->GenerateVssRays(mConstructionSamples, vssRays);
92        Construct(preprocessor->mObjects, vssRays);
93       
94        // add rays to output rays
95        while (!vssRays.empty)
96        {
97                rays.push_back(vssRays.back());
98                vssRays.pop_back();
99        }
[540]100
[542]101        const int importanceRays = 1000000;
102        preprocessor->GenerateVssRays(max(importanceRays, mPostProcessSamples);
[540]103
[542]104        PostProcess(preprocesor->mObjects, importanceRays);
105        Visualize(preprocessor->mObjects, importanceRays);
106
107        // add rays to output rays
108        while (!importanceRays.empty)
109        {
110                rays.push_back(importanceRays.back());
111                importanceRays.pop_back();
112        }
113*/
114        return (int)rays.size();
[527]115}
116
[547]117
[561]118bool ViewCellsManager::CheckValidity(ViewCell *vc,
[562]119                                                                         int minPvsSize,
120                                                                         int maxPvsSize) const
[547]121{
[562]122        if ((vc->GetPvs().GetSize() > mMaxPvsSize) ||
123                (vc->GetPvs().GetSize() < mMinPvsSize))
[561]124        {       
[547]125                return false;
[561]126        }
[547]127
128        return true;
129}
130
131
[562]132void ViewCellsManager::SetValidity(ViewCell *vc,
133                                                                   int minPvs,
134                                                                   int maxPvs) const
135{
136        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
137}
138
139
[508]140bool ViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
[440]141{
142        X3dParser parser;
[503]143
[440]144        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]145
[440]146        bool success = parser.ParseFile(filename, *this);
147        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
148
149        return success;
150}
151
[485]152
[487]153bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
154{
[542]155        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]156
157        return true;
158}
159
160
[557]161float ViewCellsManager::GetViewSpaceVolume()
162{
163        return mViewSpaceBox.GetVolume()*(2.0f*sqr(M_PI));
164}
165
166
[490]167bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
168{
[542]169        return mViewSpaceBox.IsInside(viewPoint);
[490]170}
171
[501]172
[563]173float
174ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
175                                                                                         const bool addRays
176                                                                                         )
[440]177{
[563]178  // view cells not yet constructed
179  if (!ViewCellsConstructed())
180        return 0.0f;
181 
182  VssRayContainer::const_iterator it, it_end = rays.end();
[503]183
[563]184  float sum = 0.0f;
185  for (it = rays.begin(); it != it_end; ++ it) {
186        sum += ComputeSampleContributions(*(*it), addRays);
187  }
188  return sum;
[440]189}
190
[485]191
[479]192void ViewCellsManager::EvaluateViewCellsStats()
193{
194        mViewCellsStats.Reset();
195
196        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
197
198        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]199        {
[479]200                (*it)->UpdateViewCellsStats(mViewCellsStats);
[487]201        }
[479]202}
203
[485]204
[440]205void ViewCellsManager::AddViewCell(ViewCell *viewCell)
206{
207        mViewCells.push_back(viewCell);
208}
209
[485]210
[478]211float ViewCellsManager::GetArea(ViewCell *viewCell) const
212{
213        return viewCell->GetArea();
214}
215
216
217float ViewCellsManager::GetVolume(ViewCell *viewCell) const
218{
219        return viewCell->GetVolume();
220}
221
[485]222
[503]223void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
224                                                                           ViewCellContainer &viewCells,
[440]225                                                                           const int maxViewCells) const
226{
227        // maximal max viewcells
[503]228        int limit = maxViewCells > 0 ?
[440]229                Min((int)objects.size(), maxViewCells) : (int)objects.size();
230
231        for (int i = 0; i < limit; ++ i)
232        {
233                Intersectable *object = objects[i];
[503]234
[440]235                // extract the mesh instances
236                if (object->Type() == Intersectable::MESH_INSTANCE)
237                {
238                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
239
240                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
241                        viewCells.push_back(viewCell);
242                }
243                //TODO: transformed meshes
244        }
245}
246
[485]247
[503]248ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]249                                                                                        const float height) const
250{
251        // one mesh per view cell
252        Mesh *mesh = new Mesh();
[503]253
[440]254        //-- construct prism
255
[503]256        // bottom
[440]257        mesh->mFaces.push_back(new Face(2,1,0));
258        // top
259    mesh->mFaces.push_back(new Face(3,4,5));
260        // sides
261        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
262        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
263        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
264
265        //--- extrude new vertices for top of prism
266        Vector3 triNorm = baseTri.GetNormal();
267
[503]268        Triangle3 topTri;
[440]269
270        // add base vertices and calculate top vertices
271        for (int i = 0; i < 3; ++ i)
272                mesh->mVertices.push_back(baseTri.mVertices[i]);
[503]273
274        // add top vertices
[440]275        for (int i = 0; i < 3; ++ i)
276                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]277
[440]278        mesh->Preprocess();
279
280        return GenerateViewCell(mesh);
281}
282
[485]283
[551]284void ViewCellsManager::FinalizeViewCells(const bool createMesh)
285{
286        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
287        for (it = mViewCells.begin(); it != it_end; ++ it)
288        {
289                Finalize(*it, createMesh);
290        }
[555]291
292        mTotalAreaValid = false;
[551]293}
294
295
296void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
297{
298        // implemented in subclasses
299}
300
301
[441]302ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
[440]303{
[462]304        // generate merged view cell
[440]305        ViewCell *vc = GenerateViewCell();
[462]306
[440]307        // merge pvs
308        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
309
[462]310        //-- merge ray sets
[440]311        stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
312        stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
313
314        std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
[503]315                           back.mPiercingRays.begin(), back.mPiercingRays.end(),
[440]316                           vc->mPiercingRays.begin());
317
318        return vc;
319}
320
[485]321
[480]322void ViewCellsManager::SetRenderer(Renderer *renderer)
323{
324        mRenderer = renderer;
325}
[441]326
[485]327
[440]328ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
329{
330        return new ViewCell(mesh);
331}
332
333
334void ViewCellsManager::SetVisualizationSamples(const int visSamples)
335{
[444]336        mVisualizationSamples = visSamples;
[440]337}
338
[485]339
[440]340void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
341{
342        mConstructionSamples = constructionSamples;
343}
344
[485]345
[440]346void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
347{
348        mPostProcessSamples = postProcessSamples;
349}
350
[485]351
[440]352int ViewCellsManager::GetVisualizationSamples() const
353{
354        return mVisualizationSamples;
355}
356
[485]357
[440]358int ViewCellsManager::GetConstructionSamples() const
359{
360        return mConstructionSamples;
361}
362
[485]363
[440]364int ViewCellsManager::GetPostProcessSamples() const
365{
366        return mPostProcessSamples;
367}
368
[485]369
370void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]371{
372  ViewCellContainer::const_iterator it = mViewCells.begin();
373  stat.viewcells = 0;
374  stat.minPvs = 100000000;
375  stat.maxPvs = 0;
376  stat.avgPvs = 0.0f;
377
378  for (; it != mViewCells.end(); ++it) {
379        ViewCell *viewcell = *it;
380        int pvsSize = viewcell->GetPvs().GetSize();
381        if ( pvsSize < stat.minPvs)
382          stat.minPvs = pvsSize;
383        if (pvsSize > stat.maxPvs)
384          stat.maxPvs = pvsSize;
385        stat.avgPvs += pvsSize;
386        stat.viewcells++;
387  }
388  if (stat.viewcells)
389        stat.avgPvs/=stat.viewcells;
390}
391
[485]392
[480]393void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]394{
395  s<<"############# Viewcell PVS STAT ##################\n";
396  PvsStatistics pvsStat;
397  GetPvsStatistics(pvsStat);
398  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
399  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
400  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
401}
402
[485]403
[532]404int ViewCellsManager::CastBeam(Beam &beam)
405{
406        return 0;
407}
408
[547]409
[468]410ViewCellContainer &ViewCellsManager::GetViewCells()
411{
412        return mViewCells;
413}
414
[485]415
[487]416void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
417{
[542]418        mViewSpaceBox = box;
[487]419}
420
421
[519]422AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
423{
[542]424        return mViewSpaceBox;
[519]425}
426
427
[480]428void ViewCellsManager::ResetViewCells()
429{
430        mViewCells.clear();
[508]431       
[480]432        CollectViewCells();
[508]433       
[480]434        mViewCellsStats.Reset();
435        EvaluateViewCellsStats();
[520]436        // has to be recomputed
[480]437        mTotalAreaValid = false;
438}
439
[485]440
[547]441int ViewCellsManager::GetMaxPvsSize() const
442{
443        return mMaxPvsSize;
444}
445
[563]446void
447ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
448{
449  if (!ViewCellsConstructed())
450        return;
451 
452  VssRayContainer::const_iterator it, it_end = rays.end();
453 
454  for (it = rays.begin(); it != it_end; ++ it) {
455        AddSampleContributions(*(*it));
456  }
457}
[547]458
[562]459int ViewCellsManager::GetMinPvsSize() const
460{
461        return mMinPvsSize;
462}
463
464
465
[561]466float ViewCellsManager::GetMaxPvsRatio() const
467{
468        return mMaxPvsRatio;
469}
470
471
[563]472void
473ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]474{
[563]475  // assumes viewcells have been stored...
476  ViewCellContainer *viewcells = &ray.mViewCells;
477  ViewCellContainer::const_iterator it;
478  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
479        ViewCell *viewcell = *it;
480        // if ray not outside of view space
481        viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
482  }
483}
[503]484
[563]485float
486ViewCellsManager::ComputeSampleContributions(VssRay &ray,
487                                                                                         const bool addRays
488                                                                                         )
489{
490  ViewCellContainer viewcells;
491 
492  ray.mPvsContribution = 0;
493  ray.mRelativePvsContribution = 0.0f;
494 
495  // matt TODO: remove this!!
496  Ray hray(ray);
497  float tmin = 0, tmax = 1.0;
498 
499  //hray.Init(ray.GetOrigin(), ray.GetDir(), Ray::LINE_SEGMENT);
500  if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
501        return 0.0f;
502 
503  Vector3 origin = hray.Extrap(tmin);
504  Vector3 termination = hray.Extrap(tmax);
[485]505
[563]506  CastLineSegment(origin,
507                                  termination,
508                                  viewcells);
509 
510  //Debug << "constribution: " << (int)viewcells.size() << endl;
511 
512  // copy viewcells memory efficiently
513  const bool storeViewcells = !addRays;
514 
515  if (storeViewcells)
[542]516        {
[563]517          ray.mViewCells.reserve(viewcells.size());
518          ray.mViewCells = viewcells;
[542]519        }
[563]520 
521  ViewCellContainer::const_iterator it = viewcells.begin();
522 
523 
524  for (; it != viewcells.end(); ++it) {
525        ViewCell *viewcell = *it;
526        // if ray not outside of view space
527        float contribution;
528        if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
529                                                                                                 ray.mPdf,
530                                                                                                 contribution
531                                                                                                 ))
532          ray.mPvsContribution++;
533        ray.mRelativePvsContribution += contribution;
534  }
535 
536  if (addRays)
537        for (it = viewcells.begin(); it != viewcells.end(); ++it) {
538          ViewCell *viewcell = *it;
539          // if ray not outside of view space
540          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
541        }
[503]542
[563]543  return ray.mRelativePvsContribution;
[468]544}
545
546
[469]547void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]548                                                                  const int maxSize,
[503]549                                                                  VssRayContainer &usedRays,
[485]550                                                                  VssRayContainer *savedRays) const
[469]551{
[485]552        const int limit = min(maxSize, (int)sourceRays.size());
[473]553        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]554
[485]555        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]556        for (it = sourceRays.begin(); it != it_end; ++ it)
557        {
[473]558                if (Random(1.0f) < prop)
[485]559                        usedRays.push_back(*it);
560                else if (savedRays)
561                        savedRays->push_back(*it);
[469]562        }
563}
564
[477]565
566float ViewCellsManager::GetAccVcArea()
[470]567{
568        // if already computed
569        if (mTotalAreaValid)
570                return mTotalArea;
571
572        mTotalArea = 0;
573        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
574
575        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]576        {
577                //Debug << "area: " << GetArea(*it);
[470]578        mTotalArea += GetArea(*it);
[480]579        }
580
[470]581        mTotalAreaValid = true;
582
583        return mTotalArea;
584}
585
[482]586
[475]587void ViewCellsManager::PrintStatistics(ostream &s) const
588{
589        s << mViewCellsStats << endl;
590}
591
[477]592
[508]593void ViewCellsManager::CreateUniqueViewCellIds()
[482]594{
[508]595        for (int i = 0; i < (int)mViewCells.size(); ++ i)
596                mViewCells[i]->SetId(i);
597}
598
599
600void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
601{
[482]602        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
603
604        for (it = mViewCells.begin(); it != it_end; ++ it)
605        {
606                ExportColor(exporter, *it);
[485]607                ExportVcGeometry(exporter, *it);
[482]608        }
609}
610
611
[517]612void ViewCellsManager::CreateViewCellMeshes()
[503]613{
614        // convert to meshes
615        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
616
617        for (it = mViewCells.begin(); it != it_end; ++ it)
618        {
[517]619                if (!(*it)->GetMesh())
620                        CreateMesh(*it);
[503]621        }
622}
623
[508]624
625bool ViewCellsManager::ExportViewCells(const string filename)
626{
627        return false;
628}
629
630
631void ViewCellsManager::ExportViewCell(ViewCell *viewCell, ofstream &stream)
632{
633        stream << "<ViewCell id=\"" << viewCell->GetId() << "\" ";
634        stream << "pvs=\"";
635
636        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
637        if(0) // test with empty pvs
638        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
639        {
640                stream << (*it).first->GetId() << " ";
641        }
642
643        stream << "\" />" << endl;
644}
645
646
[440]647/**********************************************************************/
648/*                   BspViewCellsManager implementation               */
649/**********************************************************************/
650
[482]651
[503]652BspViewCellsManager::BspViewCellsManager(BspTree *bspTree,
[469]653                                                                                 int constructionSamples):
[503]654ViewCellsManager(constructionSamples),
[440]655mBspTree(bspTree)
656{
657}
658
[462]659
[440]660bool BspViewCellsManager::ViewCellsConstructed() const
661{
662        return mBspTree->GetRoot() != NULL;
663}
664
[480]665
[440]666ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
667{
668        return new BspViewCell(mesh);
669}
670
[480]671
[503]672int BspViewCellsManager::Construct(const ObjectContainer &objects,
[487]673                                                                   const VssRayContainer &rays)
[440]674{
[441]675        // if view cells were already constructed
[440]676        if (ViewCellsConstructed())
677                return 0;
678
679        int sampleContributions = 0;
[503]680
[469]681        // construct view cells using the collected samples
682        RayContainer constructionRays;
683        VssRayContainer savedRays;
[440]684
[469]685        const int limit = min(mConstructionSamples, (int)rays.size());
[440]686
[469]687        VssRayContainer::const_iterator it, it_end = rays.end();
[448]688
[473]689        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
690
[469]691        for (it = rays.begin(); it != it_end; ++ it)
692        {
[473]693                if (Random(1.0f) < prop)
[469]694                        constructionRays.push_back(new Ray(*(*it)));
695                else
696                        savedRays.push_back(*it);
697        }
[440]698
[503]699    if (mViewCells.empty())
700        {
701                // no view cells loaded
[469]702                mBspTree->Construct(objects, constructionRays);
703                // collect final view cells
704                mBspTree->CollectViewCells(mViewCells);
[503]705        }
[469]706        else
707        {
708                mBspTree->Construct(mViewCells);
709        }
710
711        // destroy rays created only for construction
712        CLEAR_CONTAINER(constructionRays);
713
[440]714        Debug << mBspTree->GetStatistics() << endl;
[503]715
716        //EvaluateViewCellsStats();
[480]717        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
718
[469]719        // recast rest of the rays
720        ComputeSampleContributions(savedRays);
721
[503]722
[440]723        return sampleContributions;
724}
725
[503]726
[480]727void BspViewCellsManager::CollectViewCells()
728{
729        mBspTree->CollectViewCells(mViewCells);
730}
[468]731
[503]732
[471]733float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]734{
[471]735        // compute view cell area as subsititute for probability
[557]736#if 1
737        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[477]738#else
739        return GetArea(viewCell) / GetAccVcArea();
740#endif
[466]741}
[440]742
[503]743
[469]744float BspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[466]745{
[468]746        return viewCell->GetPvs().GetSize() * objRendercost;
[440]747}
748
[468]749
750int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
751                                                                                 const Vector3 &termination,
752                                                                                 ViewCellContainer &viewcells)
[440]753{
[468]754        return mBspTree->CastLineSegment(origin, termination, viewcells);
755}
756
757
[503]758int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]759                                                                         const VssRayContainer &rays)
760{
[469]761        if (!ViewCellsConstructed())
[441]762        {
763                Debug << "view cells not constructed" << endl;
764                return 0;
765        }
766
[440]767        //-- post processing of bsp view cells
768    int vcSize = 0;
769        int pvsSize = 0;
770
[480]771        EvaluateViewCellsStats();
[485]772        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
[480]773
774        mRenderer->RenderScene();
775        SimulationStatistics ss;
776        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
777
778    Debug << ss << endl;
779
[477]780        if (1) // export view cells
[440]781        {
782                cout << "exporting initial view cells (=leaves) ... ";
783                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]784
[440]785                if (exporter)
786                {
[477]787                        //exporter->SetWireframe();
788                        exporter->SetFilled();
[508]789                        ExportViewCellsForViz(exporter);
[503]790
[485]791                        if (mExportGeometry)
[440]792                        {
[477]793                                Material m;
[440]794                                m.mDiffuseColor = RgbColor(0, 1, 0);
795                                exporter->SetForcedMaterial(m);
796                                exporter->SetWireframe();
797
798                                exporter->ExportGeometry(objects);
799                        }
800
801                        delete exporter;
802                }
803                cout << "finished" << endl;
804        }
805
806        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
[503]807
[440]808        long startTime = GetTime();
809
[477]810
[466]811        // $$JB we do not have connectivity information from the ray in the moment
[485]812        // perhaps we could recast the rays or remember the cells traversed inside the
[466]813        // vssray (which would on other hand create some overhead)
[440]814        //-- merge or subdivide view cells
815        int merged = 0;
816
[475]817        vector<BspIntersection>::const_iterator iit;
[485]818        CLEAR_CONTAINER(mBspRays);
819        ConstructBspRays(rays, mPostProcessSamples);
[503]820
[477]821        for (int i = 0; i < (int)mBspRays.size(); ++ i)
[503]822        {
[477]823                BspRay *ray = mBspRays[i];
[503]824
[440]825                // traverse leaves stored in the rays and compare and merge consecutive
826                // leaves (i.e., the neighbors in the tree)
[477]827                if (ray->intersections.size() < 2)
[440]828                        continue;
[561]829#if 0
[477]830                iit = ray->intersections.begin();
[440]831
832                BspLeaf *previousLeaf = (*iit).mLeaf;
833                ++ iit;
[503]834
[477]835                for (; iit != ray->intersections.end(); ++ iit)
[440]836                {
837                        BspLeaf *leaf = (*iit).mLeaf;
838
[441]839                        if (ShouldMerge(leaf, previousLeaf))
[503]840                        {
[441]841                                MergeBspLeafViewCells(leaf, previousLeaf);
[440]842
843                                ++ merged;
844                        }
[503]845
[440]846                        previousLeaf = leaf;
847                }
[561]848#endif
[440]849        }
[477]850
[440]851        //-- stats and visualizations
852        cout << "finished" << endl;
853        cout << "merged " << merged << " view cells in "
854                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
855
[475]856        Debug << "Postprocessing: Merged " << merged << " view cells in "
[503]857                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
[485]858                  << "using " << (int)mBspRays.size() << " samples" << endl << endl;
[503]859
[485]860        CLEAR_CONTAINER(mBspRays);
861
[477]862        // reset view cells and stats
[480]863        ResetViewCells();
[475]864
[440]865        return merged;
866}
867
[477]868
869BspViewCellsManager::~BspViewCellsManager()
870{
871        CLEAR_CONTAINER(mBspRays);
872}
873
874
[440]875int BspViewCellsManager::GetType() const
876{
877        return BSP;
878}
879
880
881void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]882                                                                        const VssRayContainer &sampleRays)
[440]883{
[469]884        if (!ViewCellsConstructed())
885                return;
[485]886        CLEAR_CONTAINER(mBspRays);
887        ConstructBspRays(sampleRays, mVisualizationSamples);
[503]888
[469]889        if (1) // export view cells
[440]890        {
[469]891                cout << "exporting view cells after merge ... ";
892                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[477]893
[557]894
[469]895                if (exporter)
[440]896                {
[508]897                        ExportViewCellsForViz(exporter);
[469]898                        delete exporter;
[440]899                }
[503]900
[469]901                cout << "finished" << endl;
[503]902        }
[477]903
[469]904        //-- visualization of the BSP splits
905        bool exportSplits = false;
906        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]907
[469]908        if (exportSplits)
[440]909        {
[469]910                cout << "exporting splits ... ";
[477]911                ExportSplits(objects);
[469]912                cout << "finished" << endl;
[440]913        }
[477]914
915        ExportBspPvs(objects);
[440]916}
917
918
[503]919inline bool vc_gt(ViewCell *a, ViewCell *b)
920{
[440]921        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
922}
923
[477]924
925void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]926{
927        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
928
[503]929        if (exporter)
930        {
931                Material m;
[440]932                m.mDiffuseColor = RgbColor(1, 0, 0);
933                exporter->SetForcedMaterial(m);
934                exporter->SetWireframe();
[503]935
[440]936                exporter->ExportBspSplits(*mBspTree, true);
937
[482]938                //NOTE: take forced material, else big scenes cannot be viewed
[440]939                m.mDiffuseColor = RgbColor(0, 1, 0);
940                exporter->SetForcedMaterial(m);
[482]941                //exporter->ResetForcedMaterial();
942
[440]943                exporter->SetFilled();
[503]944
[440]945                // export rays
[477]946                if (0)
[440]947                {
[469]948                        VssRayContainer outRays;
[503]949
[477]950                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
951
[469]952                        for (int i = 0; i < raysSize; ++ i)
953                                // only rays piercing geometry
[477]954                                outRays.push_back(mBspRays[i]->vssRay);
[503]955
956                        // export rays
[469]957                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
[440]958                }
[477]959
[485]960                if (mExportGeometry)
[469]961                        exporter->ExportGeometry(objects);
[477]962
[440]963                delete exporter;
964        }
965}
966
[477]967
968void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]969{
[477]970        const int leafOut = 10;
[503]971
[477]972        ViewCell::NewMail();
[440]973
[477]974        //-- some rays for output
975        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]976
[477]977        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
978        Debug << "\nOutput view cells: " << endl;
[503]979
[478]980        // sort view cells to get largest view cells
981#if 0
982        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
983#endif
[503]984        int limit = min(leafOut, (int)mViewCells.size());
985
[478]986        for (int i = 0; i < limit; ++ i)
[477]987        {
[478]988                cout << "creating output for view cell " << i << " ... ";
989                VssRayContainer vcRays;
990                Intersectable::NewMail();
991#if 0
992                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
993#else
994                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[Random((int)mViewCells.size())]);
995#endif
996                cout << "creating output for view cell " << i << " ... ";
[469]997
[478]998#if 0
999                // check whether we can add the current ray to the output rays
[503]1000                for (int k = 0; k < raysOut; ++ k)
[477]1001                {
[478]1002                        BspRay *ray = mBspRays[k];
1003                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[477]1004                        {
[478]1005                                BspLeaf *leaf = ray->intersections[j].mLeaf;
[503]1006                                if (vc == leaf->GetViewCell())
[478]1007                                        vcRays.push_back(ray->vssRay);
[477]1008                        }
1009                }
[478]1010#endif
1011                //bspLeaves[j]->Mail();
1012                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]1013
[478]1014                Exporter *exporter = Exporter::GetExporter(s);
[503]1015
[478]1016                exporter->SetWireframe();
[477]1017
[478]1018                Material m;//= RandomMaterial();
1019                m.mDiffuseColor = RgbColor(0, 1, 0);
1020                exporter->SetForcedMaterial(m);
[477]1021
[478]1022                if (vc->GetMesh())
1023                        exporter->ExportViewCell(vc);
1024                else
1025                {
[503]1026                        BspNodeGeometry vcGeom;
1027
[478]1028                        //-- export view cell
1029                        mBspTree->ConstructGeometry(vc, vcGeom);
[503]1030                        exporter->ExportPolygons(vcGeom.mPolys);
[478]1031                }
[503]1032
1033                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[485]1034                          << ", piercing rays=" << (int)vcRays.size()
1035                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
[477]1036
[503]1037
[478]1038                // export rays piercing this view cell
1039#if 0
1040                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1041#else
1042                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
1043                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
1044                        exporter->ExportRays((*lit)->mVssRays);
1045#endif
1046                m.mDiffuseColor = RgbColor(1, 0, 0);
1047                exporter->SetForcedMaterial(m);
[440]1048
[478]1049                ObjectPvsMap::const_iterator it,
1050                        it_end = vc->GetPvs().mEntries.end();
[440]1051
[478]1052                exporter->SetFilled();
[469]1053
[478]1054                // output PVS of view cell
[503]1055                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]1056                {
1057                        Intersectable *intersect = (*it).first;
[469]1058
[478]1059                        if (!intersect->Mailed())
1060                        {
1061                                Material m = RandomMaterial();
1062                                exporter->SetForcedMaterial(m);
1063
1064                                exporter->ExportIntersectable(intersect);
1065                                intersect->Mail();
[503]1066                        }
[477]1067                }
[503]1068
[478]1069                DEL_PTR(exporter);
1070                cout << "finished" << endl;
[477]1071        }
1072
1073        Debug << endl;
[440]1074}
1075
[441]1076
[503]1077
[477]1078void BspViewCellsManager::ConstructBspRays(const VssRayContainer &rays,
1079                                                                                   const int numSamples)
1080{
1081        VssRayContainer::const_iterator it, it_end = rays.end();
[467]1082
[477]1083        for (it = rays.begin(); it != rays.end() && mBspRays.size() < numSamples; ++ it)
1084        {
1085                VssRay *vssRay = *it;
1086                BspRay *ray = new BspRay(vssRay);
1087
1088                ViewCellContainer viewCells;
1089
[483]1090                // cast line segment to get intersections with bsp leaves
[477]1091                CastLineSegment(vssRay->mTermination, vssRay->mOrigin, viewCells);
1092
1093                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
1094                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
1095                {
1096                        BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
1097                        ray->intersections.push_back(BspIntersection(0, vc->mLeaves[0]));
1098                }
1099
1100                mBspRays.push_back(ray);
1101        }
1102}
1103
1104
[503]1105void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]1106                                                                          ViewCell *vc) const
1107{
1108        if (mColorCode == 0) // Random color
1109        {
1110                exporter->ResetForcedMaterial();
1111                return;
1112        }
1113
1114        float importance = 0;
1115
1116        switch (mColorCode)
1117        {
1118        case 1: // pvs
1119                {
[503]1120                        importance = (float)vc->GetPvs().GetSize() /
[482]1121                                (float)mViewCellsStats.maxPvs;
1122                }
1123                break;
1124        case 2: // merges
1125                {
1126                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
1127
[503]1128                        importance = (float)bspVc->mLeaves.size() /
[482]1129                                (float)mViewCellsStats.maxLeaves;
1130                }
1131                break;
1132        case 3: // merge tree differene
1133                {
1134                        // TODO
1135                }
1136                break;
1137        default:
1138                break;
1139        }
1140
1141        Material m;
1142        m.mDiffuseColor.b = 1.0f;
1143        m.mDiffuseColor.r = importance;
1144        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[503]1145
[482]1146        exporter->SetForcedMaterial(m);
1147}
1148
[503]1149void BspViewCellsManager::ExportVcGeometry(Exporter *exporter,
[482]1150                                                                                 ViewCell *vc) const
1151{
1152        if (vc->GetMesh())
1153                exporter->ExportViewCell(vc);
1154        else
1155        {
[503]1156                BspNodeGeometry geom;
[485]1157                mBspTree->ConstructGeometry(
[503]1158                        dynamic_cast<BspViewCell *>(vc), geom);
1159                exporter->ExportPolygons(geom.mPolys);
[482]1160        }
1161}
1162
[503]1163
1164void BspViewCellsManager::CreateMesh(ViewCell *vc)
1165{
[551]1166        // TODO
[503]1167}
1168
[551]1169
1170ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point)
[502]1171{
1172  if (!mBspTree)
1173        return NULL;
1174  return mBspTree->GetViewCell(point);
1175}
1176
[440]1177/**********************************************************************/
1178/*                   KdViewCellsManager implementation               */
1179/**********************************************************************/
1180
[503]1181
1182
[440]1183KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]1184ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]1185{
1186}
1187
[471]1188float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1189{
[479]1190        // compute view cell area / volume as subsititute for probability
[477]1191#if 0
[519]1192        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[479]1193#endif
1194#if 1
[477]1195        return GetArea(viewCell) / GetAccVcArea();
1196#endif
[479]1197#if 0
[519]1198        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[479]1199#endif
[468]1200}
1201
1202
[469]1203float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1204{
[469]1205        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1206}
1207
[479]1208
[480]1209void KdViewCellsManager::CollectViewCells()
1210{
1211        //mKdTree->CollectViewCells(mViewCells); TODO
1212}
[479]1213
[519]1214
[503]1215int KdViewCellsManager::Construct(const ObjectContainer &objects,
[487]1216                                                                  const VssRayContainer &rays)
[440]1217{
[441]1218        // if view cells already constructed
[440]1219        if (ViewCellsConstructed())
1220                return 0;
[441]1221
[440]1222        mKdTree->Construct();
1223
[480]1224        mTotalAreaValid = false;
[469]1225        // create the view cells
1226        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]1227
[480]1228        // cast rays
1229        ComputeSampleContributions(rays);
1230
[479]1231        EvaluateViewCellsStats();
[480]1232        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[469]1233
[440]1234        return 0;
1235}
1236
1237bool KdViewCellsManager::ViewCellsConstructed() const
1238{
1239        return mKdTree->GetRoot() != NULL;
1240}
1241
[503]1242int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1243                                                                        const VssRayContainer &rays)
[440]1244{
1245        return 0;
1246}
1247
1248void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1249                                                                   const VssRayContainer &sampleRays)
[440]1250{
[441]1251        if (!ViewCellsConstructed())
1252                return;
1253
[469]1254        // using view cells instead of the kd PVS of objects
1255        const bool useViewCells = true;
1256        bool exportRays = false;
[440]1257
1258        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]1259        const int pvsOut = min((int)objects.size(), 10);
[466]1260        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]1261
[469]1262        if (useViewCells)
[440]1263        {
[469]1264                const int leafOut = 10;
[503]1265
[469]1266                ViewCell::NewMail();
[503]1267
[469]1268                //-- some rays for output
1269                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1270                Debug << "visualization using " << raysOut << " samples" << endl;
1271
1272                //-- some random view cells and rays for output
1273                vector<KdLeaf *> kdLeaves;
[503]1274
[469]1275                for (int i = 0; i < leafOut; ++ i)
1276                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]1277
[469]1278                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]1279                {
[469]1280                        KdLeaf *leaf = kdLeaves[i];
1281                        RayContainer vcRays;
[503]1282
[469]1283                        cout << "creating output for view cell " << i << " ... ";
[503]1284#if 0
[469]1285                        // check whether we can add the current ray to the output rays
[503]1286                        for (int k = 0; k < raysOut; ++ k)
[440]1287                        {
[469]1288                                Ray *ray = sampleRays[k];
[503]1289
[469]1290                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1291                                {
1292                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]1293
1294                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]1295                                        {
1296                                                vcRays.push_back(ray);
1297                                        }
1298                                }
[479]1299                        }
[503]1300#endif
[469]1301                        Intersectable::NewMail();
[503]1302
[469]1303                        ViewCell *vc = leaf->mViewCell;
[503]1304
[469]1305                        //bspLeaves[j]->Mail();
1306                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]1307
[469]1308                        Exporter *exporter = Exporter::GetExporter(s);
1309                        exporter->SetFilled();
1310
1311                        exporter->SetWireframe();
1312                        //exporter->SetFilled();
[503]1313
[469]1314                        Material m;//= RandomMaterial();
1315                        m.mDiffuseColor = RgbColor(1, 1, 0);
1316                        exporter->SetForcedMaterial(m);
[503]1317
[469]1318                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1319                        exporter->ExportBox(box);
1320
[503]1321                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[469]1322                                << ", piercing rays=" << (int)vcRays.size() << endl;
[503]1323
[469]1324                        // export rays piercing this view cell
[503]1325                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1326
[469]1327                        m.mDiffuseColor = RgbColor(1, 0, 0);
1328                        exporter->SetForcedMaterial(m);
[503]1329
[469]1330                        // exporter->SetWireframe();
1331                        exporter->SetFilled();
[503]1332
[469]1333                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1334                        // output PVS of view cell
[503]1335                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]1336                        {
1337                                Intersectable *intersect = (*it).first;
1338                                if (!intersect->Mailed())
1339                                {
1340                                        exporter->ExportIntersectable(intersect);
1341                                        intersect->Mail();
[503]1342                                }
[440]1343                        }
[503]1344
[469]1345                        DEL_PTR(exporter);
1346                        cout << "finished" << endl;
[440]1347                }
[469]1348
1349                DEL_PTR(rays);
[440]1350        }
[469]1351        else // using kd PVS of objects
1352        {
1353                for (int i = 0; i < limit; ++ i)
1354                {
1355                        VssRay *ray = sampleRays[i];
[503]1356
[469]1357                        // check whether we can add this to the rays
[503]1358                        for (int j = 0; j < pvsOut; j++)
[469]1359                        {
1360                                if (objects[j] == ray->mTerminationObject)
1361                                {
1362                                        rays[j].push_back(ray);
1363                                }
1364                        }
1365                }
[440]1366
[503]1367                if (exportRays)
[469]1368                {
1369                        Exporter *exporter = NULL;
1370                        exporter = Exporter::GetExporter("sample-rays.x3d");
1371                        exporter->SetWireframe();
1372                        exporter->ExportKdTree(*mKdTree);
[503]1373
1374                        for (i=0; i < pvsOut; i++)
[469]1375                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1376
1377                        exporter->SetFilled();
[503]1378
[469]1379                        delete exporter;
1380                }
[440]1381
[503]1382                for (int k=0; k < pvsOut; k++)
[469]1383                {
1384                        Intersectable *object = objects[k];
[503]1385                        char s[64];
[469]1386                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]1387
[469]1388                        Exporter *exporter = Exporter::GetExporter(s);
1389                        exporter->SetWireframe();
[503]1390
[469]1391                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1392                        Intersectable::NewMail();
[503]1393
[469]1394                        // avoid adding the object to the list
1395                        object->Mail();
1396                        ObjectContainer visibleObjects;
[503]1397
1398                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]1399                        {
1400                                KdNode *node = (*i).first;
1401                                exporter->ExportBox(mKdTree->GetBox(node));
[503]1402
[469]1403                                mKdTree->CollectObjects(node, visibleObjects);
1404                        }
[503]1405
[469]1406                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1407                        exporter->SetFilled();
[503]1408
[469]1409                        for (int j = 0; j < visibleObjects.size(); j++)
1410                                exporter->ExportIntersectable(visibleObjects[j]);
[503]1411
[469]1412                        Material m;
1413                        m.mDiffuseColor = RgbColor(1, 0, 0);
1414                        exporter->SetForcedMaterial(m);
1415                        exporter->ExportIntersectable(object);
[503]1416
[469]1417                        delete exporter;
[440]1418                }
[503]1419        }
[440]1420}
1421
[469]1422
[482]1423void KdViewCellsManager::ExportColor(Exporter *exporter,
1424                                                                         ViewCell *vc) const
1425{
1426        // TODO
1427}
1428
1429
[503]1430void KdViewCellsManager::ExportVcGeometry(Exporter *exporter,
[485]1431                                                                                  ViewCell *vc) const
[482]1432{
[485]1433        KdViewCell *kdVc = dynamic_cast<KdViewCell *>(vc);
1434        vector<KdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1435
1436        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
1437                exporter->ExportBox(mKdTree->GetBox(*it));
[482]1438}
1439
1440
[440]1441int KdViewCellsManager::GetType() const
1442{
1443        return ViewCellsManager::KD;
1444}
1445
1446
[441]1447
[440]1448KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1449{
1450        KdNode *node = leaf;
1451
1452        while (node->mParent && node->mDepth > mKdPvsDepth)
1453                node = node->mParent;
1454        return node;
1455}
1456
[469]1457int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1458                                                                                const Vector3 &termination,
1459                                                                                ViewCellContainer &viewcells)
[466]1460{
[469]1461        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]1462}
1463
[469]1464
[503]1465void KdViewCellsManager::CreateMesh(ViewCell *vc)
1466{
[551]1467        // TODO
[503]1468}
1469
[440]1470/**********************************************************************/
1471/*                   VspKdViewCellsManager implementation             */
1472/**********************************************************************/
1473
[482]1474
[503]1475VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
[462]1476                                                                                         int constructionSamples):
[503]1477ViewCellsManager(constructionSamples),
[440]1478mVspKdTree(vspKdTree)
1479{
[468]1480        mVspKdTree->SetViewCellsManager(this);
1481}
[462]1482
[471]1483float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1484{
1485        // volume or area substitutes for view point probability
[480]1486#if 0
[519]1487        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[480]1488#else
1489        return GetArea(viewCell) / GetAccVcArea();
1490#endif
[440]1491}
1492
[462]1493
[469]1494float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1495{
[469]1496        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1497}
1498
[503]1499
[480]1500void VspKdViewCellsManager::CollectViewCells()
1501{
1502        mVspKdTree->CollectViewCells(mViewCells);
1503}
[462]1504
[503]1505int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
[487]1506                                                                         const VssRayContainer &rays)
[440]1507{
[441]1508        // if view cells already constructed
[440]1509        if (ViewCellsConstructed())
1510                return 0;
[503]1511
[469]1512        VssRayContainer constructionRays;
1513        VssRayContainer savedRays;
[440]1514
[503]1515        GetRaySets(rays,
1516                           mConstructionSamples,
1517                           constructionRays,
[485]1518                           &savedRays);
[503]1519
1520        Debug << "constructing vsp kd tree using "
[469]1521                  << (int)constructionRays.size() << " samples" << endl;
[452]1522
[542]1523        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]1524        Debug << mVspKdTree->GetStatistics() << endl;
1525
[482]1526        // export leaf building blocks
1527        ExportLeaves(objects, rays);
[480]1528
[469]1529        // finally merge kd leaf building blocks to view cells
[485]1530        const int merged = mVspKdTree->MergeViewCells(rays);
1531
1532        // collapse siblings belonging to the same view cell
[486]1533        mVspKdTree->RefineViewCells(rays);
[485]1534
[542]1535        // collapse siblings belonging to the same view cell
[503]1536        mVspKdTree->CollapseTree();
1537
[482]1538        // evaluale view cell stats
1539        ResetViewCells();
[469]1540
[482]1541        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1542
[485]1543        long startTime = GetTime();
[469]1544        // recast rest of rays
1545        ComputeSampleContributions(savedRays);
[503]1546
1547        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]1548                  << " secs" << endl;
[469]1549
1550        return merged;
[440]1551}
1552
1553bool VspKdViewCellsManager::ViewCellsConstructed() const
1554{
1555        return mVspKdTree->GetRoot() != NULL;
1556}
1557
[441]1558
[462]1559ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1560{
1561        return new VspKdViewCell(mesh);
1562}
1563
[503]1564int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1565                                                                           const VssRayContainer &rays)
[440]1566{
[441]1567        if (!ViewCellsConstructed())
1568                return 0;
1569
[482]1570        // recalculate stats
1571        EvaluateViewCellsStats();
1572
[469]1573        return 0;
[440]1574}
1575
[482]1576
1577void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
1578                                                                                 const VssRayContainer &sampleRays)
[440]1579{
[441]1580        if (!ViewCellsConstructed())
1581                return;
1582
[482]1583        //-- export leaf building blocks
[503]1584        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]1585        if (!exporter)
1586                return;
1587
1588        //exporter->SetWireframe();
1589        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1590        exporter->ExportVspKdTree(*mVspKdTree);
1591
[503]1592        if (mExportGeometry)
[482]1593                exporter->ExportGeometry(objects);
1594
[503]1595        if (mExportRays)
[440]1596        {
[503]1597                const float prob = (float)mVisualizationSamples
[482]1598                        / ((float)sampleRays.size() + Limits::Small);
[440]1599
[482]1600                exporter->SetWireframe();
[440]1601
[482]1602                //-- collect uniformly distributed rays
1603                VssRayContainer rays;
[440]1604
[482]1605                for (int i = 0; i < sampleRays.size(); ++ i)
1606                {
1607                        if (RandomValue(0,1) < prob)
1608                                rays.push_back(sampleRays[i]);
[440]1609                }
[482]1610                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]1611        }
1612
[482]1613        delete exporter;
1614}
1615
1616void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1617                                                                          const VssRayContainer &sampleRays)
1618{
1619        if (!ViewCellsConstructed())
1620                return;
[503]1621
[482]1622        //-- export single view cells
1623        for (int i = 0; i < 10; ++ i)
[440]1624        {
[482]1625                char s[64];
1626                sprintf(s, "vsp_viewcell%04d.x3d", i);
1627                Exporter *exporter = Exporter::GetExporter(s);
[503]1628                const int idx =
[482]1629                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]1630
[503]1631                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]1632
[483]1633                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
1634                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
[482]1635                //-- export geometry
1636                Material m;
1637                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]1638
[482]1639                exporter->SetForcedMaterial(m);
1640                exporter->SetWireframe();
1641
[485]1642                ExportVcGeometry(exporter, vc);
[482]1643
1644                //-- export stored rays
[485]1645                if (mExportRays)
[440]1646                {
[503]1647                        vector<VspKdLeaf *>::const_iterator it,
[482]1648                                it_end = vc->mLeaves.end();
[440]1649
[482]1650                        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
1651                        {
1652                                VspKdLeaf *leaf = *it;
1653                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]1654
[482]1655                                VssRayContainer vssRays;
[483]1656
1657                                VssRayContainer castRays;
1658                                VssRayContainer initRays;
1659
[482]1660                                leaf->GetRays(vssRays);
[440]1661
[482]1662                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]1663                                const float prop = 200.0f / (float)vssRays.size();
[440]1664
[482]1665                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]1666                                {
[485]1667                                        if (Random(1) < prop)
[483]1668                                                if ((*it)->mTerminationObject == NULL)
1669                                                        castRays.push_back(*it);
[503]1670                                                else
[483]1671                                                        initRays.push_back(*it);
1672                                }
1673
1674                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
1675                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]1676                        }
1677                }
[440]1678
[482]1679                //-- output PVS of view cell
1680                m.mDiffuseColor = RgbColor(1, 0, 0);
1681                exporter->SetForcedMaterial(m);
[440]1682
[483]1683                Intersectable::NewMail();
1684
[482]1685                ObjectPvsMap::const_iterator it,
1686                        it_end = vc->GetPvs().mEntries.end();
1687
1688                exporter->SetFilled();
1689
[503]1690                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]1691                {
1692                        Intersectable *intersect = (*it).first;
1693
1694                        if (!intersect->Mailed())
1695                        {
1696                                Material m = RandomMaterial();
1697                                exporter->SetForcedMaterial(m);
1698
1699                                exporter->ExportIntersectable(intersect);
1700                                intersect->Mail();
[503]1701                        }
[482]1702                }
1703
1704                delete exporter;
[440]1705        }
[462]1706
1707        //-- export final view cells
[503]1708        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
1709
[485]1710        //if (exportGeometry) exporter->SetWireframe();
1711        //else exporter->SetFilled();
[483]1712
[508]1713        ExportViewCellsForViz(exporter);
[462]1714
[503]1715        if (mExportGeometry)
[465]1716        {
1717                exporter->SetFilled();
[462]1718                exporter->ExportGeometry(objects);
[465]1719        }
[469]1720
[503]1721        if (mExportRays)
[462]1722        {
[503]1723                const float prob = (float)mVisualizationSamples
[482]1724                        / ((float)sampleRays.size() + Limits::Small);
[503]1725
[462]1726                exporter->SetWireframe();
[503]1727
[466]1728                VssRayContainer rays;
[503]1729
[462]1730                for (int i = 0; i < sampleRays.size(); ++ i)
1731                {
[466]1732                  if (RandomValue(0,1) < prob)
1733                        rays.push_back(sampleRays[i]);
[462]1734                }
[503]1735                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]1736        }
1737
1738        delete exporter;
[440]1739}
1740
1741int VspKdViewCellsManager::GetType() const
1742{
1743        return VSP_KD;
1744}
[442]1745
[462]1746
[469]1747int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1748                                                                                   const Vector3 &termination,
1749                                                                                   ViewCellContainer &viewcells)
[466]1750{
[469]1751        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]1752}
1753
[477]1754
[482]1755void VspKdViewCellsManager::ExportColor(Exporter *exporter,
1756                                                                                ViewCell *vc) const
1757{
1758        if (mColorCode == 0) // Random color
1759                return;
[503]1760
[482]1761        float importance = 0;
[477]1762
[482]1763        switch (mColorCode)
1764        {
1765        case 1: // pvs
1766                {
[503]1767                        importance = (float)vc->GetPvs().GetSize() /
[482]1768                                (float)mViewCellsStats.maxPvs;
1769                }
1770                break;
1771        case 2: // merges
1772                {
1773            VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(vc);
1774
[503]1775                        importance = (float)vspKdVc->mLeaves.size() /
[482]1776                                (float)mViewCellsStats.maxLeaves;
1777                }
1778                break;
[485]1779        case 3: // merged tree depth difference
[482]1780                {
[503]1781                        //importance = (float)GetMaxTreeDiff(vc) /
[482]1782                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
1783                }
1784                break;
1785        default:
1786                break;
1787        }
1788
1789        Material m;
1790        m.mDiffuseColor.b = 1.0f;
1791        m.mDiffuseColor.r = importance;
1792        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1793        //Debug << "importance: " << importance << endl;
1794        exporter->SetForcedMaterial(m);
1795}
1796
1797
[503]1798void VspKdViewCellsManager::ExportVcGeometry(Exporter *exporter,
[482]1799                                                                                   ViewCell *vc) const
1800{
1801        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
1802        vector<VspKdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1803
[486]1804        Mesh m;
[482]1805        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
[486]1806        {
1807                mVspKdTree->GetBBox(*it).AddBoxToMesh(&m);
1808        }
1809
1810        exporter->ExportMesh(&m);
[482]1811}
1812
1813
[503]1814void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
1815{
[551]1816        //TODO
[503]1817}
[442]1818
[503]1819/**************************************************************************/
1820/*                   VspBspViewCellsManager implementation                */
1821/**************************************************************************/
[482]1822
[503]1823
1824VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
[442]1825                                                                                           int constructionSamples):
[503]1826ViewCellsManager(constructionSamples),
[442]1827mVspBspTree(vspBspTree)
1828{
[478]1829        mVspBspTree->SetViewCellsManager(this);
[442]1830}
1831
[477]1832
[475]1833VspBspViewCellsManager::~VspBspViewCellsManager()
1834{
1835}
1836
[477]1837
[471]1838float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1839{
[551]1840        if (0 && mVspBspTree->mUseAreaForPvs)
[547]1841                return GetArea(viewCell) / GetAccVcArea();
1842        else
1843                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]1844}
1845
[477]1846
[480]1847void VspBspViewCellsManager::CollectViewCells()
1848{
[547]1849        mVspBspTree->CollectViewCells(mViewCells, false);
[480]1850}
1851
1852
[503]1853float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
[477]1854                                                                                        float objRendercost) const
[468]1855{
1856        return viewCell->GetPvs().GetSize() * objRendercost;
1857}
1858
[462]1859
[442]1860bool VspBspViewCellsManager::ViewCellsConstructed() const
1861{
1862        return mVspBspTree->GetRoot() != NULL;
1863}
1864
[462]1865
[442]1866ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1867{
1868        return new BspViewCell(mesh);
1869}
1870
[503]1871int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
[487]1872                                                                          const VssRayContainer &rays)
[442]1873{
[503]1874        // if view cells were already constructed
1875        if (ViewCellsConstructed())
1876                return 0;
[442]1877
[503]1878        Debug << "Constructing bsp view cells" << endl;
1879
1880        int sampleContributions = 0;
1881
1882        VssRayContainer sampleRays;
1883
1884        int limit = min (mConstructionSamples, (int)rays.size());
1885
[469]1886        VssRayContainer constructionRays;
1887        VssRayContainer savedRays;
[442]1888
[557]1889        Debug << "construction samples: " << mConstructionSamples << " rays: " << (int)rays.size() << endl;
[485]1890        GetRaySets(rays, mConstructionSamples, constructionRays, &savedRays);
[487]1891
[508]1892        Debug << "construction rays: " << (int)constructionRays.size() << endl;
1893        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]1894
[547]1895        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
1896       
[542]1897        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[503]1898
[480]1899        Debug << mVspBspTree->GetStatistics() << endl;
[491]1900
[490]1901        // collapse invalid regions
[491]1902        cout << "collapsing invalid tree regions ... ";
[495]1903        long startTime = GetTime();
[503]1904        int collapsedLeaves = mVspBspTree->CollapseTree();
[501]1905        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3 << " seconds" << endl;
[495]1906    cout << "finished" << endl;
[503]1907
[491]1908        cout << "reseting view cell stats ... ";
[480]1909        ResetViewCells();
[491]1910        cout << "finished" << endl;
[503]1911
[480]1912        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[491]1913
1914        if (1) // export initial view cells
1915        {
1916                cout << "exporting initial view cells (=leaves) ... ";
1917                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]1918
[491]1919                if (exporter)
1920                {
1921                        //exporter->SetWireframe();
1922                        exporter->SetFilled();
[508]1923                        ExportViewCellsForViz(exporter);
[491]1924
[495]1925                        if (0 && mExportRays)
1926                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
[503]1927
[491]1928                        if (mExportGeometry)
1929                                exporter->ExportGeometry(objects);
[503]1930
[491]1931                        delete exporter;
1932                }
1933                cout << "finished" << endl;
1934        }
1935
[495]1936        startTime = GetTime();
[503]1937
1938        // reset view cells and stats
1939        ResetViewCells();
1940
[491]1941        cout << "Computing remaining ray contributions ... ";
[469]1942        // recast rest of rays
1943        ComputeSampleContributions(savedRays);
[491]1944        cout << "finished" << endl;
1945
[503]1946        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]1947                  << " secs" << endl;
[442]1948
[485]1949        cout << "construction finished" << endl;
[503]1950
[442]1951        return sampleContributions;
1952}
1953
[489]1954
[503]1955void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
1956                                                                                        const ObjectContainer &objects)
[475]1957{
[442]1958        //-- post processing of bsp view cells
1959    int vcSize = 0;
1960        int pvsSize = 0;
1961
[480]1962        mRenderer->RenderScene();
1963        SimulationStatistics ss;
1964        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1965    Debug << ss << endl;
1966
[442]1967        //-- merge or subdivide view cells
1968        int merged = 0;
[503]1969
[561]1970        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
[485]1971        long startTime = GetTime();
[442]1972
[503]1973        // TODO: should be done BEFORE the ray casting
[547]1974        merged = mVspBspTree->MergeViewCells(rays, objects);
[442]1975
[485]1976        //-- stats and visualizations
[561]1977        cout << "finished merging" << endl;
[485]1978        cout << "merged " << merged << " view cells in "
1979                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1980
1981        Debug << "Postprocessing: Merged " << merged << " view cells in "
1982                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]1983
[491]1984        cout << "reseting view cell stats ... ";
[485]1985        ResetViewCells();
[491]1986        cout << "finished" << endl;
1987
[485]1988        //BspLeaf::NewMail();
1989        if (1) // export merged view cells
[483]1990        {
[485]1991                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1992                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
[483]1993
[485]1994                cout << "exporting view cells after merge ... ";
1995
1996                if (exporter)
[483]1997                {
[551]1998                        if (1)
1999                                exporter->SetWireframe();
2000                        else
2001                                exporter->SetFilled();
[508]2002                        ExportViewCellsForViz(exporter);
[442]2003
[485]2004                        if (mExportGeometry)
[483]2005                        {
[485]2006                                Material m;
2007                                m.mDiffuseColor = RgbColor(0, 1, 0);
2008                                exporter->SetForcedMaterial(m);
2009                                exporter->SetFilled();
[442]2010
[485]2011                                exporter->ExportGeometry(objects);
[442]2012                        }
[485]2013
2014                        delete exporter;
[442]2015                }
[485]2016                cout << "finished" << endl;
[442]2017        }
[503]2018}
[475]2019
[503]2020
2021void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays)
2022{
[485]2023        Debug << "render time before refine:" << endl;
2024        mRenderer->RenderScene();
[503]2025        SimulationStatistics ss;
[485]2026        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2027    Debug << ss << endl;
2028
[489]2029        cout << "Refining the merged view cells ... ";
[503]2030        long startTime = GetTime();
[485]2031
2032        // refining the merged view cells
2033        const int refined = mVspBspTree->RefineViewCells(rays);
2034
[442]2035        //-- stats and visualizations
2036        cout << "finished" << endl;
[485]2037        cout << "refined " << refined << " view cells in "
[442]2038                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2039
[485]2040        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]2041                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]2042}
[495]2043
[517]2044
[503]2045int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2046                                                                                const VssRayContainer &rays)
2047{
2048        if (!ViewCellsConstructed())
2049        {
[517]2050                Debug << "postprocess error: no view cells constructed" << endl;
[503]2051                return 0;
2052        }
[520]2053
[542]2054       
2055        // view cells already finished before post processing step (i.e. because they were loaded)
[520]2056        if (mViewCellsFinished)
[542]2057        {
[551]2058                FinalizeViewCells(true);
[542]2059                EvaluateViewCellsStats();
[517]2060                return 0;
[542]2061        }
2062       
[448]2063
[542]2064        // check if new view cells turned invalid
[544]2065        mVspBspTree->ValidateTree();
[542]2066        ResetViewCells();
2067
2068
[517]2069        VssRayContainer postProcessRays;
2070        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2071
2072        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[520]2073       
[517]2074        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2075
[552]2076        // should maybe be done here to allow merge working with area or volume
2077        // and to correct the rendering statistics
[554]2078        if (0)
[551]2079        {
2080                FinalizeViewCells(false);
2081        }
2082
2083        //-- merge the individual view cells
[517]2084        MergeViewCells(postProcessRays, objects);
2085        //-- refines the merged view cells
2086        RefineViewCells(postProcessRays);
2087        // collapse sibling leaves that share the same view cell
2088        mVspBspTree->CollapseTree();
2089
[520]2090        ResetViewCells();
2091
[508]2092        // real meshes are only contructed only at this stage
[551]2093        FinalizeViewCells(true);
[517]2094
[508]2095        // write view cells to disc
2096        if (mExportViewCells)
2097        {
[517]2098                char buff[100];
2099                environment->GetStringValue("ViewCells.filename", buff);
2100                string vcFilename(buff);
2101
2102                ExportViewCells(buff);
[508]2103        }
[503]2104
2105        return 0;
[442]2106}
2107
[490]2108
[442]2109int VspBspViewCellsManager::GetType() const
2110{
2111        return VSP_BSP;
2112}
2113
2114
[490]2115bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2116{
2117        if (!ViewCellsConstructed())
2118                return ViewCellsManager::GetViewPoint(viewPoint);
2119
2120        // TODO: set reasonable limit
2121        const int limit = 20;
2122
2123        for (int i = 0; i < limit; ++ i)
2124        {
[542]2125                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]2126                if (mVspBspTree->ViewPointValid(viewPoint))
2127                {
2128                        return true;
2129                }
2130        }
2131        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2132        return false;
2133}
2134
2135
2136bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2137{
[542]2138        return mViewSpaceBox.IsInside(viewPoint) &&
[490]2139                   mVspBspTree->ViewPointValid(viewPoint);
2140}
2141
2142
[442]2143void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2144                                                                           const VssRayContainer &sampleRays)
[442]2145{
2146        if (!ViewCellsConstructed())
2147                return;
2148
[485]2149        VssRayContainer visRays;
2150        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]2151
[442]2152        if (1) // export view cells
2153        {
[478]2154                cout << "exporting view cells after post process ... ";
[485]2155                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[442]2156
2157                if (exporter)
2158                {
[542]2159                        if (1)
2160                        {
2161                                exporter->SetWireframe();
2162                                exporter->ExportBox(mViewSpaceBox);
2163                                exporter->SetFilled();
2164                        }
2165
[485]2166                        if (mExportGeometry)
[542]2167                        {
[485]2168                                exporter->ExportGeometry(objects);
[542]2169                        }
[489]2170
2171                        // export rays
[490]2172                        if (mExportRays)
[489]2173                        {
[490]2174                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2175                        }
[557]2176                       
[508]2177                        ExportViewCellsForViz(exporter);
[442]2178                        delete exporter;
2179                }
[557]2180        }
[503]2181
[557]2182        // export shuffled view cells
2183        if (1)
2184        {
2185                cout << "exporting shuffled view cells ...";
2186
2187                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2188                if (exporter)
2189                {
2190                        if (1)
2191                        {
2192                                exporter->SetWireframe();
2193                                exporter->ExportBox(mViewSpaceBox);
2194                                exporter->SetFilled();
2195                        }
2196
2197                        if (mExportGeometry)
2198                        {
2199                                exporter->ExportGeometry(objects);
2200                        }
2201
2202                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2203
2204                        Material vm, lm;
2205
2206                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2207                        {
2208                                BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
2209
2210                                vm = RandomMaterial();
2211
2212                                lm = vm;
2213                                       
[558]2214                                vm.mDiffuseColor.r -= 0.45f;
2215                                vm.mDiffuseColor.g -= 0.45f;
2216                                vm.mDiffuseColor.b -= 0.45f;
[557]2217
2218                                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
2219
2220                                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2221                                {
2222                                        BspLeaf *leaf = *lit;
2223
2224                                        if (leaf->Mailed())
2225                                                exporter->SetForcedMaterial(lm);
2226                                        else
2227                                                exporter->SetForcedMaterial(vm);
2228                                       
2229                                        BspNodeGeometry geom;
2230                                        mVspBspTree->ConstructGeometry(leaf, geom);
2231                                        exporter->ExportPolygons(geom.mPolys);
2232                                }
2233                        }
2234                       
2235                        delete exporter;
2236                }
2237
2238
[442]2239                cout << "finished" << endl;
[503]2240        }
[442]2241
2242        //-- visualization of the BSP splits
2243        bool exportSplits = false;
[489]2244        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]2245
[442]2246        if (exportSplits)
2247        {
2248                cout << "exporting splits ... ";
[485]2249                ExportSplits(objects, visRays);
[442]2250                cout << "finished" << endl;
2251        }
2252
[542]2253        //-- export single view cells
[485]2254        ExportBspPvs(objects, visRays);
[442]2255}
2256
[503]2257
[485]2258void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2259                                                                                  const VssRayContainer &rays)
[442]2260{
2261        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2262
[503]2263        if (exporter)
2264        {
2265                Material m;
[442]2266                m.mDiffuseColor = RgbColor(1, 0, 0);
2267                exporter->SetForcedMaterial(m);
2268                exporter->SetWireframe();
[503]2269
[448]2270                exporter->ExportBspSplits(*mVspBspTree, true);
[442]2271
2272                // take forced material, else big scenes cannot be viewed
2273                m.mDiffuseColor = RgbColor(0, 1, 0);
2274                exporter->SetForcedMaterial(m);
2275                exporter->SetFilled();
2276
2277                exporter->ResetForcedMaterial();
[503]2278
[442]2279                // export rays
[485]2280                if (mExportRays)
2281                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]2282
[485]2283                if (mExportGeometry)
[442]2284                        exporter->ExportGeometry(objects);
2285
2286                delete exporter;
2287        }
2288}
2289
[503]2290
[485]2291void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2292                                                                                  const VssRayContainer &rays)
[442]2293{
2294        const int leafOut = 10;
[503]2295
[442]2296        ViewCell::NewMail();
[503]2297
[442]2298        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
[475]2299        Debug << "\nOutput view cells: " << endl;
[503]2300
[485]2301        // sort view cells to visualize the largest view cells
[478]2302#if 0
2303        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2304#endif
[503]2305        int limit = min(leafOut, (int)mViewCells.size());
[483]2306
[485]2307#if 1
2308        //-- some rays for output
2309        vector<BspRay *> bspRays;
2310        mVspBspTree->ConstructBspRays(bspRays, rays);
2311
2312        const int raysOut = min((int)bspRays.size(), mVisualizationSamples);
2313#endif
2314
[478]2315        for (int i = 0; i < limit; ++ i)
[442]2316        {
[478]2317                cout << "creating output for view cell " << i << " ... ";
[503]2318
[478]2319                VssRayContainer vcRays;
[485]2320                Intersectable::NewMail();
[542]2321#if 0 // largest view cell pvs first
[478]2322                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
2323#else
[485]2324                BspViewCell *vc = dynamic_cast<BspViewCell *>
2325                        (mViewCells[Random((int)mViewCells.size())]);
[478]2326#endif
[442]2327
[483]2328#if 1
[478]2329                // check whether we can add the current ray to the output rays
[503]2330                for (int k = 0; k < raysOut; ++ k)
[442]2331                {
[485]2332                        BspRay *ray = bspRays[k];
[478]2333                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[442]2334                        {
[478]2335                                BspLeaf *leaf = ray->intersections[j].mLeaf;
[503]2336                                if (vc == leaf->GetViewCell())
[478]2337                                        vcRays.push_back(ray->vssRay);
[442]2338                        }
2339                }
[478]2340#endif
2341                //bspLeaves[j]->Mail();
2342                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2343                Exporter *exporter = Exporter::GetExporter(s);
2344                exporter->SetWireframe();
[442]2345
[478]2346                Material m;//= RandomMaterial();
2347                m.mDiffuseColor = RgbColor(0, 1, 0);
2348                exporter->SetForcedMaterial(m);
[442]2349
[503]2350                ExportVcGeometry(exporter, vc);
2351
2352
2353                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[485]2354                          << ", piercing rays=" << (int)vcRays.size()
2355                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
[503]2356
[485]2357                //-- export rays piercing this view cell
[483]2358#if 1
[495]2359                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[483]2360#endif
[478]2361#if 0
2362                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
[483]2363
[478]2364                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2365                        exporter->ExportRays((*lit)->mVssRays);
2366#endif
2367                m.mDiffuseColor = RgbColor(1, 0, 0);
2368                exporter->SetForcedMaterial(m);
[442]2369
[478]2370                ObjectPvsMap::const_iterator it,
2371                        it_end = vc->GetPvs().mEntries.end();
[442]2372
[478]2373                exporter->SetFilled();
[442]2374
[478]2375                // output PVS of view cell
[503]2376                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]2377                {
2378                        Intersectable *intersect = (*it).first;
[442]2379
[478]2380                        if (!intersect->Mailed())
2381                        {
2382                                Material m = RandomMaterial();
2383                                exporter->SetForcedMaterial(m);
2384
2385                                exporter->ExportIntersectable(intersect);
2386                                intersect->Mail();
[503]2387                        }
[442]2388                }
[503]2389
[478]2390                DEL_PTR(exporter);
2391                cout << "finished" << endl;
[442]2392        }
[475]2393
[485]2394#if 1
2395        CLEAR_CONTAINER(bspRays);
2396#endif
[475]2397        Debug << endl;
[442]2398}
2399
2400
[469]2401int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2402                                                                                        const Vector3 &termination,
2403                                                                                        ViewCellContainer &viewcells)
[466]2404{
[469]2405        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]2406}
[482]2407
2408
[503]2409void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]2410                                                                                 ViewCell *vc) const
2411{
[562]2412        if (CheckValidity(vc, mMinPvsSize, mMaxPvsSize) && (mColorCode == 0)) // Random color
[482]2413                return;
[503]2414
[482]2415        float importance = 0;
[547]2416        Material m;
2417       
[482]2418        switch (mColorCode)
2419        {
2420        case 1: // pvs
2421                {
[503]2422                        importance = (float)vc->GetPvs().GetSize() /
[482]2423                                (float)mViewCellsStats.maxPvs;
2424                }
2425                break;
2426        case 2: // merges
2427                {
2428            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2429
[503]2430                        importance = (float)bspVc->mLeaves.size() /
[482]2431                                (float)mViewCellsStats.maxLeaves;
2432                }
2433                break;
2434        case 3: // merge tree differene
2435                {
[503]2436                        importance = (float)GetMaxTreeDiff(vc) /
[482]2437                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]2438
[482]2439                }
2440                break;
2441        default:
2442                break;
2443        }
2444
[562]2445        m.mDiffuseColor.b = CheckValidity(vc, mMinPvsSize, mMaxPvsSize) ? 1.0f : 0.0f;
[482]2446        m.mDiffuseColor.r = importance;
2447        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[547]2448
[482]2449        //Debug << "importance: " << importance << endl;
2450        exporter->SetForcedMaterial(m);
2451}
2452
2453
[503]2454void VspBspViewCellsManager::ExportVcGeometry(Exporter *exporter,
[485]2455                                                                                          ViewCell *vc) const
[482]2456{
[542]2457        if (vc->GetMesh())
[503]2458        {
2459                exporter->ExportMesh(vc->GetMesh());
2460                return;
2461        }
2462
[485]2463        BspNodeGeometry geom;
2464        mVspBspTree->
[503]2465                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom);
[485]2466        exporter->ExportPolygons(geom.mPolys);
[482]2467}
2468
2469
2470int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
2471{
2472        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2473
2474        int maxDist = 0;
2475        // compute max height difference
2476        for (int i = 0; i < (int)bspVc->mLeaves.size(); ++ i)
2477                for (int j = 0; j < (int)bspVc->mLeaves.size(); ++ j)
2478        {
2479                BspLeaf *leaf = bspVc->mLeaves[i];
2480
2481                if (i != j)
2482                {
2483                        BspLeaf *leaf2 = bspVc->mLeaves[j];
2484                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
2485                        if (dist > maxDist)
2486                                maxDist = dist;
2487                }
2488        }
[492]2489        return maxDist;
2490}
[482]2491
[492]2492
[503]2493ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point)
[492]2494{
[508]2495        if (!mVspBspTree)
2496                return NULL;
2497        return mVspBspTree->GetViewCell(point);
[492]2498}
[503]2499
2500
2501void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
2502{
2503        BspNodeGeometry geom;
2504        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2505        mVspBspTree->ConstructGeometry(bspVc, geom);
2506
2507        Mesh *mesh = new Mesh();
2508        geom.AddToMesh(*mesh);
2509        vc->SetMesh(mesh);
2510        mMeshContainer.push_back(mesh);
2511}
[508]2512
2513
2514bool VspBspViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
2515{
2516        ViewCellsParser parser;
2517       
2518        DEL_PTR(mVspBspTree);
2519        mVspBspTree = new VspBspTree();
2520       
2521        bool success = parser.ParseFile(filename, mVspBspTree, this, objects);
[520]2522        mVspBspTree->RepairViewCellsLeafLists();
2523        mVspBspTree->mBox = GetViewSpaceBox();
[508]2524        ResetViewCells();
[555]2525       
2526        mViewCellsFinished = true;
[562]2527        mMaxPvsSize = (int)objects->size();
[517]2528
[555]2529        FinalizeViewCells(true);
[562]2530       
[508]2531        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
2532
2533        return success;
2534}
2535
2536
2537inline bool ilt(Intersectable *obj1, Intersectable *obj2)
2538{
2539        return obj1->mId < obj2->mId;
2540}
2541
2542
2543bool VspBspViewCellsManager::ExportViewCells(const string filename)
2544{
2545        cout << "exporting view cells to xml ... ";
2546        std::ofstream stream;
2547
2548        // for output we need unique ids
2549        CreateUniqueViewCellIds();
2550
2551        stream.open(filename.c_str());
2552        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2553        stream << "<Visibility_Solution>" << endl;
2554       
2555        //-- load the view cells itself, i.e., the ids and the pvs
2556        stream << "<ViewCells>" << endl;
2557        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2558        for (it = mViewCells.begin(); it != it_end; ++ it)
2559                ExportViewCell(*it, stream);
2560   
2561        stream << "</ViewCells>" << endl;
2562       
2563        //-- load the hierarchy
2564        stream << "<BspTree>" << endl;
2565        mVspBspTree->Export(stream);
2566        stream << endl << "</BspTree>" << endl;
2567       
2568        stream << "</Visibility_Solution>" << endl;
2569        stream.close();
2570
2571        cout << "finished" << endl;
2572
2573        return true;
[532]2574}
2575
2576
2577int VspBspViewCellsManager::CastBeam(Beam &beam)
2578{
[535]2579        return mVspBspTree->CastBeam(beam);
[532]2580}
[551]2581
2582
[555]2583void VspBspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
[551]2584{
2585        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCell);
2586        CreateMesh(vc);
2587
2588        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
2589
2590        float area = 0;
2591        float volume = 0;
2592
2593        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
2594        {
2595                BspNodeGeometry geom;
2596                BspLeaf *leaf = *it;
2597                mVspBspTree->ConstructGeometry(leaf, geom);
2598
2599                area += geom.GetArea();
2600                volume += geom.GetVolume();
2601        }
2602
2603        viewCell->SetVolume(volume);
2604        viewCell->SetArea(area);
[563]2605}
Note: See TracBrowser for help on using the repository browser.