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

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