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

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