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

Revision 568, 60.9 KB checked in by mattausch, 18 years ago (diff)

debug version for testing shuffling and visualizing neighbors

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