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

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