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

Revision 484, 52.3 KB checked in by mattausch, 19 years ago (diff)

work around preprocessor bug

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