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

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