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

Revision 591, 77.9 KB checked in by mattausch, 18 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"
[540]15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
[440]17
[517]18
[532]19
[440]20ViewCellsManager::ViewCellsManager():
[480]21mRenderer(NULL),
[574]22mInitialSamples(0),
[440]23mConstructionSamples(0),
24mPostProcessSamples(0),
[470]25mVisualizationSamples(0),
26mTotalAreaValid(false),
[517]27mTotalArea(0.0f),
[547]28mViewCellsFinished(false),
[562]29mMaxPvsSize(9999999),
[564]30mMinPvsSize(0), // one means only empty view cells are invalid
[561]31mMaxPvsRatio(1.0)
[440]32{
[542]33        mViewSpaceBox.Initialize();
[482]34        ParseEnvironment();
[580]35
36        mViewCellsTree = new ViewCellsTree(this);
[440]37}
38
[517]39
[482]40void ViewCellsManager::ParseEnvironment()
41{
[503]42        // visualization stuff
[485]43        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
44        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
[547]45        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[564]46        bool emptyViewCells = false;
47        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", emptyViewCells);
48        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]49
[574]50        environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
51        environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
52        environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
53
54        environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
[577]55        environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
[591]56        environment->GetBoolValue("ViewCells.PostProcess.e", mUseMerge);
[581]57       
[582]58        environment->GetIntValue("ViewCells.active", mNumMergedViewCells);
[586]59        environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
[591]60        environment->GetBoolValue("ViewCells.Visualization.useCuttingPlane", mUseCuttingPlaneForViz);
[580]61
[591]62        environment->GetBoolValue("ViewCells.Visualization.", mUseCuttingPlaneForViz);
63
64        environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
65
[564]66        mMinPvsSize = emptyViewCells ? 1 : 0;
67
[482]68        char buf[50];
69        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
[503]70
[482]71        if (strcmp(buf, "PVS") == 0)
72                mColorCode = 1;
73        else if (strcmp(buf, "MergedLeaves") == 0)
74                mColorCode = 2;
75        else if (strcmp(buf, "MergedTreeDiff") == 0)
76                mColorCode = 3;
77        else
78                mColorCode = 0;
79
80        Debug << "colorCode: " << mColorCode << endl;
[440]81}
82
[485]83
[440]84ViewCellsManager::~ViewCellsManager()
85{
[480]86        DEL_PTR(mRenderer);
[580]87        //CLEAR_CONTAINER(mViewCells);
88        DEL_PTR(mViewCellsTree);
89
[503]90        CLEAR_CONTAINER(mMeshContainer);
[440]91}
92
[485]93
[574]94int ViewCellsManager::CastPassSamples(const int samplesPerPass,
95                                                                          const int sampleType,
96                                                                          VssRayContainer &passSamples) const
[527]97{
[570]98        SimpleRayContainer simpleRays;
[540]99
[573]100        preprocessor->GenerateRays(samplesPerPass,
101                                                           sampleType,
[570]102                                                           simpleRays);
[564]103
[573]104        // shoot simple ray and add it to importance samples
105        preprocessor->CastRays(simpleRays, passSamples);
[570]106
[574]107        return (int)passSamples.size();
108}
[570]109
[574]110
111/// helper function which destroys rays or copies them into the output ray container
112inline void addOutRays(VssRayContainer &rays, VssRayContainer *outRays)
113{
114        cout << "disposing samples ... ";
[582]115        long startTime = GetTime();
116        int n = (int)rays.size();
117
[573]118        if (outRays)
[542]119        {
[574]120                VssRayContainer::const_iterator it, it_end = rays.end();
121
122                for (it = rays.begin(); it != it_end; ++ it)
123                {
124                        outRays->push_back(*it);
125                }
[573]126        }
127        else
128        {
[574]129                CLEAR_CONTAINER(rays);
[573]130        }
[574]131        cout << "finished" << endl;
[582]132        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[573]133}
[570]134
135
[573]136int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
137{
138        int numSamples = 0;
139        SimpleRayContainer simpleRays;
140       
[574]141        VssRayContainer initialSamples;
[540]142
[574]143        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
[573]144        //-- construction rays => we use uniform samples for this
[574]145        CastPassSamples(mInitialSamples,
[575]146                                        //Preprocessor::DIRECTION_BASED_DISTRIBUTION,
147                                        Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION,
[574]148                                        initialSamples);
[573]149       
[574]150        cout << "finished" << endl;
151
[573]152        // construct view cells
[574]153        const int numInitialSamples =
154                ConstructSubdivision(preprocessor->mObjects, initialSamples);
[540]155
[574]156        numSamples += numInitialSamples;
[542]157
[574]158        // rays can be passed or deleted
159        addOutRays(initialSamples, outRays);
160       
[570]161
[573]162        //-- guided rays are used for further sampling
[574]163        const int n = mConstructionSamples; //+initialSamples;
[570]164
[574]165        bool dirSamples = false;
[573]166
167        while (numSamples < n)
168        {
[574]169                cout << "casting " << mSamplesPerPass << " samples ... ";
170                VssRayContainer constructionSamples;
171
172                const int samplingType =
173                        dirSamples ?
174                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
175                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
176
[575]177                dirSamples = !dirSamples; // toggle sampling method
[574]178                numSamples += CastPassSamples(mSamplesPerPass,
179                                                                          samplingType,
180                                                                          constructionSamples);
181
182                cout << "finished" << endl;
183
184                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
185
186                // TODO: leak?
187                ComputeSampleContributions(constructionSamples, true, false);
188                cout << "finished" << endl;
189
190
191                addOutRays(constructionSamples, outRays);
192
193                cout << "total samples: " << numSamples << endl;
[542]194        }
[573]195       
[570]196
[573]197        //-- post processing
198        VssRayContainer postProcessSamples;
[570]199
[573]200        //-- construction rays => we use uniform samples for this
[574]201        CastPassSamples(mPostProcessSamples,
202                                    Preprocessor::DIRECTION_BASED_DISTRIBUTION,
203                                        postProcessSamples);
[573]204       
[574]205        cout << "starting post processing and visualization" << endl;
206
207        // store viewCells for postprocessing
208        const bool storeViewCells = true;
209        ComputeSampleContributions(postProcessSamples, true, storeViewCells);
[570]210        // merge the view cells
[573]211        PostProcess(preprocessor->mObjects, postProcessSamples);
[570]212
213
[574]214        //-- visualization
215        VssRayContainer visualizationSamples;
216
217        //-- construction rays => we use uniform samples for this
218        CastPassSamples(mVisualizationSamples,
219                                    Preprocessor::DIRECTION_BASED_DISTRIBUTION,
220                                        visualizationSamples);
221
222        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
223
224        //Debug << "visualizationsamples: " << mVisualizationSamples << " " << visualizationSamples.size() << endl;
225        // different visualizations
226        Visualize(preprocessor->mObjects, visualizationSamples);
227
228        addOutRays(visualizationSamples, outRays);
229
[573]230        return numSamples;
[527]231}
232
[547]233
[564]234bool ViewCellsManager::CheckValidity(ViewCell *vc,
235                                                                         int minPvsSize,
[562]236                                                                         int maxPvsSize) const
[547]237{
[569]238
239  if ((vc->GetPvs().GetSize() > maxPvsSize) ||
240          (vc->GetPvs().GetSize() < minPvsSize))
[564]241        {
[569]242          return false;
[561]243        }
[570]244
[569]245  return true;
[547]246}
247
248
[581]249bool ViewCellsManager::ViewCellsTreeConstructed() const
250{
251        return mViewCellsTree->GetRoot();
252}
253
254
[564]255void ViewCellsManager::SetValidity(ViewCell *vc,
256                                                                   int minPvs,
[562]257                                                                   int maxPvs) const
258{
259        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
260}
261
[577]262
[569]263void
264ViewCellsManager::SetValidity(
[570]265                                                          int minPvsSize,
[569]266                                                          int maxPvsSize) const
267{
268  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[570]269
[569]270  for (it = mViewCells.begin(); it != it_end; ++ it) {
271        SetValidity(*it, minPvsSize, maxPvsSize);
272  }
273}
[562]274
[569]275void
276ViewCellsManager::SetValidityPercentage(
277                                                                                const float minValid,
278                                                                                const float maxValid
279                                                                                )
280{
281  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[570]282
[569]283  int start = mViewCells.size()*minValid;
284  int end = mViewCells.size()*maxValid;
[570]285
[569]286  for (int i=0; i < mViewCells.size(); i++)
287        mViewCells[i]->SetValid(i >= start && i <= end);
288}
289
290int
291ViewCellsManager::CountValidViewcells() const
292{
293  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
294  int valid = 0;
295  for (it = mViewCells.begin(); it != it_end; ++ it) {
296        if ((*it)->GetValid())
297          valid++;
298  }
299  return valid;
300}
301
[577]302
303bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
[440]304{
305        X3dParser parser;
[503]306
[440]307        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]308
[440]309        bool success = parser.ParseFile(filename, *this);
310        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
311
312        return success;
313}
314
[485]315
[487]316bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
317{
[542]318        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]319
320        return true;
321}
322
323
[557]324float ViewCellsManager::GetViewSpaceVolume()
325{
[580]326        return mViewSpaceBox.GetVolume()*(2.0f*sqr((float)M_PI));
[557]327}
328
329
[490]330bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
331{
[569]332  if (!ViewCellsConstructed())
[542]333        return mViewSpaceBox.IsInside(viewPoint);
[569]334  else {
335        if (!mViewSpaceBox.IsInside(viewPoint))
336          return false;
337        ViewCell *viewcell = GetViewCell(viewPoint);
338        if (!viewcell || !viewcell->GetValid())
339          return false;
340  }
341  return true;
[490]342}
343
[501]344
[563]345float
346ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
[574]347                                                                                         const bool addRays,
348                                                                                         const bool storeViewCells
[563]349                                                                                         )
[440]350{
[563]351  // view cells not yet constructed
352  if (!ViewCellsConstructed())
353        return 0.0f;
[564]354
[563]355  VssRayContainer::const_iterator it, it_end = rays.end();
[503]356
[563]357  float sum = 0.0f;
358  for (it = rays.begin(); it != it_end; ++ it) {
[574]359        sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
[567]360        //ComputeSampleContributions(*(*it), addRays);
361        //      sum += (*it)->mPvsContribution;
[563]362  }
363  return sum;
[440]364}
365
[485]366
[479]367void ViewCellsManager::EvaluateViewCellsStats()
368{
369        mViewCellsStats.Reset();
370
371        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
372
373        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]374        {
[479]375                (*it)->UpdateViewCellsStats(mViewCellsStats);
[487]376        }
[479]377}
378
[485]379
[580]380void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
[579]381                                                                                                float &expectedRenderCost,
[580]382                                                                                                float &deviation,
383                                                                                                float &variance,
384                                                                                                int &totalPvs,
385                                                                                                float &avgRenderCost)
[579]386{
387        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
388
[580]389
[579]390        //-- compute expected value
391
392        totalRenderCost = 0;
[580]393        totalPvs = 0;
[579]394
395        for (it = mViewCells.begin(); it != it_end; ++ it)
396        {
397                ViewCell *vc = *it;
398                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
[580]399                totalPvs += (int)vc->GetPvs().GetSize();
[579]400        }
401
[580]402        // normalize with view space box
403        totalRenderCost /= mViewSpaceBox.GetVolume();
[579]404        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
[580]405        avgRenderCost = totalPvs / (float)mViewCells.size();
[579]406
407
[580]408        //-- compute standard defiation
[579]409        variance = 0;
[580]410        deviation = 0;
[579]411
412        for (it = mViewCells.begin(); it != it_end; ++ it)
413        {
414                ViewCell *vc = *it;
415
416                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
[580]417                float dev;
[579]418
[580]419                if (1)
420                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
421                else
422                        dev = fabs(expectedRenderCost - renderCost);
[579]423
[580]424                deviation += dev;
425                variance += dev * dev;
[579]426        }
[580]427
[579]428        variance /= (float)mViewCells.size();
[580]429        deviation /= (float)mViewCells.size();
[579]430}
431
432
433
[440]434void ViewCellsManager::AddViewCell(ViewCell *viewCell)
435{
436        mViewCells.push_back(viewCell);
437}
438
[485]439
[478]440float ViewCellsManager::GetArea(ViewCell *viewCell) const
441{
442        return viewCell->GetArea();
443}
444
445
446float ViewCellsManager::GetVolume(ViewCell *viewCell) const
447{
448        return viewCell->GetVolume();
449}
450
[485]451
[503]452void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
453                                                                           ViewCellContainer &viewCells,
[440]454                                                                           const int maxViewCells) const
455{
456        // maximal max viewcells
[503]457        int limit = maxViewCells > 0 ?
[440]458                Min((int)objects.size(), maxViewCells) : (int)objects.size();
459
460        for (int i = 0; i < limit; ++ i)
461        {
462                Intersectable *object = objects[i];
[503]463
[440]464                // extract the mesh instances
465                if (object->Type() == Intersectable::MESH_INSTANCE)
466                {
467                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
468
469                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
470                        viewCells.push_back(viewCell);
471                }
472                //TODO: transformed meshes
473        }
474}
475
[485]476
[503]477ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]478                                                                                        const float height) const
479{
480        // one mesh per view cell
481        Mesh *mesh = new Mesh();
[503]482
[440]483        //-- construct prism
484
[503]485        // bottom
[440]486        mesh->mFaces.push_back(new Face(2,1,0));
487        // top
488    mesh->mFaces.push_back(new Face(3,4,5));
489        // sides
490        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
491        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
492        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
493
494        //--- extrude new vertices for top of prism
495        Vector3 triNorm = baseTri.GetNormal();
496
[503]497        Triangle3 topTri;
[440]498
499        // add base vertices and calculate top vertices
500        for (int i = 0; i < 3; ++ i)
501                mesh->mVertices.push_back(baseTri.mVertices[i]);
[503]502
503        // add top vertices
[440]504        for (int i = 0; i < 3; ++ i)
505                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]506
[440]507        mesh->Preprocess();
508
509        return GenerateViewCell(mesh);
510}
511
[485]512
[551]513void ViewCellsManager::FinalizeViewCells(const bool createMesh)
514{
515        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
516        for (it = mViewCells.begin(); it != it_end; ++ it)
517        {
518                Finalize(*it, createMesh);
519        }
[555]520
521        mTotalAreaValid = false;
[551]522}
523
524
525void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
526{
527        // implemented in subclasses
528}
529
530
[582]531ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
[440]532{
[580]533        // generate parent view cell
534        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
[462]535
[440]536        // merge pvs
[582]537        vc->GetPvs().Merge(left->GetPvs(), right->GetPvs());
[440]538
[462]539        //-- merge ray sets
[564]540        if (0)
541        {
[582]542                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
543                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
[440]544
[582]545                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
546                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
[564]547                                   vc->mPiercingRays.begin());
548        }
[440]549
[580]550
[582]551        vc->SetupChildLink(left);
552        vc->SetupChildLink(right);
[580]553
554
[440]555        return vc;
556}
557
[485]558
[582]559ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
560{
561        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
562
563        ViewCellContainer::const_iterator it, it_end = children.end();
564
565        for (it = children.begin(); it != it_end; ++ it)
566        {
567                // merge pvs
568                vc->GetPvs().Merge(vc->GetPvs(), (*it)->GetPvs());
569
570                vc->SetupChildLink(*it);
571        }
572
573        return vc;
574}
575
576
[480]577void ViewCellsManager::SetRenderer(Renderer *renderer)
578{
579        mRenderer = renderer;
580}
[441]581
[485]582
[580]583ViewCellsTree *ViewCellsManager::GetViewCellsTree()
[440]584{
[580]585        return mViewCellsTree;
[440]586}
587
588
589void ViewCellsManager::SetVisualizationSamples(const int visSamples)
590{
[444]591        mVisualizationSamples = visSamples;
[440]592}
593
[485]594
[440]595void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
596{
597        mConstructionSamples = constructionSamples;
598}
599
[485]600
[574]601void ViewCellsManager::SetInitialSamples(const int initialSamples)
602{
603        mInitialSamples = initialSamples;
604}
605
606
[440]607void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
608{
609        mPostProcessSamples = postProcessSamples;
610}
611
[485]612
[440]613int ViewCellsManager::GetVisualizationSamples() const
614{
615        return mVisualizationSamples;
616}
617
[485]618
[440]619int ViewCellsManager::GetConstructionSamples() const
620{
621        return mConstructionSamples;
622}
623
[485]624
[440]625int ViewCellsManager::GetPostProcessSamples() const
626{
627        return mPostProcessSamples;
628}
629
[485]630
631void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]632{
633  ViewCellContainer::const_iterator it = mViewCells.begin();
634  stat.viewcells = 0;
635  stat.minPvs = 100000000;
636  stat.maxPvs = 0;
637  stat.avgPvs = 0.0f;
638
639  for (; it != mViewCells.end(); ++it) {
640        ViewCell *viewcell = *it;
641        int pvsSize = viewcell->GetPvs().GetSize();
642        if ( pvsSize < stat.minPvs)
643          stat.minPvs = pvsSize;
644        if (pvsSize > stat.maxPvs)
645          stat.maxPvs = pvsSize;
646        stat.avgPvs += pvsSize;
647        stat.viewcells++;
648  }
649  if (stat.viewcells)
650        stat.avgPvs/=stat.viewcells;
651}
652
[485]653
[480]654void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]655{
656  s<<"############# Viewcell PVS STAT ##################\n";
657  PvsStatistics pvsStat;
658  GetPvsStatistics(pvsStat);
659  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
660  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
661  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
662}
663
[485]664
[532]665int ViewCellsManager::CastBeam(Beam &beam)
666{
667        return 0;
668}
669
[547]670
[468]671ViewCellContainer &ViewCellsManager::GetViewCells()
672{
673        return mViewCells;
674}
675
[485]676
[487]677void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
678{
[542]679        mViewSpaceBox = box;
[591]680
681        CreateCuttingPlane();
682       
[577]683        mTotalAreaValid = false;
[487]684}
685
686
[591]687void ViewCellsManager::CreateCuttingPlane()
688{
689        int axis = 0;
690
691        Vector3 point = mViewSpaceBox.Center();
692
693        if (mUseCuttingPlaneForViz)
694        environment->GetIntValue("ViewCells.Visualization.cuttingPlaneAxis", axis);
695
696        Vector3 normal(0,0,0);
697        normal[axis] = 1;
698
699        mCuttingPlane = Plane3(normal, point);
700}
701
702
[519]703AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
704{
[542]705        return mViewSpaceBox;
[519]706}
707
708
[480]709void ViewCellsManager::ResetViewCells()
710{
711        mViewCells.clear();
[590]712       
[480]713        CollectViewCells();
[590]714       
[480]715        mViewCellsStats.Reset();
716        EvaluateViewCellsStats();
[590]717
[520]718        // has to be recomputed
[480]719        mTotalAreaValid = false;
720}
721
[485]722
[547]723int ViewCellsManager::GetMaxPvsSize() const
724{
725        return mMaxPvsSize;
726}
727
[590]728
[563]729void
730ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
731{
732  if (!ViewCellsConstructed())
733        return;
[564]734
[563]735  VssRayContainer::const_iterator it, it_end = rays.end();
[564]736
[563]737  for (it = rays.begin(); it != it_end; ++ it) {
738        AddSampleContributions(*(*it));
739  }
740}
[547]741
[581]742
[562]743int ViewCellsManager::GetMinPvsSize() const
744{
745        return mMinPvsSize;
746}
747
748
749
[561]750float ViewCellsManager::GetMaxPvsRatio() const
751{
752        return mMaxPvsRatio;
753}
754
755
[563]756void
757ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]758{
[563]759  // assumes viewcells have been stored...
760  ViewCellContainer *viewcells = &ray.mViewCells;
761  ViewCellContainer::const_iterator it;
762  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
763        ViewCell *viewcell = *it;
[569]764        if (viewcell->GetValid()) {
765          // if ray not outside of view space
766          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
767        }
[563]768  }
769}
[503]770
[574]771
[570]772float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
[574]773                                                                                                   const bool addRays,
774                                                                                                   const bool storeViewCells)
[563]775{
[570]776        ViewCellContainer viewcells;
[564]777
[570]778        ray.mPvsContribution = 0;
779        ray.mRelativePvsContribution = 0.0f;
[485]780
[570]781        static Ray hray;
[564]782        hray.Init(ray);
783        //hray.mFlags |= Ray::CULL_BACKFACES;
784        //Ray hray(ray);
785
786        float tmin = 0, tmax = 1.0;
787
788        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
[565]789                return 0;
[564]790
791        Vector3 origin = hray.Extrap(tmin);
792        Vector3 termination = hray.Extrap(tmax);
793
794        CastLineSegment(origin, termination, viewcells);
795        //Debug << "constribution: " << (int)viewcells.size() << endl;
796
[570]797        // copy viewcells memory efficiently
[574]798        //const bool storeViewcells = !addRays;
[564]799
[574]800        if (storeViewCells)
[570]801        {
802                ray.mViewCells.reserve(viewcells.size());
803                ray.mViewCells = viewcells;
804        }
[564]805
[570]806        ViewCellContainer::const_iterator it = viewcells.begin();
[564]807
808
[563]809  for (; it != viewcells.end(); ++it) {
810        ViewCell *viewcell = *it;
[569]811        if (viewcell->GetValid()) {
812          // if ray not outside of view space
813          float contribution;
814          if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
815                                                                                                   ray.mPdf,
816                                                                                                   contribution
817                                                                                                   ))
818                ray.mPvsContribution++;
819          ray.mRelativePvsContribution += contribution;
820        }
[563]821  }
[564]822
[563]823  if (addRays)
824        for (it = viewcells.begin(); it != viewcells.end(); ++it) {
825          ViewCell *viewcell = *it;
[569]826          if (viewcell->GetValid()) {
827                // if ray not outside of view space
828                viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
829          }
[563]830        }
[570]831
832        return ray.mRelativePvsContribution;
[468]833}
834
835
[469]836void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]837                                                                  const int maxSize,
[503]838                                                                  VssRayContainer &usedRays,
[485]839                                                                  VssRayContainer *savedRays) const
[469]840{
[485]841        const int limit = min(maxSize, (int)sourceRays.size());
[473]842        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]843
[485]844        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]845        for (it = sourceRays.begin(); it != it_end; ++ it)
846        {
[473]847                if (Random(1.0f) < prop)
[485]848                        usedRays.push_back(*it);
849                else if (savedRays)
850                        savedRays->push_back(*it);
[469]851        }
852}
853
[477]854
855float ViewCellsManager::GetAccVcArea()
[470]856{
857        // if already computed
858        if (mTotalAreaValid)
859                return mTotalArea;
860
861        mTotalArea = 0;
862        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
863
864        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]865        {
866                //Debug << "area: " << GetArea(*it);
[470]867        mTotalArea += GetArea(*it);
[480]868        }
869
[470]870        mTotalAreaValid = true;
871
872        return mTotalArea;
873}
874
[482]875
[475]876void ViewCellsManager::PrintStatistics(ostream &s) const
877{
878        s << mViewCellsStats << endl;
879}
880
[477]881
[508]882void ViewCellsManager::CreateUniqueViewCellIds()
[482]883{
[508]884        for (int i = 0; i < (int)mViewCells.size(); ++ i)
885                mViewCells[i]->SetId(i);
886}
887
888
889void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
890{
[482]891        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
892
893        for (it = mViewCells.begin(); it != it_end; ++ it)
894        {
[574]895                if (!mOnlyValidViewCells || (*it)->GetValid())
896                {
[582]897                        ExportColor(exporter, *it);             
[591]898                        ExportViewCellGeometry(exporter, *it,
899                                mUseCuttingPlaneForViz ? &mCuttingPlane : NULL);
[574]900                }
[482]901        }
[582]902
[482]903}
904
905
[517]906void ViewCellsManager::CreateViewCellMeshes()
[503]907{
908        // convert to meshes
909        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
910
911        for (it = mViewCells.begin(); it != it_end; ++ it)
912        {
[517]913                if (!(*it)->GetMesh())
914                        CreateMesh(*it);
[503]915        }
916}
917
[508]918
[564]919bool ViewCellsManager::ExportViewCells(const string filename)
920{
[508]921        return false;
922}
923
924
925void ViewCellsManager::ExportViewCell(ViewCell *viewCell, ofstream &stream)
926{
927        stream << "<ViewCell id=\"" << viewCell->GetId() << "\" ";
928        stream << "pvs=\"";
929
930        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
931        if(0) // test with empty pvs
932        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
933        {
934                stream << (*it).first->GetId() << " ";
935        }
936
937        stream << "\" />" << endl;
938}
939
940
[440]941/**********************************************************************/
942/*                   BspViewCellsManager implementation               */
943/**********************************************************************/
944
[482]945
[574]946BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
947ViewCellsManager(), mBspTree(bspTree)
[440]948{
[574]949        environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
[587]950        mBspTree->SetViewCellsManager(this);
[590]951        mBspTree->mViewCellsTree = mViewCellsTree;
[440]952}
953
[462]954
[440]955bool BspViewCellsManager::ViewCellsConstructed() const
956{
957        return mBspTree->GetRoot() != NULL;
958}
959
[480]960
[440]961ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
962{
963        return new BspViewCell(mesh);
964}
965
[480]966
[574]967int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
968                                                                                          const VssRayContainer &rays)
[440]969{
[441]970        // if view cells were already constructed
[440]971        if (ViewCellsConstructed())
972                return 0;
973
974        int sampleContributions = 0;
[503]975
[469]976        // construct view cells using the collected samples
977        RayContainer constructionRays;
978        VssRayContainer savedRays;
[440]979
[574]980        const int limit = min(mInitialSamples, (int)rays.size());
[440]981
[469]982        VssRayContainer::const_iterator it, it_end = rays.end();
[448]983
[473]984        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
985
[469]986        for (it = rays.begin(); it != it_end; ++ it)
987        {
[473]988                if (Random(1.0f) < prop)
[469]989                        constructionRays.push_back(new Ray(*(*it)));
990                else
991                        savedRays.push_back(*it);
992        }
[440]993
[503]994    if (mViewCells.empty())
995        {
996                // no view cells loaded
[587]997                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
[469]998                // collect final view cells
999                mBspTree->CollectViewCells(mViewCells);
[503]1000        }
[469]1001        else
1002        {
1003                mBspTree->Construct(mViewCells);
1004        }
1005
1006        // destroy rays created only for construction
1007        CLEAR_CONTAINER(constructionRays);
1008
[440]1009        Debug << mBspTree->GetStatistics() << endl;
[503]1010
1011        //EvaluateViewCellsStats();
[480]1012        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1013
[469]1014        // recast rest of the rays
[574]1015        ComputeSampleContributions(savedRays, true, false);
[469]1016
[503]1017
[587]1018        ResetViewCells();
1019   
1020        Debug << "\nView cells after " << (int)savedRays.size()
1021                  << " samples:\n" << mViewCellsStats << endl;
1022
1023        if (1) // export initial view cells
1024        {
1025                cout << "exporting initial view cells (=leaves) ... ";
1026                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
1027
1028                if (exporter)
1029                {
1030                        //exporter->SetWireframe();
1031                        exporter->SetFilled();
1032                        ExportViewCellsForViz(exporter);
1033
1034                        if (0 && mExportRays)
1035                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
1036
1037                        if (mExportGeometry)
1038                                exporter->ExportGeometry(objects);
1039
1040                        delete exporter;
1041                }
1042                cout << "finished" << endl;
1043        }
1044
1045
[440]1046        return sampleContributions;
1047}
1048
[503]1049
[480]1050void BspViewCellsManager::CollectViewCells()
1051{
[587]1052        // view cells tree constructed
1053        if (!ViewCellsTreeConstructed())
[591]1054        {               
[587]1055                mBspTree->CollectViewCells(mViewCells);
1056        }
1057        else
1058        {
1059                // we can use the view cells tree hierarchy to get the right set
[591]1060                mViewCellsTree->CollectBestViewCellSet(mViewCells,
1061                                                                                           mNumMergedViewCells);
[587]1062        }
[480]1063}
[468]1064
[503]1065
[471]1066float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]1067{
[471]1068        // compute view cell area as subsititute for probability
[591]1069        if (1)
1070                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1071        else
1072                return GetArea(viewCell) / GetAccVcArea();
[466]1073}
[440]1074
[503]1075
[587]1076float BspViewCellsManager::GetRendercost(ViewCell *viewCell,
1077                                                                                 float objRendercost) const
[466]1078{
[468]1079        return viewCell->GetPvs().GetSize() * objRendercost;
[440]1080}
1081
[468]1082
1083int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1084                                                                                 const Vector3 &termination,
1085                                                                                 ViewCellContainer &viewcells)
[440]1086{
[468]1087        return mBspTree->CastLineSegment(origin, termination, viewcells);
1088}
1089
1090
[503]1091int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]1092                                                                         const VssRayContainer &rays)
1093{
[469]1094        if (!ViewCellsConstructed())
[441]1095        {
1096                Debug << "view cells not constructed" << endl;
1097                return 0;
1098        }
1099
[590]1100       
1101        // view cells already finished before post processing step (i.e. because they were loaded)
1102        if (mViewCellsFinished)
1103        {
1104                FinalizeViewCells(true);
1105                EvaluateViewCellsStats();
1106
1107                return 0;
1108        }
1109
[440]1110        //-- post processing of bsp view cells
1111    int vcSize = 0;
1112        int pvsSize = 0;
1113
[480]1114        EvaluateViewCellsStats();
[485]1115        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
[480]1116
1117        mRenderer->RenderScene();
1118        SimulationStatistics ss;
1119        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1120
1121    Debug << ss << endl;
1122
[477]1123        if (1) // export view cells
[440]1124        {
1125                cout << "exporting initial view cells (=leaves) ... ";
1126                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]1127
[440]1128                if (exporter)
1129                {
[477]1130                        //exporter->SetWireframe();
1131                        exporter->SetFilled();
[508]1132                        ExportViewCellsForViz(exporter);
[503]1133
[485]1134                        if (mExportGeometry)
[440]1135                        {
[477]1136                                Material m;
[440]1137                                m.mDiffuseColor = RgbColor(0, 1, 0);
1138                                exporter->SetForcedMaterial(m);
[590]1139                       
[440]1140                                exporter->SetWireframe();
1141
1142                                exporter->ExportGeometry(objects);
1143                        }
1144
1145                        delete exporter;
1146                }
1147                cout << "finished" << endl;
1148        }
1149
[591]1150       
[503]1151
[591]1152        //-- merge view cells
1153        int merged;
[587]1154       
[591]1155        const bool mergeBspLeaves = false;
1156        if (mergeBspLeaves)
1157        {
1158                cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1159                long startTime = GetTime();
1160       
1161                VssRayContainer postProcessRays;
1162                GetRaySets(rays, mPostProcessSamples, postProcessRays);
[440]1163
[591]1164                merged = mViewCellsTree->ConstructMergeTree(rays, objects);
[440]1165
[591]1166                //-- stats and visualizations
1167                cout << "finished" << endl;
1168                cout << "merged " << merged << " view cells in "
1169                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[440]1170
[591]1171                Debug << "Postprocessing: Merged " << merged << " view cells in "
1172                        << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
1173                        << "using " << (int)rays.size() << " samples" << endl << endl;
1174        }
[503]1175
[477]1176        // reset view cells and stats
[480]1177        ResetViewCells();
[587]1178        FinalizeViewCells(true);
1179       
[590]1180        // HACK: removes view cells in bsp leaves with active ones
1181        if (0)
1182                AddCurrentViewCellsToHierarchy();
[475]1183
[587]1184        // write view cells to disc
1185        if (mExportViewCells)
1186        {
1187                char buff[100];
1188                environment->GetStringValue("ViewCells.filename", buff);
1189                string vcFilename(buff);
1190
1191                ExportViewCells(buff);
1192        }
1193
[440]1194        return merged;
1195}
1196
[477]1197
1198BspViewCellsManager::~BspViewCellsManager()
1199{
1200}
1201
1202
[440]1203int BspViewCellsManager::GetType() const
1204{
1205        return BSP;
1206}
1207
1208
1209void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1210                                                                        const VssRayContainer &sampleRays)
[440]1211{
[469]1212        if (!ViewCellsConstructed())
1213                return;
[574]1214       
[587]1215        //BspLeaf::NewMail();
1216        if (1) // export merged view cells
[440]1217        {
[587]1218
1219                cout << "reseting view cells ... ";
1220                ResetViewCells();
1221
1222                cout << "finished" << endl;
1223
[469]1224                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[587]1225                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
[477]1226
[587]1227                cout << "exporting view cells after merge ... ";
[557]1228
[469]1229                if (exporter)
[440]1230                {
[587]1231                        if (0)
1232                                exporter->SetWireframe();
1233                        else
1234                                exporter->SetFilled();
[590]1235
[508]1236                        ExportViewCellsForViz(exporter);
[587]1237
1238                        if (mExportGeometry)
1239                        {
1240                                Material m;
1241                                m.mDiffuseColor = RgbColor(0, 1, 0);
1242                                exporter->SetForcedMaterial(m);
1243                                exporter->SetFilled();
1244
1245                                exporter->ExportGeometry(objects);
1246                        }
1247
[469]1248                        delete exporter;
[440]1249                }
[469]1250                cout << "finished" << endl;
[503]1251        }
[477]1252
[469]1253        //-- visualization of the BSP splits
1254        bool exportSplits = false;
1255        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]1256
[469]1257        if (exportSplits)
[440]1258        {
[469]1259                cout << "exporting splits ... ";
[477]1260                ExportSplits(objects);
[469]1261                cout << "finished" << endl;
[440]1262        }
[477]1263
1264        ExportBspPvs(objects);
[440]1265}
1266
1267
[503]1268inline bool vc_gt(ViewCell *a, ViewCell *b)
1269{
[440]1270        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1271}
1272
[477]1273
1274void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]1275{
1276        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1277
[503]1278        if (exporter)
1279        {
1280                Material m;
[440]1281                m.mDiffuseColor = RgbColor(1, 0, 0);
1282                exporter->SetForcedMaterial(m);
1283                exporter->SetWireframe();
[503]1284
[440]1285                exporter->ExportBspSplits(*mBspTree, true);
1286
[482]1287                //NOTE: take forced material, else big scenes cannot be viewed
[440]1288                m.mDiffuseColor = RgbColor(0, 1, 0);
1289                exporter->SetForcedMaterial(m);
[482]1290                //exporter->ResetForcedMaterial();
1291
[440]1292                exporter->SetFilled();
[503]1293
[485]1294                if (mExportGeometry)
[469]1295                        exporter->ExportGeometry(objects);
[477]1296
[440]1297                delete exporter;
1298        }
1299}
1300
[477]1301
1302void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]1303{
[477]1304        const int leafOut = 10;
[503]1305
[477]1306        ViewCell::NewMail();
[440]1307
[477]1308        //-- some rays for output
1309        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]1310
[477]1311        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1312        Debug << "\nOutput view cells: " << endl;
[503]1313
[478]1314        // sort view cells to get largest view cells
[587]1315        if (0)
1316                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1317
[503]1318        int limit = min(leafOut, (int)mViewCells.size());
1319
[478]1320        for (int i = 0; i < limit; ++ i)
[477]1321        {
[478]1322                cout << "creating output for view cell " << i << " ... ";
1323                VssRayContainer vcRays;
1324                Intersectable::NewMail();
[582]1325                ViewCell *vc;
1326
1327                if (0)
1328                        vc = mViewCells[i];
1329                else
1330                        vc = mViewCells[Random((int)mViewCells.size())];
1331
[478]1332                cout << "creating output for view cell " << i << " ... ";
[469]1333
[587]1334                if(0)
[477]1335                {
[587]1336                        // check whether we can add the current ray to the output rays
1337                        for (int k = 0; k < raysOut; ++ k)
[477]1338                        {
[587]1339                                BspRay *ray = mBspRays[k];
1340                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1341                                {
1342                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1343                                        if (vc == leaf->GetViewCell())
1344                                                vcRays.push_back(ray->vssRay);
1345                                }
[477]1346                        }
1347                }
[587]1348
[478]1349                //bspLeaves[j]->Mail();
1350                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]1351
[478]1352                Exporter *exporter = Exporter::GetExporter(s);
[503]1353
[478]1354                exporter->SetWireframe();
[477]1355
[478]1356                Material m;//= RandomMaterial();
1357                m.mDiffuseColor = RgbColor(0, 1, 0);
1358                exporter->SetForcedMaterial(m);
[477]1359
[587]1360                ExportViewCellGeometry(exporter, vc);
1361               
[503]1362
[584]1363                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
[580]1364                          << ", piercing rays=" << (int)vcRays.size() << endl;
1365                         // << ", leaves=" << (int)vc->mLeaves.size() << endl;
[477]1366
[503]1367
[478]1368                // export rays piercing this view cell
1369                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
[580]1370
[478]1371                m.mDiffuseColor = RgbColor(1, 0, 0);
1372                exporter->SetForcedMaterial(m);
[440]1373
[478]1374                ObjectPvsMap::const_iterator it,
1375                        it_end = vc->GetPvs().mEntries.end();
[440]1376
[478]1377                exporter->SetFilled();
[469]1378
[478]1379                // output PVS of view cell
[503]1380                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]1381                {
1382                        Intersectable *intersect = (*it).first;
[469]1383
[478]1384                        if (!intersect->Mailed())
1385                        {
1386                                Material m = RandomMaterial();
1387                                exporter->SetForcedMaterial(m);
1388
1389                                exporter->ExportIntersectable(intersect);
1390                                intersect->Mail();
[503]1391                        }
[477]1392                }
[503]1393
[478]1394                DEL_PTR(exporter);
1395                cout << "finished" << endl;
[477]1396        }
1397
1398        Debug << endl;
[440]1399}
1400
[441]1401
[503]1402void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]1403                                                                          ViewCell *vc) const
1404{
1405        if (mColorCode == 0) // Random color
1406        {
1407                exporter->ResetForcedMaterial();
1408                return;
1409        }
1410
1411        float importance = 0;
1412
1413        switch (mColorCode)
1414        {
1415        case 1: // pvs
1416                {
[503]1417                        importance = (float)vc->GetPvs().GetSize() /
[482]1418                                (float)mViewCellsStats.maxPvs;
1419                }
1420                break;
1421        case 2: // merges
1422                {
[580]1423                        importance = (float)mViewCellsTree->GetSize(vc) /
[482]1424                                (float)mViewCellsStats.maxLeaves;
1425                }
1426                break;
1427        case 3: // merge tree differene
1428                {
1429                        // TODO
1430                }
1431                break;
1432        default:
1433                break;
1434        }
1435
1436        Material m;
1437        m.mDiffuseColor.b = 1.0f;
1438        m.mDiffuseColor.r = importance;
1439        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[503]1440
[482]1441        exporter->SetForcedMaterial(m);
1442}
1443
[587]1444
[580]1445void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]1446                                                                                                 ViewCell *vc,
1447                                                                                                 const Plane3 *cuttingPlane) const
[482]1448{
1449        if (vc->GetMesh())
1450        {
[587]1451                exporter->ExportMesh(vc->GetMesh());
[591]1452       
[587]1453                return;
[482]1454        }
[587]1455
1456        BspNodeGeometry geom;
1457        mBspTree->ConstructGeometry(vc, geom);
[591]1458
1459
1460        if (cuttingPlane)
1461        {
1462                BspNodeGeometry front;
1463                BspNodeGeometry back;
1464
1465                geom.SplitGeometry(front,
1466                                                   back,
1467                                                   *cuttingPlane,
1468                                                   mViewSpaceBox,
1469                                                   0.005);
1470
1471                exporter->ExportPolygons(back.mPolys);
1472        }
1473        else
1474        {
1475                exporter->ExportPolygons(geom.mPolys);
1476        }
[482]1477}
1478
[503]1479
1480void BspViewCellsManager::CreateMesh(ViewCell *vc)
1481{
[587]1482        if (vc->GetMesh())
1483                delete vc->GetMesh();
1484
1485        BspNodeGeometry geom;
1486       
1487        mBspTree->ConstructGeometry(vc, geom);
1488
1489        Mesh *mesh = new Mesh();
1490        geom.AddToMesh(*mesh);
1491        vc->SetMesh(mesh);
1492        mMeshContainer.push_back(mesh);
[503]1493}
1494
[551]1495
[587]1496void BspViewCellsManager::Finalize(ViewCell *viewCell,
1497                                                                   const bool createMesh)
[502]1498{
[587]1499        CreateMesh(viewCell);
[572]1500
[587]1501        float area = 0;
1502        float volume = 0;
[572]1503
[587]1504        ViewCellContainer leaves;
1505        mViewCellsTree->CollectLeaves(viewCell, leaves);
1506
1507        ViewCellContainer::const_iterator it, it_end = leaves.end();
1508
1509        for (it = leaves.begin(); it != it_end; ++ it)
1510        {
1511                BspNodeGeometry geom;
1512                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
1513                mBspTree->ConstructGeometry(leaf, geom);
1514
1515                area += geom.GetArea();
1516                volume += geom.GetVolume();
1517        }
1518
1519        viewCell->SetVolume(volume);
1520        viewCell->SetArea(area);
[502]1521}
1522
[580]1523
[587]1524ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
[580]1525{
[587]1526        if (!mBspTree)
1527                return NULL;
1528
1529        if (!mViewSpaceBox.IsInside(point))
1530                return NULL;
1531       
1532        return mBspTree->GetViewCell(point);
[580]1533}
1534
1535
[587]1536void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1537                                                                                                 vector<MergeCandidate> &candidates)
1538{
1539        cout << "collecting merge candidates ... " << endl;
1540
1541        if (mUseRaysForMerge)
1542        {
1543                mBspTree->CollectMergeCandidates(rays, candidates);
1544        }
1545        else
1546        {
1547                vector<BspLeaf *> leaves;
1548                mBspTree->CollectLeaves(leaves);
1549                mBspTree->CollectMergeCandidates(leaves, candidates);
1550        }
1551
1552        cout << "fininshed collecting candidates" << endl;
1553}
1554
1555
[440]1556
[590]1557bool BspViewCellsManager::ExportViewCells(const string filename)
1558{
1559        cout << "exporting view cells to xml ... ";
1560        std::ofstream stream;
[503]1561
[590]1562        // for output we need unique ids for each view cell
1563        CreateUniqueViewCellIds();
[503]1564
[590]1565
1566        stream.open(filename.c_str());
1567        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
1568        stream << "<Visibility_Solution>" << endl;
1569
1570        //-- the view space bounding box
1571        stream << "<ViewSpaceBox"
1572                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
1573                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
1574
1575        //-- the type of the view cells hierarchy
1576        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
1577        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
1578        //-- load the view cells itself, i.e., the ids and the pvs
1579        stream << "<ViewCells>" << endl;
1580        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1581        for (it = mViewCells.begin(); it != it_end; ++ it)
1582                ExportViewCell(*it, stream);
1583
1584        stream << "</ViewCells>" << endl;
1585
1586        //-- load the hierarchy
1587        stream << "<Hierarchy>" << endl;
1588        mBspTree->Export(stream);
1589        stream << endl << "</Hierarchy>" << endl;
1590
1591        stream << "</Visibility_Solution>" << endl;
1592        stream.close();
1593
1594        cout << "finished" << endl;
1595
1596        return true;
1597}
1598
1599
1600void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
1601{
1602        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1603        for (it = mViewCells.begin(); it != it_end; ++ it)
1604        {
1605                ViewCell *vc = *it;
1606                ViewCellContainer leaves;
1607                mViewCellsTree->CollectLeaves(vc, leaves);
1608               
1609                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
1610
1611                for (lit = leaves.begin(); lit != lit_end; ++ lit)
1612                {
1613                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
1614                        bspVc->mLeaf->SetViewCell(vc);
1615                }
1616        }
1617}
1618
1619/************************************************************************/
1620/*                   KdViewCellsManager implementation                  */
1621/************************************************************************/
1622
1623
1624
[440]1625KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]1626ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]1627{
1628}
1629
[471]1630float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1631{
[479]1632        // compute view cell area / volume as subsititute for probability
[477]1633#if 0
[519]1634        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[479]1635#endif
1636#if 1
[477]1637        return GetArea(viewCell) / GetAccVcArea();
1638#endif
[479]1639#if 0
[519]1640        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[479]1641#endif
[468]1642}
1643
1644
[469]1645float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1646{
[469]1647        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1648}
1649
[479]1650
[480]1651void KdViewCellsManager::CollectViewCells()
1652{
1653        //mKdTree->CollectViewCells(mViewCells); TODO
1654}
[479]1655
[519]1656
[574]1657int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]1658                                                                  const VssRayContainer &rays)
[440]1659{
[441]1660        // if view cells already constructed
[440]1661        if (ViewCellsConstructed())
1662                return 0;
[441]1663
[440]1664        mKdTree->Construct();
1665
[480]1666        mTotalAreaValid = false;
[469]1667        // create the view cells
1668        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]1669
[480]1670        // cast rays
[574]1671        ComputeSampleContributions(rays, true, false);
[480]1672
[479]1673        EvaluateViewCellsStats();
[480]1674        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[469]1675
[440]1676        return 0;
1677}
1678
[587]1679
[440]1680bool KdViewCellsManager::ViewCellsConstructed() const
1681{
1682        return mKdTree->GetRoot() != NULL;
1683}
1684
[503]1685int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1686                                                                        const VssRayContainer &rays)
[440]1687{
1688        return 0;
1689}
1690
1691void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1692                                                                   const VssRayContainer &sampleRays)
[440]1693{
[441]1694        if (!ViewCellsConstructed())
1695                return;
1696
[469]1697        // using view cells instead of the kd PVS of objects
1698        const bool useViewCells = true;
1699        bool exportRays = false;
[440]1700
1701        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]1702        const int pvsOut = min((int)objects.size(), 10);
[466]1703        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]1704
[469]1705        if (useViewCells)
[440]1706        {
[469]1707                const int leafOut = 10;
[503]1708
[469]1709                ViewCell::NewMail();
[503]1710
[469]1711                //-- some rays for output
1712                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1713                Debug << "visualization using " << raysOut << " samples" << endl;
1714
1715                //-- some random view cells and rays for output
1716                vector<KdLeaf *> kdLeaves;
[503]1717
[469]1718                for (int i = 0; i < leafOut; ++ i)
1719                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]1720
[469]1721                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]1722                {
[469]1723                        KdLeaf *leaf = kdLeaves[i];
1724                        RayContainer vcRays;
[503]1725
[469]1726                        cout << "creating output for view cell " << i << " ... ";
[503]1727#if 0
[469]1728                        // check whether we can add the current ray to the output rays
[503]1729                        for (int k = 0; k < raysOut; ++ k)
[440]1730                        {
[469]1731                                Ray *ray = sampleRays[k];
[503]1732
[469]1733                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1734                                {
1735                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]1736
1737                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]1738                                        {
1739                                                vcRays.push_back(ray);
1740                                        }
1741                                }
[479]1742                        }
[503]1743#endif
[469]1744                        Intersectable::NewMail();
[503]1745
[469]1746                        ViewCell *vc = leaf->mViewCell;
[503]1747
[469]1748                        //bspLeaves[j]->Mail();
1749                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]1750
[469]1751                        Exporter *exporter = Exporter::GetExporter(s);
1752                        exporter->SetFilled();
1753
1754                        exporter->SetWireframe();
1755                        //exporter->SetFilled();
[503]1756
[469]1757                        Material m;//= RandomMaterial();
1758                        m.mDiffuseColor = RgbColor(1, 1, 0);
1759                        exporter->SetForcedMaterial(m);
[503]1760
[469]1761                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1762                        exporter->ExportBox(box);
1763
[503]1764                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[469]1765                                << ", piercing rays=" << (int)vcRays.size() << endl;
[503]1766
[469]1767                        // export rays piercing this view cell
[503]1768                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1769
[469]1770                        m.mDiffuseColor = RgbColor(1, 0, 0);
1771                        exporter->SetForcedMaterial(m);
[503]1772
[469]1773                        // exporter->SetWireframe();
1774                        exporter->SetFilled();
[503]1775
[469]1776                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1777                        // output PVS of view cell
[503]1778                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]1779                        {
1780                                Intersectable *intersect = (*it).first;
1781                                if (!intersect->Mailed())
1782                                {
1783                                        exporter->ExportIntersectable(intersect);
1784                                        intersect->Mail();
[503]1785                                }
[440]1786                        }
[503]1787
[469]1788                        DEL_PTR(exporter);
1789                        cout << "finished" << endl;
[440]1790                }
[469]1791
1792                DEL_PTR(rays);
[440]1793        }
[469]1794        else // using kd PVS of objects
1795        {
1796                for (int i = 0; i < limit; ++ i)
1797                {
1798                        VssRay *ray = sampleRays[i];
[503]1799
[469]1800                        // check whether we can add this to the rays
[503]1801                        for (int j = 0; j < pvsOut; j++)
[469]1802                        {
1803                                if (objects[j] == ray->mTerminationObject)
1804                                {
1805                                        rays[j].push_back(ray);
1806                                }
1807                        }
1808                }
[440]1809
[503]1810                if (exportRays)
[469]1811                {
1812                        Exporter *exporter = NULL;
1813                        exporter = Exporter::GetExporter("sample-rays.x3d");
1814                        exporter->SetWireframe();
1815                        exporter->ExportKdTree(*mKdTree);
[503]1816
1817                        for (i=0; i < pvsOut; i++)
[469]1818                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1819
1820                        exporter->SetFilled();
[503]1821
[469]1822                        delete exporter;
1823                }
[440]1824
[503]1825                for (int k=0; k < pvsOut; k++)
[469]1826                {
1827                        Intersectable *object = objects[k];
[503]1828                        char s[64];
[469]1829                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]1830
[469]1831                        Exporter *exporter = Exporter::GetExporter(s);
1832                        exporter->SetWireframe();
[503]1833
[469]1834                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1835                        Intersectable::NewMail();
[503]1836
[469]1837                        // avoid adding the object to the list
1838                        object->Mail();
1839                        ObjectContainer visibleObjects;
[503]1840
1841                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]1842                        {
1843                                KdNode *node = (*i).first;
1844                                exporter->ExportBox(mKdTree->GetBox(node));
[503]1845
[469]1846                                mKdTree->CollectObjects(node, visibleObjects);
1847                        }
[503]1848
[469]1849                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1850                        exporter->SetFilled();
[503]1851
[469]1852                        for (int j = 0; j < visibleObjects.size(); j++)
1853                                exporter->ExportIntersectable(visibleObjects[j]);
[503]1854
[469]1855                        Material m;
1856                        m.mDiffuseColor = RgbColor(1, 0, 0);
1857                        exporter->SetForcedMaterial(m);
1858                        exporter->ExportIntersectable(object);
[503]1859
[469]1860                        delete exporter;
[440]1861                }
[503]1862        }
[440]1863}
1864
[469]1865
[482]1866void KdViewCellsManager::ExportColor(Exporter *exporter,
1867                                                                         ViewCell *vc) const
1868{
1869        // TODO
1870}
1871
[580]1872ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1873{
1874        return new KdViewCell(mesh);
1875}
[482]1876
[580]1877
1878void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]1879                                                                                                ViewCell *vc,
1880                                                                                                const Plane3 *cuttingPlane) const
[482]1881{
[580]1882        ViewCellContainer leaves;
[485]1883
[580]1884        mViewCellsTree->CollectLeaves(vc, leaves);
1885        ViewCellContainer::const_iterator it, it_end = leaves.end();
1886
1887        for (it = leaves.begin(); it != it_end; ++ it)
1888        {
1889                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
1890       
1891                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
1892        }
[482]1893}
1894
1895
[440]1896int KdViewCellsManager::GetType() const
1897{
1898        return ViewCellsManager::KD;
1899}
1900
1901
[441]1902
[440]1903KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1904{
1905        KdNode *node = leaf;
1906
1907        while (node->mParent && node->mDepth > mKdPvsDepth)
1908                node = node->mParent;
1909        return node;
1910}
1911
[469]1912int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1913                                                                                const Vector3 &termination,
1914                                                                                ViewCellContainer &viewcells)
[466]1915{
[469]1916        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]1917}
1918
[469]1919
[503]1920void KdViewCellsManager::CreateMesh(ViewCell *vc)
1921{
[551]1922        // TODO
[503]1923}
1924
[580]1925
1926
1927void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1928                                                                                                vector<MergeCandidate> &candidates)
1929{
1930        // TODO
1931}
1932
1933
[440]1934/**********************************************************************/
1935/*                   VspKdViewCellsManager implementation             */
1936/**********************************************************************/
1937
[482]1938
[574]1939VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
1940ViewCellsManager(), mVspKdTree(vspKdTree)
[440]1941{
[574]1942        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
[468]1943        mVspKdTree->SetViewCellsManager(this);
1944}
[462]1945
[471]1946float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1947{
1948        // volume or area substitutes for view point probability
[480]1949#if 0
[519]1950        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[480]1951#else
1952        return GetArea(viewCell) / GetAccVcArea();
1953#endif
[440]1954}
1955
[462]1956
[469]1957float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1958{
[469]1959        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1960}
1961
[503]1962
[480]1963void VspKdViewCellsManager::CollectViewCells()
1964{
1965        mVspKdTree->CollectViewCells(mViewCells);
1966}
[462]1967
[570]1968
[574]1969int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1970                                                                                                const VssRayContainer &rays)
[440]1971{
[441]1972        // if view cells already constructed
[440]1973        if (ViewCellsConstructed())
1974                return 0;
[503]1975
[469]1976        VssRayContainer constructionRays;
1977        VssRayContainer savedRays;
[440]1978
[503]1979        GetRaySets(rays,
[574]1980                           mInitialSamples,
[503]1981                           constructionRays,
[485]1982                           &savedRays);
[503]1983
1984        Debug << "constructing vsp kd tree using "
[469]1985                  << (int)constructionRays.size() << " samples" << endl;
[452]1986
[542]1987        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]1988        Debug << mVspKdTree->GetStatistics() << endl;
1989
[482]1990        // export leaf building blocks
1991        ExportLeaves(objects, rays);
[480]1992
[469]1993        // finally merge kd leaf building blocks to view cells
[485]1994        const int merged = mVspKdTree->MergeViewCells(rays);
1995
1996        // collapse siblings belonging to the same view cell
[486]1997        mVspKdTree->RefineViewCells(rays);
[485]1998
[542]1999        // collapse siblings belonging to the same view cell
[503]2000        mVspKdTree->CollapseTree();
2001
[482]2002        // evaluale view cell stats
2003        ResetViewCells();
[469]2004
[482]2005        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2006
[485]2007        long startTime = GetTime();
[469]2008        // recast rest of rays
[574]2009        ComputeSampleContributions(savedRays, true, false);
[503]2010
2011        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]2012                  << " secs" << endl;
[469]2013
2014        return merged;
[440]2015}
2016
2017bool VspKdViewCellsManager::ViewCellsConstructed() const
2018{
2019        return mVspKdTree->GetRoot() != NULL;
2020}
2021
[441]2022
[462]2023ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2024{
2025        return new VspKdViewCell(mesh);
2026}
2027
[503]2028int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2029                                                                           const VssRayContainer &rays)
[440]2030{
[441]2031        if (!ViewCellsConstructed())
2032                return 0;
2033
[482]2034        // recalculate stats
2035        EvaluateViewCellsStats();
2036
[469]2037        return 0;
[440]2038}
2039
[482]2040
2041void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2042                                                                                 const VssRayContainer &sampleRays)
[440]2043{
[441]2044        if (!ViewCellsConstructed())
2045                return;
2046
[482]2047        //-- export leaf building blocks
[503]2048        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]2049        if (!exporter)
2050                return;
2051
2052        //exporter->SetWireframe();
2053        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2054        exporter->ExportVspKdTree(*mVspKdTree);
2055
[503]2056        if (mExportGeometry)
[482]2057                exporter->ExportGeometry(objects);
2058
[503]2059        if (mExportRays)
[440]2060        {
[503]2061                const float prob = (float)mVisualizationSamples
[482]2062                        / ((float)sampleRays.size() + Limits::Small);
[440]2063
[482]2064                exporter->SetWireframe();
[440]2065
[482]2066                //-- collect uniformly distributed rays
2067                VssRayContainer rays;
[440]2068
[482]2069                for (int i = 0; i < sampleRays.size(); ++ i)
2070                {
2071                        if (RandomValue(0,1) < prob)
2072                                rays.push_back(sampleRays[i]);
[440]2073                }
[482]2074                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]2075        }
2076
[482]2077        delete exporter;
2078}
2079
2080void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2081                                                                          const VssRayContainer &sampleRays)
2082{
2083        if (!ViewCellsConstructed())
2084                return;
[503]2085
[482]2086        //-- export single view cells
2087        for (int i = 0; i < 10; ++ i)
[440]2088        {
[482]2089                char s[64];
2090                sprintf(s, "vsp_viewcell%04d.x3d", i);
2091                Exporter *exporter = Exporter::GetExporter(s);
[503]2092                const int idx =
[482]2093                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]2094
[503]2095                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]2096
[483]2097                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
2098                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
[482]2099                //-- export geometry
2100                Material m;
2101                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]2102
[482]2103                exporter->SetForcedMaterial(m);
2104                exporter->SetWireframe();
2105
[580]2106                ExportViewCellGeometry(exporter, vc);
[482]2107
2108                //-- export stored rays
[580]2109               
[485]2110                if (mExportRays)
[440]2111                {
[580]2112                        ViewCellContainer leaves;
2113                        mViewCellsTree->CollectLeaves(vc, leaves);
[440]2114
[580]2115                        ViewCellContainer::const_iterator it,
2116                                it_end = leaves.end();
2117
2118                        for (it = leaves.begin(); it != it_end; ++ it)
[482]2119                        {
[580]2120                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2121                                VspKdLeaf *leaf = vspKdVc->mLeaf;
[482]2122                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]2123
[482]2124                                VssRayContainer vssRays;
[483]2125
2126                                VssRayContainer castRays;
2127                                VssRayContainer initRays;
2128
[482]2129                                leaf->GetRays(vssRays);
[440]2130
[482]2131                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]2132                                const float prop = 200.0f / (float)vssRays.size();
[440]2133
[482]2134                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]2135                                {
[485]2136                                        if (Random(1) < prop)
[483]2137                                                if ((*it)->mTerminationObject == NULL)
2138                                                        castRays.push_back(*it);
[503]2139                                                else
[483]2140                                                        initRays.push_back(*it);
2141                                }
2142
2143                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2144                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]2145                        }
2146                }
[580]2147       
[482]2148                //-- output PVS of view cell
2149                m.mDiffuseColor = RgbColor(1, 0, 0);
2150                exporter->SetForcedMaterial(m);
[440]2151
[483]2152                Intersectable::NewMail();
2153
[482]2154                ObjectPvsMap::const_iterator it,
2155                        it_end = vc->GetPvs().mEntries.end();
2156
2157                exporter->SetFilled();
2158
[503]2159                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]2160                {
2161                        Intersectable *intersect = (*it).first;
2162
2163                        if (!intersect->Mailed())
2164                        {
2165                                Material m = RandomMaterial();
2166                                exporter->SetForcedMaterial(m);
2167
2168                                exporter->ExportIntersectable(intersect);
2169                                intersect->Mail();
[503]2170                        }
[482]2171                }
2172
2173                delete exporter;
[440]2174        }
[462]2175
2176        //-- export final view cells
[503]2177        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2178
[485]2179        //if (exportGeometry) exporter->SetWireframe();
2180        //else exporter->SetFilled();
[483]2181
[508]2182        ExportViewCellsForViz(exporter);
[462]2183
[503]2184        if (mExportGeometry)
[465]2185        {
2186                exporter->SetFilled();
[462]2187                exporter->ExportGeometry(objects);
[465]2188        }
[469]2189
[503]2190        if (mExportRays)
[462]2191        {
[503]2192                const float prob = (float)mVisualizationSamples
[482]2193                        / ((float)sampleRays.size() + Limits::Small);
[503]2194
[462]2195                exporter->SetWireframe();
[503]2196
[466]2197                VssRayContainer rays;
[503]2198
[462]2199                for (int i = 0; i < sampleRays.size(); ++ i)
2200                {
[466]2201                  if (RandomValue(0,1) < prob)
2202                        rays.push_back(sampleRays[i]);
[462]2203                }
[503]2204                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]2205        }
2206
2207        delete exporter;
[440]2208}
2209
2210int VspKdViewCellsManager::GetType() const
2211{
2212        return VSP_KD;
2213}
[442]2214
[462]2215
[469]2216int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2217                                                                                   const Vector3 &termination,
2218                                                                                   ViewCellContainer &viewcells)
[466]2219{
[469]2220        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]2221}
2222
[477]2223
[482]2224void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2225                                                                                ViewCell *vc) const
2226{
2227        if (mColorCode == 0) // Random color
2228                return;
[503]2229
[482]2230        float importance = 0;
[477]2231
[482]2232        switch (mColorCode)
2233        {
2234        case 1: // pvs
2235                {
[503]2236                        importance = (float)vc->GetPvs().GetSize() /
[482]2237                                (float)mViewCellsStats.maxPvs;
2238                }
2239                break;
[580]2240        case 2: // merged leaves
[482]2241                {
[580]2242                int lSize = mViewCellsTree->GetSize(vc);
2243                        importance = (float)lSize /
[482]2244                                (float)mViewCellsStats.maxLeaves;
2245                }
2246                break;
[485]2247        case 3: // merged tree depth difference
[482]2248                {
[503]2249                        //importance = (float)GetMaxTreeDiff(vc) /
[482]2250                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2251                }
2252                break;
2253        default:
2254                break;
2255        }
2256
2257        Material m;
2258        m.mDiffuseColor.b = 1.0f;
2259        m.mDiffuseColor.r = importance;
2260        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2261        //Debug << "importance: " << importance << endl;
2262        exporter->SetForcedMaterial(m);
2263}
2264
2265
[580]2266void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2267                                                                                                   ViewCell *vc,
2268                                                                                                   const Plane3 *cuttingPlane) const
[482]2269{
2270        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2271
[486]2272        Mesh m;
[580]2273
2274        ViewCellContainer leaves;
2275        mViewCellsTree->CollectLeaves(vc, leaves);
2276
2277        ViewCellContainer::const_iterator it, it_end = leaves.end();
2278
2279        for (it = leaves.begin(); it != it_end; ++ it)
[486]2280        {
[580]2281                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2282                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
[486]2283        }
2284
2285        exporter->ExportMesh(&m);
[482]2286}
2287
2288
[503]2289void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2290{
[551]2291        //TODO
[503]2292}
[442]2293
[574]2294
[584]2295void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2296                                                                                                   vector<MergeCandidate> &candidates)
[580]2297{
2298        // TODO
2299}
[574]2300
[580]2301
[503]2302/**************************************************************************/
2303/*                   VspBspViewCellsManager implementation                */
2304/**************************************************************************/
[482]2305
[503]2306
[574]2307VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
2308ViewCellsManager(), mVspBspTree(vspBspTree)
[442]2309{
[574]2310        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
[478]2311        mVspBspTree->SetViewCellsManager(this);
[590]2312        mVspBspTree->mViewCellsTree = mViewCellsTree;
[442]2313}
2314
[477]2315
[475]2316VspBspViewCellsManager::~VspBspViewCellsManager()
2317{
2318}
2319
[477]2320
[471]2321float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2322{
[551]2323        if (0 && mVspBspTree->mUseAreaForPvs)
[547]2324                return GetArea(viewCell) / GetAccVcArea();
2325        else
2326                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]2327}
2328
[477]2329
[480]2330void VspBspViewCellsManager::CollectViewCells()
2331{
[581]2332        // view cells tree constructed
2333        if (!ViewCellsTreeConstructed())
2334        {
[590]2335                mVspBspTree->CollectViewCells(mViewCells, false);
[581]2336        }
2337        else
2338        {
2339                // we can use the view cells tree hierarchy to get the right set
[582]2340                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumMergedViewCells);
[581]2341        }
2342
[480]2343}
2344
2345
[503]2346float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
[477]2347                                                                                        float objRendercost) const
[468]2348{
2349        return viewCell->GetPvs().GetSize() * objRendercost;
2350}
2351
[462]2352
[442]2353bool VspBspViewCellsManager::ViewCellsConstructed() const
2354{
2355        return mVspBspTree->GetRoot() != NULL;
2356}
2357
[462]2358
[442]2359ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2360{
2361        return new BspViewCell(mesh);
2362}
2363
[569]2364
[574]2365int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]2366                                                                          const VssRayContainer &rays)
[442]2367{
[503]2368        // if view cells were already constructed
2369        if (ViewCellsConstructed())
2370                return 0;
[442]2371
[503]2372        Debug << "Constructing bsp view cells" << endl;
2373
2374        int sampleContributions = 0;
2375
2376        VssRayContainer sampleRays;
2377
[574]2378        int limit = min (mInitialSamples, (int)rays.size());
[503]2379
[469]2380        VssRayContainer constructionRays;
2381        VssRayContainer savedRays;
[442]2382
[587]2383        Debug << "samples used for subdivision: " << mInitialSamples
2384                  << " rays: " << (int)rays.size() << endl;
2385
[574]2386        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
[487]2387
[574]2388        Debug << "initial rays: " << (int)constructionRays.size() << endl;
[508]2389        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]2390
[547]2391        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
[564]2392
[542]2393        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[503]2394
[480]2395        Debug << mVspBspTree->GetStatistics() << endl;
[491]2396
[490]2397        // collapse invalid regions
[491]2398        cout << "collapsing invalid tree regions ... ";
[495]2399        long startTime = GetTime();
[503]2400        int collapsedLeaves = mVspBspTree->CollapseTree();
[587]2401        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
2402                  << " seconds" << endl;
2403
[495]2404    cout << "finished" << endl;
[503]2405
[491]2406        cout << "reseting view cell stats ... ";
[480]2407        ResetViewCells();
[491]2408        cout << "finished" << endl;
[503]2409
[480]2410        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[491]2411
2412        if (1) // export initial view cells
2413        {
2414                cout << "exporting initial view cells (=leaves) ... ";
2415                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]2416
[491]2417                if (exporter)
2418                {
2419                        //exporter->SetWireframe();
2420                        exporter->SetFilled();
[508]2421                        ExportViewCellsForViz(exporter);
[491]2422
[495]2423                        if (0 && mExportRays)
2424                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
[503]2425
[491]2426                        if (mExportGeometry)
2427                                exporter->ExportGeometry(objects);
[503]2428
[491]2429                        delete exporter;
2430                }
2431                cout << "finished" << endl;
2432        }
2433
[495]2434        startTime = GetTime();
[503]2435
2436        // reset view cells and stats
2437        ResetViewCells();
2438
[491]2439        cout << "Computing remaining ray contributions ... ";
[469]2440        // recast rest of rays
[574]2441        ComputeSampleContributions(savedRays, true, false);
[491]2442        cout << "finished" << endl;
2443
[503]2444        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]2445                  << " secs" << endl;
[442]2446
[485]2447        cout << "construction finished" << endl;
[503]2448
[442]2449        return sampleContributions;
2450}
2451
[489]2452
[503]2453void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2454                                                                                        const ObjectContainer &objects)
[475]2455{
[442]2456        //-- post processing of bsp view cells
2457    int vcSize = 0;
2458        int pvsSize = 0;
2459
[480]2460        mRenderer->RenderScene();
2461        SimulationStatistics ss;
2462        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2463    Debug << ss << endl;
2464
[442]2465        //-- merge or subdivide view cells
2466        int merged = 0;
[503]2467
[561]2468        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
[485]2469        long startTime = GetTime();
[442]2470
[580]2471       
[503]2472        // TODO: should be done BEFORE the ray casting
[580]2473        merged = mViewCellsTree->ConstructMergeTree(rays, objects);
[442]2474
[485]2475        //-- stats and visualizations
[561]2476        cout << "finished merging" << endl;
[485]2477        cout << "merged " << merged << " view cells in "
2478                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2479
2480        Debug << "Postprocessing: Merged " << merged << " view cells in "
2481                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]2482
[491]2483
[485]2484        //BspLeaf::NewMail();
2485        if (1) // export merged view cells
[483]2486        {
[574]2487
2488                cout << "reseting view cells ... ";
2489                ResetViewCells();
[587]2490
[574]2491                cout << "finished" << endl;
2492
[485]2493                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2494                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
[483]2495
[485]2496                cout << "exporting view cells after merge ... ";
2497
2498                if (exporter)
[483]2499                {
[564]2500                        if (0)
[551]2501                                exporter->SetWireframe();
2502                        else
2503                                exporter->SetFilled();
[508]2504                        ExportViewCellsForViz(exporter);
[442]2505
[485]2506                        if (mExportGeometry)
[483]2507                        {
[485]2508                                Material m;
2509                                m.mDiffuseColor = RgbColor(0, 1, 0);
2510                                exporter->SetForcedMaterial(m);
2511                                exporter->SetFilled();
[442]2512
[485]2513                                exporter->ExportGeometry(objects);
[442]2514                        }
[485]2515
2516                        delete exporter;
[442]2517                }
[485]2518                cout << "finished" << endl;
[442]2519        }
[503]2520}
[475]2521
[503]2522
[564]2523void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2524                                                                                         const ObjectContainer &objects)
[503]2525{
[485]2526        Debug << "render time before refine:" << endl;
2527        mRenderer->RenderScene();
[503]2528        SimulationStatistics ss;
[485]2529        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2530    Debug << ss << endl;
2531
[489]2532        cout << "Refining the merged view cells ... ";
[503]2533        long startTime = GetTime();
[485]2534
2535        // refining the merged view cells
[580]2536        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
[485]2537
[442]2538        //-- stats and visualizations
2539        cout << "finished" << endl;
[485]2540        cout << "refined " << refined << " view cells in "
[442]2541                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2542
[485]2543        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]2544                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]2545}
[495]2546
[517]2547
[503]2548int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2549                                                                                const VssRayContainer &rays)
2550{
2551        if (!ViewCellsConstructed())
2552        {
[517]2553                Debug << "postprocess error: no view cells constructed" << endl;
[503]2554                return 0;
2555        }
[520]2556
[564]2557
[542]2558        // view cells already finished before post processing step (i.e. because they were loaded)
[520]2559        if (mViewCellsFinished)
[542]2560        {
[551]2561                FinalizeViewCells(true);
[542]2562                EvaluateViewCellsStats();
[577]2563
[517]2564                return 0;
[542]2565        }
[448]2566
[564]2567
[542]2568        // check if new view cells turned invalid
[574]2569        SetValidity(mMinPvsSize, mMaxPvsSize);
2570        // update valid view space according to valid view cells
[544]2571        mVspBspTree->ValidateTree();
[542]2572
[574]2573        // recompute view cell statistics
2574        mViewCellsStats.Reset();
2575        EvaluateViewCellsStats();
[580]2576
[574]2577        // has to be recomputed
2578        mTotalAreaValid = false;
[542]2579
[574]2580
[517]2581        VssRayContainer postProcessRays;
2582        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2583
2584        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]2585
[517]2586        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2587
[552]2588        // should maybe be done here to allow merge working with area or volume
2589        // and to correct the rendering statistics
[554]2590        if (0)
[551]2591        {
2592                FinalizeViewCells(false);
2593        }
2594
[591]2595        if (mMergeViewCells)
2596        {
2597                //-- merge the individual view cells
2598                MergeViewCells(postProcessRays, objects);
2599       
[580]2600
[591]2601                //-- refines the merged view cells
2602                if (0)
2603                        RefineViewCells(postProcessRays, objects);
[568]2604
[591]2605                if (mCompressViewCells)
2606                {
2607                        int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2608                        Debug << "number of entries before compress: " << pvsEntries << endl;
[584]2609
[591]2610                        mViewCellsTree->CompressViewCellsPvs();
[583]2611
[591]2612                        pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2613                        Debug << "number of entries after compress: " << pvsEntries << endl;
2614                }
[586]2615        }
[584]2616
[580]2617        if (1)
2618        {               
2619                float totalCost, erc, var, dev, avg;
2620                int totalpvs;
2621
2622                mViewCellsStats.Reset();
2623
2624        EvaluateRenderStatistics(totalCost, erc, dev, var, totalpvs, avg);
2625               
2626                Debug << "statistics after merge " 
2627                          << " erc: " << erc
2628                          << " dev: " << dev
2629                          << " totalpvs: " << totalpvs
2630                          << " avg: " << avg << endl;
2631        }
2632
2633
[568]2634        //-- export shuffled view cells
[586]2635        if (0)
[568]2636        {
2637                cout << "exporting shuffled view cells ... ";
2638
2639                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2640                if (exporter)
2641                {
2642                        if (1)
2643                        {
2644                                exporter->SetWireframe();
2645                                exporter->ExportBox(mViewSpaceBox);
2646                                exporter->SetFilled();
2647                        }
2648
2649                        if (mExportGeometry)
2650                        {
2651                                exporter->ExportGeometry(objects);
2652                        }
2653
2654                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2655
2656                        Material vm, lm;
2657
2658                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2659                        {
[582]2660                                ViewCell *vc = *vit;
[568]2661
2662                                vm = RandomMaterial();
2663
2664                                lm = vm;
2665
2666                                vm.mDiffuseColor.r -= 0.45f;
2667                                vm.mDiffuseColor.g -= 0.45f;
2668                                vm.mDiffuseColor.b -= 0.45f;
2669
2670
[580]2671                                ViewCellContainer leaves;
2672                                mViewCellsTree->CollectLeaves(vc, leaves);
2673
2674                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2675
2676                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
[568]2677                                {
[580]2678                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
[568]2679
2680                                        if (leaf->Mailed())
2681                                                exporter->SetForcedMaterial(lm);
2682                                        else
2683                                                exporter->SetForcedMaterial(vm);
2684
2685                                        BspNodeGeometry geom;
2686                                        mVspBspTree->ConstructGeometry(leaf, geom);
2687                                        exporter->ExportPolygons(geom.mPolys);
2688                                }
2689                        }
2690
2691                        delete exporter;
2692                }
2693
2694
2695                cout << "finished" << endl;
2696        }
2697
[517]2698        // collapse sibling leaves that share the same view cell
[586]2699        if (0)
2700                mVspBspTree->CollapseTree();
2701
[574]2702        // recompute view cell list and statistics
[520]2703        ResetViewCells();
2704
[508]2705        // real meshes are only contructed only at this stage
[551]2706        FinalizeViewCells(true);
[517]2707
[590]2708        // HACK: removes view cells in bsp leaves with active ones
2709        if (0)
2710                AddCurrentViewCellsToHierarchy();
[577]2711
[590]2712
[508]2713        // write view cells to disc
2714        if (mExportViewCells)
2715        {
[517]2716                char buff[100];
2717                environment->GetStringValue("ViewCells.filename", buff);
2718                string vcFilename(buff);
2719
2720                ExportViewCells(buff);
[508]2721        }
[503]2722
2723        return 0;
[442]2724}
2725
[490]2726
[442]2727int VspBspViewCellsManager::GetType() const
2728{
2729        return VSP_BSP;
2730}
2731
2732
[490]2733bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2734{
2735        if (!ViewCellsConstructed())
2736                return ViewCellsManager::GetViewPoint(viewPoint);
2737
2738        // TODO: set reasonable limit
2739        const int limit = 20;
2740
2741        for (int i = 0; i < limit; ++ i)
2742        {
[542]2743                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]2744                if (mVspBspTree->ViewPointValid(viewPoint))
2745                {
2746                        return true;
2747                }
2748        }
2749        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2750        return false;
2751}
2752
2753
2754bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2755{
[569]2756  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2757  // validy update in preprocessor for all managers)
2758  return ViewCellsManager::ViewPointValid(viewPoint);
[570]2759
[569]2760  //    return mViewSpaceBox.IsInside(viewPoint) &&
2761  //               mVspBspTree->ViewPointValid(viewPoint);
[490]2762}
2763
2764
[442]2765void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2766                                                                           const VssRayContainer &sampleRays)
[442]2767{
2768        if (!ViewCellsConstructed())
2769                return;
2770
[485]2771        VssRayContainer visRays;
2772        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]2773
[442]2774        if (1) // export view cells
2775        {
[485]2776                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[442]2777
2778                if (exporter)
2779                {
[580]2780                        cout << "exporting view cells after post process ... ";
2781
[542]2782                        if (1)
2783                        {
2784                                exporter->SetWireframe();
2785                                exporter->ExportBox(mViewSpaceBox);
2786                                exporter->SetFilled();
2787                        }
2788
[485]2789                        if (mExportGeometry)
[542]2790                        {
[485]2791                                exporter->ExportGeometry(objects);
[542]2792                        }
[489]2793
2794                        // export rays
[490]2795                        if (mExportRays)
[489]2796                        {
[490]2797                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2798                        }
[564]2799
[508]2800                        ExportViewCellsForViz(exporter);
[442]2801                        delete exporter;
[580]2802                        cout << "finished" << endl;
[442]2803                }
[557]2804        }
[503]2805
[577]2806        if (1)
2807        {
2808                cout << "exporting depth map ... ";
2809
2810                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2811                if (exporter)
2812                {
2813                        if (1)
2814                        {
2815                                exporter->SetWireframe();
2816                                exporter->ExportBox(mViewSpaceBox);
2817                                exporter->SetFilled();
2818                        }
2819
2820                        if (mExportGeometry)
2821                        {
2822                                exporter->ExportGeometry(objects);
2823                        }
2824
2825                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
2826
2827                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2828
2829                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2830                        {
[582]2831                                ViewCell *vc = *vit;
[577]2832
[580]2833                                ViewCellContainer leaves;
2834                                mViewCellsTree->CollectLeaves(vc, leaves);
[577]2835
[580]2836                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2837
2838                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
[577]2839                                {
[580]2840                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
[577]2841
2842                                        Material m;
2843
2844                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
2845                                        m.mDiffuseColor.r = relDepth;
2846                                        m.mDiffuseColor.g = 0.0f;
2847                                        m.mDiffuseColor.b = 1.0f - relDepth;
2848
2849                    exporter->SetForcedMaterial(m);
2850                               
2851
2852                                        BspNodeGeometry geom;
2853                                        mVspBspTree->ConstructGeometry(leaf, geom);
2854                                        exporter->ExportPolygons(geom.mPolys);
2855                                }
2856                        }
2857
2858                        delete exporter;
2859                }
2860
2861
2862                cout << "finished" << endl;
2863        }
2864
[442]2865        //-- visualization of the BSP splits
2866        bool exportSplits = false;
[489]2867        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]2868
[442]2869        if (exportSplits)
2870        {
2871                cout << "exporting splits ... ";
[485]2872                ExportSplits(objects, visRays);
[442]2873                cout << "finished" << endl;
2874        }
2875
[542]2876        //-- export single view cells
[485]2877        ExportBspPvs(objects, visRays);
[442]2878}
2879
[503]2880
[485]2881void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2882                                                                                  const VssRayContainer &rays)
[442]2883{
2884        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2885
[503]2886        if (exporter)
2887        {
2888                Material m;
[442]2889                m.mDiffuseColor = RgbColor(1, 0, 0);
2890                exporter->SetForcedMaterial(m);
2891                exporter->SetWireframe();
[503]2892
[448]2893                exporter->ExportBspSplits(*mVspBspTree, true);
[442]2894
2895                // take forced material, else big scenes cannot be viewed
2896                m.mDiffuseColor = RgbColor(0, 1, 0);
2897                exporter->SetForcedMaterial(m);
2898                exporter->SetFilled();
2899
2900                exporter->ResetForcedMaterial();
[503]2901
[442]2902                // export rays
[485]2903                if (mExportRays)
2904                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]2905
[485]2906                if (mExportGeometry)
[442]2907                        exporter->ExportGeometry(objects);
2908
2909                delete exporter;
2910        }
2911}
2912
[503]2913
[485]2914void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2915                                                                                  const VssRayContainer &rays)
[442]2916{
2917        const int leafOut = 10;
[503]2918
[442]2919        ViewCell::NewMail();
[503]2920
[442]2921        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
[475]2922        Debug << "\nOutput view cells: " << endl;
[503]2923
[485]2924        // sort view cells to visualize the largest view cells
[587]2925        if (0)
2926                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2927
[503]2928        int limit = min(leafOut, (int)mViewCells.size());
[483]2929
[587]2930        int raysOut;
2931
[485]2932        //-- some rays for output
[587]2933        if (1)
2934                raysOut = min((int)rays.size(), mVisualizationSamples);
[485]2935
[478]2936        for (int i = 0; i < limit; ++ i)
[442]2937        {
[478]2938                cout << "creating output for view cell " << i << " ... ";
[503]2939
[478]2940                VssRayContainer vcRays;
[485]2941                Intersectable::NewMail();
[582]2942                ViewCell *vc;
[574]2943       
2944                if (0) // largest view cell pvs first
[582]2945                        vc = mViewCells[i];
[574]2946                else
[582]2947                        vc = mViewCells[Random((int)mViewCells.size())];
[442]2948
[587]2949                vector<ViewCell *> leaves;
2950                mViewCellsTree->CollectLeaves(vc, leaves);
2951
[574]2952        if (1)
[442]2953                {
[574]2954                        // check whether we can add the current ray to the output rays
2955                        for (int k = 0; k < raysOut; ++ k)
[442]2956                        {
[574]2957                                VssRay *ray = rays[k];
2958                                for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
2959                                {
[582]2960                                        ViewCell *rayvc = ray->mViewCells[j];
[587]2961
2962                                        if (leaves[0] == rayvc)
[574]2963                                                vcRays.push_back(ray);
2964                                }
[442]2965                        }
2966                }
[574]2967
[478]2968                //bspLeaves[j]->Mail();
2969                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2970                Exporter *exporter = Exporter::GetExporter(s);
2971                exporter->SetWireframe();
[442]2972
[478]2973                Material m;//= RandomMaterial();
2974                m.mDiffuseColor = RgbColor(0, 1, 0);
2975                exporter->SetForcedMaterial(m);
[442]2976
[580]2977                ExportViewCellGeometry(exporter, vc);
[503]2978
2979
[586]2980                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
[580]2981                          << ", piercing rays=" << (int)vcRays.size() << endl;
2982                        //  << ", leaves=" << (int)vc->mLeaves.size() << endl;
[503]2983
[574]2984               
[485]2985                //-- export rays piercing this view cell
[574]2986                if (1)
2987                {
2988                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2989                }
2990                else
2991                {
[483]2992
[580]2993                        ViewCellContainer leaves;
2994                        mViewCellsTree->CollectLeaves(vc, leaves);
2995
2996                        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2997
2998                        for (lit = leaves.begin(); lit != lit_end; ++ lit)
2999                        {
3000                                BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3001                                exporter->ExportRays(l->mVssRays);
3002                        }
[574]3003                }
3004
3005       
[478]3006                m.mDiffuseColor = RgbColor(1, 0, 0);
3007                exporter->SetForcedMaterial(m);
[442]3008
[478]3009                ObjectPvsMap::const_iterator it,
3010                        it_end = vc->GetPvs().mEntries.end();
[442]3011
[478]3012                exporter->SetFilled();
[442]3013
[574]3014       
[478]3015                // output PVS of view cell
[503]3016                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]3017                {
[574]3018               
[478]3019                        Intersectable *intersect = (*it).first;
[442]3020
[478]3021                        if (!intersect->Mailed())
3022                        {
3023                                Material m = RandomMaterial();
3024                                exporter->SetForcedMaterial(m);
3025
3026                                exporter->ExportIntersectable(intersect);
3027                                intersect->Mail();
[503]3028                        }
[442]3029                }
[503]3030
[574]3031               
[478]3032                DEL_PTR(exporter);
3033                cout << "finished" << endl;
[442]3034        }
[475]3035
3036        Debug << endl;
[442]3037}
3038
3039
[469]3040int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3041                                                                                        const Vector3 &termination,
3042                                                                                        ViewCellContainer &viewcells)
[466]3043{
[469]3044        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]3045}
[482]3046
3047
[503]3048void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]3049                                                                                 ViewCell *vc) const
3050{
[564]3051        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[503]3052
[482]3053        float importance = 0;
[564]3054        static Material m;
3055
[482]3056        switch (mColorCode)
3057        {
[564]3058        case 0: // Random
3059                {
3060                        if (vcValid)
3061                        {
[591]3062                                m.mDiffuseColor.r = RandomValue(0.3f, 1.0f);
3063                                m.mDiffuseColor.g = RandomValue(0.3f, 1.0f);
3064                                m.mDiffuseColor.b = RandomValue(0.3f, 1.0f);
[564]3065                        }
3066                        else
3067                        {
3068                                m.mDiffuseColor.r = 0.0f;
3069                                m.mDiffuseColor.g = 1.0f;
3070                                m.mDiffuseColor.b = 0.0f;
3071                        }
[591]3072
3073                        exporter->SetForcedMaterial(m);
3074                        return;
[564]3075                }
[591]3076               
[482]3077        case 1: // pvs
3078                {
[503]3079                        importance = (float)vc->GetPvs().GetSize() /
[482]3080                                (float)mViewCellsStats.maxPvs;
[570]3081
[482]3082                }
3083                break;
3084        case 2: // merges
3085                {
[580]3086            int lSize = mViewCellsTree->GetSize(vc);
3087       
3088                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
[482]3089                }
3090                break;
3091        case 3: // merge tree differene
3092                {
[503]3093                        importance = (float)GetMaxTreeDiff(vc) /
[482]3094                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]3095
[482]3096                }
3097                break;
3098        default:
3099                break;
3100        }
3101
[564]3102        // special color code for invalid view cells
[482]3103        m.mDiffuseColor.r = importance;
3104        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[564]3105        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[547]3106
[482]3107        //Debug << "importance: " << importance << endl;
3108        exporter->SetForcedMaterial(m);
3109}
3110
3111
[580]3112void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3113                                                    ViewCell *vc,
3114                                                                                                        const Plane3 *cuttingPlane) const
[482]3115{
[542]3116        if (vc->GetMesh())
[503]3117        {
3118                exporter->ExportMesh(vc->GetMesh());
[590]3119       
[503]3120                return;
3121        }
3122
[591]3123       
3124        if (cuttingPlane)
3125        {
3126                ViewCellContainer leaves;
3127                mViewCellsTree->CollectLeaves(vc, leaves);
3128                ViewCellContainer::const_iterator it, it_end = leaves.end();
3129
3130                for (it = leaves.begin(); it != it_end; ++ it)
3131                {
3132                        BspNodeGeometry geom;
3133
3134                        BspNodeGeometry front;
3135                        BspNodeGeometry back;
3136
3137       
3138                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3139
3140                        mVspBspTree->ConstructGeometry(leaf, geom);
3141                       
3142                        geom.SplitGeometry(front,
3143                                                           back,
3144                                                           *cuttingPlane,
3145                                                           mViewSpaceBox,
3146                                                           0.005);
3147
3148                        exporter->ExportPolygons(back.mPolys);
3149                }
3150        }
3151        else
3152        {
3153                BspNodeGeometry geom;
3154                mVspBspTree->ConstructGeometry(vc, geom);
3155                       
3156                exporter->ExportPolygons(geom.mPolys);
3157        }
[482]3158}
3159
3160
3161int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3162{
[580]3163        ViewCellContainer leaves;
3164        mViewCellsTree->CollectLeaves(vc, leaves);
[482]3165
3166        int maxDist = 0;
[580]3167       
[482]3168        // compute max height difference
[580]3169        for (int i = 0; i < (int)leaves.size(); ++ i)
3170                for (int j = 0; j < (int)leaves.size(); ++ j)
[482]3171        {
[580]3172                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
[482]3173
3174                if (i != j)
3175                {
[580]3176                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
[482]3177                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3178                        if (dist > maxDist)
3179                                maxDist = dist;
3180                }
3181        }
[580]3182
[492]3183        return maxDist;
3184}
[482]3185
[492]3186
[569]3187ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
[492]3188{
[508]3189        if (!mVspBspTree)
3190                return NULL;
[572]3191
3192        if (!mViewSpaceBox.IsInside(point))
3193          return NULL;
3194
[508]3195        return mVspBspTree->GetViewCell(point);
[492]3196}
[503]3197
3198
3199void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3200{
[577]3201        if (vc->GetMesh())
3202                delete vc->GetMesh();
3203
[590]3204       
[503]3205        BspNodeGeometry geom;
[590]3206
3207        mVspBspTree->ConstructGeometry(vc, geom);
[582]3208       
[503]3209        Mesh *mesh = new Mesh();
3210        geom.AddToMesh(*mesh);
3211        vc->SetMesh(mesh);
3212        mMeshContainer.push_back(mesh);
3213}
[508]3214
3215
[577]3216ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3217                                                                                                  ObjectContainer *objects)
[508]3218{
3219        ViewCellsParser parser;
[564]3220
[577]3221        ViewCellsManager *vm = NULL;
[564]3222
[577]3223        if (parser.ParseFile(filename, &vm, objects))
3224        {
[590]3225                //vm->PrepareLoadedViewCells();
[577]3226                vm->ResetViewCells();
[564]3227
[577]3228                vm->mViewCellsFinished = true;
3229                vm->mMaxPvsSize = (int)objects->size();
[517]3230
[577]3231                vm->FinalizeViewCells(true);
[564]3232
[577]3233                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3234        }
3235        else
3236        {
3237                Debug << "failed loading view cells" << endl;
3238                DEL_PTR(vm);
3239        }
3240
3241
3242        return vm;
[508]3243}
3244
3245
3246inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3247{
3248        return obj1->mId < obj2->mId;
3249}
3250
3251
3252bool VspBspViewCellsManager::ExportViewCells(const string filename)
3253{
[564]3254        cout << "exporting view cells to xml ... ";
[508]3255        std::ofstream stream;
3256
[577]3257        // for output we need unique ids for each view cell
[590]3258        CreateUniqueViewCellIds();
[508]3259
[590]3260
[508]3261        stream.open(filename.c_str());
3262        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3263        stream << "<Visibility_Solution>" << endl;
[564]3264
[577]3265        //-- the view space bounding box
3266        stream << "<ViewSpaceBox"
3267                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3268                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3269
3270        //-- the type of the view cells hierarchy
3271        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3272
[508]3273        //-- load the view cells itself, i.e., the ids and the pvs
3274        stream << "<ViewCells>" << endl;
3275        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3276        for (it = mViewCells.begin(); it != it_end; ++ it)
3277                ExportViewCell(*it, stream);
[564]3278
[508]3279        stream << "</ViewCells>" << endl;
[564]3280
[508]3281        //-- load the hierarchy
[590]3282        stream << "<Hierarchy>" << endl;
[508]3283        mVspBspTree->Export(stream);
[590]3284        stream << endl << "</Hierarchy>" << endl;
[564]3285
[508]3286        stream << "</Visibility_Solution>" << endl;
3287        stream.close();
3288
3289        cout << "finished" << endl;
3290
3291        return true;
[532]3292}
3293
3294
3295int VspBspViewCellsManager::CastBeam(Beam &beam)
3296{
[535]3297        return mVspBspTree->CastBeam(beam);
[532]3298}
[551]3299
3300
[587]3301void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
3302                                                                          const bool createMesh)
[551]3303{
[582]3304        CreateMesh(viewCell);
[551]3305
3306        float area = 0;
3307        float volume = 0;
3308
[580]3309        ViewCellContainer leaves;
[582]3310        mViewCellsTree->CollectLeaves(viewCell, leaves);
[580]3311
3312        ViewCellContainer::const_iterator it, it_end = leaves.end();
3313
3314        for (it = leaves.begin(); it != it_end; ++ it)
[551]3315        {
3316                BspNodeGeometry geom;
[580]3317                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
[551]3318                mVspBspTree->ConstructGeometry(leaf, geom);
3319
3320                area += geom.GetArea();
3321                volume += geom.GetVolume();
3322        }
3323
3324        viewCell->SetVolume(volume);
3325        viewCell->SetArea(area);
[563]3326}
[575]3327
3328
[577]3329void VspBspViewCellsManager::PrepareLoadedViewCells()
3330{
3331        // TODO: do I still need this here?
[590]3332        if (0)
[577]3333        mVspBspTree->RepairViewCellsLeafLists();
3334}
[575]3335
[577]3336
[580]3337
3338void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3339                                                                                                        vector<MergeCandidate> &candidates)
3340{       
3341        cout << "collecting merge candidates ... " << endl;
3342
3343        if (mUseRaysForMerge)
3344        {
3345                mVspBspTree->CollectMergeCandidates(rays, candidates);
3346        }
3347        else
3348        {
3349                vector<BspLeaf *> leaves;
3350                mVspBspTree->CollectLeaves(leaves);
3351                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3352        }
3353
3354        cout << "fininshed collecting candidates" << endl;
3355}
3356
3357
[590]3358void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
3359{
3360        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3361        for (it = mViewCells.begin(); it != it_end; ++ it)
3362        {
3363        }
3364}
[580]3365
3366//////////////////////////////////
[575]3367ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3368{
3369        //TODO
3370        return NULL;// new VspBspViewCellsManager();
3371}
[580]3372
Note: See TracBrowser for help on using the repository browser.