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

Revision 563, 60.3 KB checked in by bittner, 18 years ago (diff)

rss sampling changes, preprocessor::GenerateRays?

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