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

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