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

Revision 561, 59.3 KB checked in by mattausch, 18 years ago (diff)

added flexible checkvalitity function for view cells

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