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

Revision 453, 40.8 KB checked in by mattausch, 19 years ago (diff)
Line 
1#include "ViewCellsManager.h"
2#include "RenderSimulator.h"
3#include "Mesh.h"
4#include "Triangle3.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "X3dParser.h"
8#include "ViewCellBsp.h"
9#include "KdTree.h"
10#include "VspKdTree.h"
11#include "Exporter.h"
12#include "VspBspTree.h"
13
14
15ViewCellsManager::ViewCellsManager():
16mRenderSimulator(NULL),
17mConstructionSamples(0),
18mPostProcessSamples(0),
19mVisualizationSamples(0)
20{
21        // post processing stuff
22        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
23        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
24        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
25}
26
27ViewCellsManager::ViewCellsManager(int constructionSamples):
28mConstructionSamples(constructionSamples),
29mRenderSimulator(NULL),
30mPostProcessSamples(0),
31mVisualizationSamples(0)
32{
33        // post processing stuff
34        environment->GetIntValue("ViewCells.PostProcessing.minPvsDif", mMinPvsDif);
35        environment->GetIntValue("ViewCells.PostProcessing.minPvs", mMinPvs);
36        environment->GetIntValue("ViewCells.PostProcessing.maxPvs", mMaxPvs);
37}
38
39ViewCellsManager::~ViewCellsManager()
40{
41        DEL_PTR(mRenderSimulator);
42}
43
44void ViewCellsManager::InitRenderSimulator()
45{
46        float objRenderCost = 0, vcOverhead = 0, moveSpeed = 0;
47
48        environment->GetFloatValue("Simulation.objRenderCost",objRenderCost);
49        environment->GetFloatValue("Simulation.vcOverhead", vcOverhead);
50        environment->GetFloatValue("Simulation.moveSpeed", moveSpeed);
51
52        mRenderSimulator->SetObjectRenderCost(objRenderCost);
53        mRenderSimulator->SetVcOverhead(vcOverhead);
54        mRenderSimulator->SetMoveSpeed(moveSpeed);
55}
56
57bool ViewCellsManager::LoadViewCells(const string filename)
58{
59        X3dParser parser;
60       
61        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
62       
63        bool success = parser.ParseFile(filename, *this);
64        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
65
66        return success;
67}
68
69void ViewCellsManager::ComputeSampleContributions(const RayContainer &rays,
70                                                                                                  int &sampleContributions,
71                                                                                                  int &contributingSamples,
72                                                                                                  const bool castRays)
73{
74        // view cells not yet constructed
75        if (!ViewCellsConstructed())
76                return;
77
78        RayContainer::const_iterator it, it_end = rays.end();
79
80        sampleContributions = 0;
81        contributingSamples = 0;
82
83    for (it = rays.begin(); it != it_end; ++ it)
84        {
85                sampleContributions += ComputeSampleContributions(*(*it), castRays);
86                contributingSamples += sampleContributions > 0;
87        }
88}
89
90void ViewCellsManager::AddViewCell(ViewCell *viewCell)
91{
92        mViewCells.push_back(viewCell);
93}
94
95void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
96                                                                           ViewCellContainer &viewCells,
97                                                                           const int maxViewCells) const
98{
99        // maximal max viewcells
100        int limit = maxViewCells > 0 ?
101                Min((int)objects.size(), maxViewCells) : (int)objects.size();
102
103        for (int i = 0; i < limit; ++ i)
104        {
105                Intersectable *object = objects[i];
106               
107                // extract the mesh instances
108                if (object->Type() == Intersectable::MESH_INSTANCE)
109                {
110                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
111
112                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
113                        viewCells.push_back(viewCell);
114                }
115                //TODO: transformed meshes
116        }
117}
118
119ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
120                                                                                        const float height) const
121{
122        // one mesh per view cell
123        Mesh *mesh = new Mesh();
124       
125        //-- construct prism
126
127        // bottom
128        mesh->mFaces.push_back(new Face(2,1,0));
129        // top
130    mesh->mFaces.push_back(new Face(3,4,5));
131        // sides
132        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
133        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
134        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
135
136        //--- extrude new vertices for top of prism
137        Vector3 triNorm = baseTri.GetNormal();
138
139        Triangle3 topTri;       
140
141        // add base vertices and calculate top vertices
142        for (int i = 0; i < 3; ++ i)
143                mesh->mVertices.push_back(baseTri.mVertices[i]);
144       
145        // add top vertices     
146        for (int i = 0; i < 3; ++ i)
147                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
148       
149        mesh->Preprocess();
150
151        return GenerateViewCell(mesh);
152}
153
154ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
155{
156        ViewCell *vc = GenerateViewCell();
157        // merge pvs
158        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
159
160        // merge ray sets
161        stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
162        stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
163
164        std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
165                           back.mPiercingRays.begin(), back.mPiercingRays.end(),
166                           vc->mPiercingRays.begin());
167
168        return vc;
169}
170
171SimulationStatistics ViewCellsManager::SimulateRendering() const
172{
173        if (!ViewCellsConstructed() || !mRenderSimulator)
174                return SimulationStatistics();
175
176        return mRenderSimulator->SimulateRendering();
177}
178
179ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
180{
181        return new ViewCell(mesh);
182}
183
184
185void ViewCellsManager::SetVisualizationSamples(const int visSamples)
186{
187        mVisualizationSamples = visSamples;
188}
189
190void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
191{
192        mConstructionSamples = constructionSamples;
193}
194
195void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
196{
197        mPostProcessSamples = postProcessSamples;
198}
199
200int ViewCellsManager::GetVisualizationSamples() const
201{
202        return mVisualizationSamples;
203}
204
205int ViewCellsManager::GetConstructionSamples() const
206{
207        return mConstructionSamples;
208}
209
210int ViewCellsManager::GetPostProcessSamples() const
211{
212        return mPostProcessSamples;
213}
214
215/**********************************************************************/
216/*                   BspViewCellsManager implementation               */
217/**********************************************************************/
218
219BspViewCellsManager::BspViewCellsManager(BspTree *bspTree, int constructionSamples):
220ViewCellsManager(constructionSamples),
221mBspTree(bspTree)
222{
223   mRenderSimulator = new BspRenderSimulator(bspTree);
224   InitRenderSimulator();
225}
226
227bool BspViewCellsManager::ViewCellsConstructed() const
228{
229        return mBspTree->GetRoot() != NULL;
230}
231
232ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
233{
234        return new BspViewCell(mesh);
235}
236
237int BspViewCellsManager::Construct(const ObjectContainer &objects,
238                                                                   const VssRayContainer &rays,
239                                                                   AxisAlignedBox3 *sceneBbox)
240{
241        // if view cells were already constructed
242        if (ViewCellsConstructed())
243                return 0;
244
245        int sampleContributions = 0;
246       
247        RayContainer sampleRays;
248
249        int limit = min (mConstructionSamples, (int)rays.size());
250
251        // construct view cells using the collected samples
252        Debug << "construcing bsp view cells from "
253                  << limit << " samples " << endl;
254
255    for (int i = 0; i < limit; ++ i)
256                sampleRays.push_back(new Ray(*rays[i]));
257
258        if (mViewCells.empty()) // no view cells loaded
259                mBspTree->Construct(objects, sampleRays);
260        else
261                mBspTree->Construct(mViewCells);
262
263        Debug << mBspTree->GetStatistics() << endl;
264       
265        return sampleContributions;
266}
267
268int BspViewCellsManager::ComputeSampleContributions(Ray &ray, const bool castRay)
269{
270        // view cells not yet constructed
271        if (!ViewCellsConstructed())
272                return 0;
273
274        int contributingSamples = 0;
275
276        if (castRay)
277                mBspTree->CastRay(ray);
278       
279        //if (mBspTree->bspIntersections.empty()) return 0;
280
281        Intersectable *tObject =
282                !ray.intersections.empty() ? ray.intersections[0].mObject : NULL;
283
284        Intersectable *sObject = ray.sourceObject.mObject;
285
286        if (sObject || tObject)
287        {
288                // object can be seen from the view cell => add to view cell pvs
289                for (int j = 0; j < (int)ray.bspIntersections.size(); ++ j)
290                {       
291                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
292               
293                        // if ray not outside of view space
294                        if (leaf->GetViewCell() != mBspTree->GetRootCell())
295                        {
296                                if (sObject)
297                                {
298                                        contributingSamples +=
299                                                leaf->GetViewCell()->GetPvs().AddSample(sObject);
300                                }
301
302                                if (tObject)
303                                {
304                                        contributingSamples +=
305                                                leaf->GetViewCell()->GetPvs().AddSample(tObject);
306                                }
307                        }
308                }
309        }
310
311        // rays passing through this viewcell
312        if (0)
313                for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j)
314                {
315                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
316
317                        if (leaf->GetViewCell() != mBspTree->GetRootCell())
318                                leaf->GetViewCell()->
319                                        AddPassingRay(ray, contributingSamples ? 1 : 0);
320                }
321
322        return contributingSamples;
323}
324
325int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
326                                                                         const RayContainer &rays)
327{
328        if (!ViewCellsConstructed())
329        {
330                Debug << "view cells not constructed" << endl;
331                return 0;
332        }
333
334        //-- post processing of bsp view cells
335    int vcSize = 0;
336        int pvsSize = 0;
337
338        BspViewCellsStatistics vcStats;
339        mBspTree->EvaluateViewCellsStats(vcStats);
340        Debug << "original view cell partition:\n" << vcStats << endl;
341               
342        if (1) // export view cells before merge
343        {
344                cout << "exporting initial view cells (=leaves) ... ";
345                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
346       
347                if (exporter)
348                {
349                        exporter->SetWireframe();
350                        exporter->ExportBspLeaves(*mBspTree, vcStats.maxPvs);
351                        //exporter->ExportBspViewCellPartition(*mBspTree, 0);
352                               
353                        if (0)
354                        {
355                                Material m;//= RandomMaterial();
356                                m.mDiffuseColor = RgbColor(0, 1, 0);
357                                exporter->SetForcedMaterial(m);
358                                exporter->SetWireframe();
359
360                                exporter->ExportGeometry(objects);
361                        }
362
363                        delete exporter;
364                }
365                cout << "finished" << endl;
366
367                //-- render simulation
368                cout << "\nevaluating bsp view cells render time before merge ... ";
369                 
370                const SimulationStatistics ss = SimulateRendering();
371                         
372                cout << " finished" << endl;
373                cout << ss << endl;
374                Debug << ss << endl;
375        }
376
377
378        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
379
380        long startTime = GetTime();
381
382        //-- merge or subdivide view cells
383        int merged = 0;
384
385        RayContainer::const_iterator rit, rit_end = rays.end();
386        vector<Ray::BspIntersection>::const_iterator iit;
387
388        int limit = min((int)rays.size(), mPostProcessSamples);
389
390        for (int i = 0; i < limit; ++ i)
391        { 
392                Ray *ray = rays[i];
393
394                // traverse leaves stored in the rays and compare and merge consecutive
395                // leaves (i.e., the neighbors in the tree)
396                if (ray->bspIntersections.size() < 2)
397                        continue;
398
399                iit = ray->bspIntersections.begin();
400
401                BspLeaf *previousLeaf = (*iit).mLeaf;
402                ++ iit;
403               
404                for (; iit != ray->bspIntersections.end(); ++ iit)
405                {
406                        BspLeaf *leaf = (*iit).mLeaf;
407
408                        if (ShouldMerge(leaf, previousLeaf))
409                        {                       
410                                MergeBspLeafViewCells(leaf, previousLeaf);
411
412                                ++ merged;
413                        }
414               
415                        previousLeaf = leaf;
416                }
417        }
418
419        //-- stats and visualizations
420        cout << "finished" << endl;
421        cout << "merged " << merged << " view cells in "
422                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
423
424        return merged;
425}
426
427int BspViewCellsManager::GetType() const
428{
429        return BSP;
430}
431
432
433void BspViewCellsManager::Visualize(const ObjectContainer &objects,
434                                                                        const RayContainer &sampleRays)
435{
436        if (!ViewCellsConstructed())
437                return;
438
439        //-- recount pvs
440        BspViewCellsStatistics vcStats;
441        mBspTree->EvaluateViewCellsStats(vcStats);
442
443        if (1) // export view cells
444        {
445                cout << "exporting view cells after merge ... ";
446                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
447
448                if (exporter)
449                {
450                        exporter->ExportBspViewCellPartition(*mBspTree, vcStats.maxPvs);
451                        //exporter->ExportBspViewCellPartition(*mBspTree, 0);
452                        delete exporter;
453                }
454
455                cout << "finished" << endl;
456        }       
457
458        //-- visualization of the BSP splits
459        bool exportSplits = false;
460                environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
461       
462        if (exportSplits)
463        {
464                cout << "exporting splits ... ";
465                ExportSplits(objects, sampleRays);
466                cout << "finished" << endl;
467        }
468
469        ExportBspPvs(objects, sampleRays);
470}
471
472
473inline bool vc_gt(ViewCell *a, ViewCell *b)
474{
475        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
476}
477
478void BspViewCellsManager::ExportSplits(const ObjectContainer &objects,
479                                                                           const RayContainer &sampleRays)
480{
481        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
482
483        if (exporter)
484        {       
485                Material m;
486                m.mDiffuseColor = RgbColor(1, 0, 0);
487                exporter->SetForcedMaterial(m);
488                exporter->SetWireframe();
489                exporter->ExportBspSplits(*mBspTree, true);
490
491                // take forced material, else big scenes cannot be viewed
492                m.mDiffuseColor = RgbColor(0, 1, 0);
493                exporter->SetForcedMaterial(m);
494                exporter->SetFilled();
495
496                exporter->ResetForcedMaterial();
497               
498                // export rays
499                if (0)
500                {
501                        RayContainer outRays;
502               
503                        int raysSize = min((int)sampleRays.size(), mVisualizationSamples);
504
505                        for (int i = 0; i < raysSize; ++ i)
506                        {
507                                // only rays piercing geometry
508                                if (!sampleRays[i]->intersections.empty())
509                                        outRays.push_back(sampleRays[i]);
510                        }
511                       
512                        // export rays
513                        exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
514                }
515
516                if (0)
517                        exporter->ExportGeometry(objects);
518
519                delete exporter;
520        }
521}
522
523void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
524                                                                           const RayContainer &sampleRays)
525{
526        const int leafOut = 10;
527       
528        ViewCell::NewMail();
529
530        //-- some rays for output
531        const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
532        Debug << "visualization using " << raysOut << " samples" << endl;
533       
534
535        if (1)
536        {
537                //-- some random view cells and rays for output
538                vector<BspLeaf *> bspLeaves;
539
540                for (int i = 0; i < leafOut; ++ i)
541                        bspLeaves.push_back(mBspTree->GetRandomLeaf());
542               
543                for (int i = 0; i < bspLeaves.size(); ++ i)
544                {
545                        BspLeaf *leaf = bspLeaves[i];
546
547                        RayContainer vcRays;
548               
549                        cout << "creating output for view cell " << i << " ... ";
550
551                        // check whether we can add the current ray to the output rays
552                        for (int k = 0; k < raysOut; ++ k)
553                        {
554                                Ray *ray = sampleRays[k];
555
556                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
557                                {
558                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
559
560                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
561                                        {
562                                                vcRays.push_back(ray);
563                                        }
564                                }
565                        }
566
567            Intersectable::NewMail();
568
569                        BspViewCell *vc = dynamic_cast<BspViewCell *>(leaf->GetViewCell());
570
571                        //bspLeaves[j]->Mail();
572                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
573
574                        Exporter *exporter = Exporter::GetExporter(s);
575                        exporter->SetFilled();
576
577                        exporter->SetWireframe();
578                        //exporter->SetFilled();
579
580                        Material m;//= RandomMaterial();
581                        m.mDiffuseColor = RgbColor(1, 1, 0);
582                        exporter->SetForcedMaterial(m);
583
584                        if (vc->GetMesh())
585                                exporter->ExportViewCell(vc);
586                        else
587                        {
588                                PolygonContainer vcGeom;
589                                // export view cell geometry
590                                mBspTree->ConstructGeometry(vc, vcGeom);
591                                exporter->ExportPolygons(vcGeom);
592                                CLEAR_CONTAINER(vcGeom);
593                        }
594
595                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
596                                  << ", piercing rays=" << (int)vcRays.size() << endl;
597
598                        // export rays piercing this view cell
599                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0)); 
600                       
601                        m.mDiffuseColor = RgbColor(1, 0, 0);
602                        exporter->SetForcedMaterial(m);
603
604                        // exporter->SetWireframe();
605                        exporter->SetFilled();
606
607                        ViewCellPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
608                        // output PVS of view cell
609                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
610                        {
611                                Intersectable *intersect = (*it).first;
612                                if (!intersect->Mailed())
613                                {
614                                        exporter->ExportIntersectable(intersect);
615                                        intersect->Mail();
616                                }                       
617                        }
618
619                        DEL_PTR(exporter);
620                        cout << "finished" << endl;
621                }
622        }
623        else
624        {
625                ViewCellContainer viewCells;
626                RayContainer vcRays;
627
628                mBspTree->CollectViewCells(viewCells);
629                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
630
631                int limit = min(leafOut, (int)viewCells.size());
632               
633                for (int i = 0; i < limit; ++ i)
634                {
635                        cout << "creating output for view cell " << i << " ... ";
636                       
637            Intersectable::NewMail();
638                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
639
640                        cout << "creating output for view cell " << i << " ... ";
641                        // check whether we can add the current ray to the output rays
642                        for (int k = 0; k < raysOut; ++ k)
643                        {
644                                Ray *ray = sampleRays[k];
645
646                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
647                                {
648                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
649
650                                        if (vc == leaf->GetViewCell())
651                                        {
652                                                vcRays.push_back(ray);
653                                        }
654                                }
655                        }
656
657                        //bspLeaves[j]->Mail();
658                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
659
660                        Exporter *exporter = Exporter::GetExporter(s);
661                       
662                        exporter->SetWireframe();
663
664                        Material m;//= RandomMaterial();
665                        m.mDiffuseColor = RgbColor(0, 1, 0);
666                        exporter->SetForcedMaterial(m);
667
668                        if (vc->GetMesh())
669                                exporter->ExportViewCell(vc);
670                        else
671                        {
672                                PolygonContainer cell;
673                                // export view cell
674                                mBspTree->ConstructGeometry(vc, cell);
675                                exporter->ExportPolygons(cell);
676                                CLEAR_CONTAINER(cell);
677                        }
678
679                       
680                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
681                                  << ", piercing rays=" << (int)vcRays.size() << endl;
682
683                       
684                        // export rays piercing this view cell
685                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
686       
687                        m.mDiffuseColor = RgbColor(1, 0, 0);
688                        exporter->SetForcedMaterial(m);
689
690                        ViewCellPvsMap::const_iterator it,
691                                it_end = vc->GetPvs().mEntries.end();
692
693                        // output PVS of view cell
694                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
695                        {
696                                Intersectable *intersect = (*it).first;
697                                if (!intersect->Mailed())
698                                {
699                                        Material m = RandomMaterial();
700                       
701                                        exporter->SetForcedMaterial(m);
702
703                                        exporter->ExportIntersectable(intersect);
704                                        intersect->Mail();
705                                }                       
706                        }
707                               
708                        DEL_PTR(exporter);
709                        cout << "finished" << endl;
710                }
711        }
712}
713
714
715bool BspViewCellsManager::MergeBspLeafViewCells(BspLeaf *front, BspLeaf *back) const
716{
717        BspViewCell *viewCell =
718                dynamic_cast<BspViewCell *>(MergeViewCells(*front->GetViewCell(), *back->GetViewCell()));
719       
720        if (!viewCell)
721                return false;
722
723        // change view cells of all leaves associated with the
724        // previous view cells
725
726        BspViewCell *fVc = front->GetViewCell();
727        BspViewCell *bVc = back->GetViewCell();
728
729        vector<BspLeaf *> fLeaves = fVc->mBspLeaves;
730        vector<BspLeaf *> bLeaves = bVc->mBspLeaves;
731
732        vector<BspLeaf *>::const_iterator it;
733       
734        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
735        {
736                (*it)->SetViewCell(viewCell);
737                viewCell->mBspLeaves.push_back(*it);
738        }
739        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
740        {
741                (*it)->SetViewCell(viewCell);
742                viewCell->mBspLeaves.push_back(*it);
743        }
744       
745        DEL_PTR(fVc);
746        DEL_PTR(bVc);
747
748        return true;
749}
750
751bool BspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
752{
753        ViewCell *fvc = front->GetViewCell();
754        ViewCell *bvc = back->GetViewCell();
755
756        if ((fvc == mBspTree->GetRootCell()) || (bvc == mBspTree->GetRootCell()) || (fvc == bvc))
757                return false;
758
759        int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
760
761        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
762        {
763                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
764                        (bvc->GetPvs().GetSize() < mMinPvs) ||
765                        ((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
766                {
767                        return true;
768                }
769        }
770       
771        return false;
772}
773
774void BspViewCellsManager::PrintStatistics(ostream &s) const
775{
776        BspViewCellsStatistics vcStats;
777        mBspTree->EvaluateViewCellsStats(vcStats);
778        s << vcStats << endl;
779}
780
781/**********************************************************************/
782/*                   KdViewCellsManager implementation               */
783/**********************************************************************/
784
785KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
786ViewCellsManager(),
787mKdTree(kdTree),
788mKdPvsDepth(100)
789{
790   mRenderSimulator = new KdRenderSimulator(mKdTree);
791   InitRenderSimulator();
792}
793
794int KdViewCellsManager::Construct(const ObjectContainer &objects,
795                                                                  const VssRayContainer &rays,
796                                                                  AxisAlignedBox3 *sceneBbox)
797{
798        // if view cells already constructed
799        if (ViewCellsConstructed())
800                return 0;
801
802        Debug << "Constructing bsp view cells" << endl;
803       
804        mKdTree->Construct();
805
806        return 0;
807}
808
809bool KdViewCellsManager::ViewCellsConstructed() const
810{
811        return mKdTree->GetRoot() != NULL;
812}
813
814int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
815                                                                        const RayContainer &rays)
816{
817        return 0;
818}
819
820void KdViewCellsManager::Visualize(const ObjectContainer &objects,
821                                                                   const RayContainer &sampleRays)
822{
823        if (!ViewCellsConstructed())
824                return;
825
826        const int pvsOut = min((int)objects.size(), 10);
827
828        int limit = min(mVisualizationSamples, (int)sampleRays.size());
829
830        RayContainer *rays = new RayContainer[pvsOut];
831
832        for  (int i = 0; i < limit; ++ i)
833        {
834                Ray *ray = sampleRays[i];
835
836                if (!ray->intersections.empty())
837                {
838                        // check whether we can add this to the rays
839                        for (int j = 0; j < pvsOut; j++)
840                        {
841                                if (objects[j] == ray->intersections[0].mObject)
842                                {
843                                        rays[j].push_back(ray);
844                                }
845                        }
846                }
847        }
848
849        bool exportRays = false;
850        if (exportRays) {
851                Exporter *exporter = NULL;
852                exporter = Exporter::GetExporter("sample-rays.x3d");
853                exporter->SetWireframe();
854                exporter->ExportKdTree(*mKdTree);
855               
856                for (i=0; i < pvsOut; i++)
857                        exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
858                exporter->SetFilled();
859               
860                delete exporter;
861        }
862
863        for (int k=0; k < pvsOut; k++)
864        {
865                Intersectable *object = objects[k];
866                char s[64];     
867                sprintf(s, "sample-pvs%04d.x3d", k);
868
869                Exporter *exporter = Exporter::GetExporter(s);
870                exporter->SetWireframe();
871         
872        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
873                Intersectable::NewMail();
874                       
875                // avoid adding the object to the list
876                object->Mail();
877                ObjectContainer visibleObjects;
878           
879                for (; i != object->mKdPvs.mEntries.end(); i++)
880                {
881                         KdNode *node = (*i).first;
882                         exporter->ExportBox(mKdTree->GetBox(node));
883                         mKdTree->CollectObjects(node, visibleObjects);
884                }
885
886                exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
887                exporter->SetFilled();
888                 
889                for (int j = 0; j < visibleObjects.size(); j++)
890                        exporter->ExportIntersectable(visibleObjects[j]);
891                 
892                Material m;
893                m.mDiffuseColor = RgbColor(1, 0, 0);
894                exporter->SetForcedMaterial(m);
895                exporter->ExportIntersectable(object);
896         
897                delete exporter;
898        }
899        DEL_PTR(rays);
900}
901
902int KdViewCellsManager::GetType() const
903{
904        return ViewCellsManager::KD;
905}
906
907int KdViewCellsManager::ComputeSampleContributions(Ray &ray, const bool castRay)
908{
909        // view cells not yet constructed
910        if (!ViewCellsConstructed())
911                return 0;
912
913        if (castRay)
914                mKdTree->CastRay(ray);
915
916        if (ray.kdLeaves.empty())
917                return 0;
918
919        Intersectable *tObject =
920                !ray.intersections.empty() ? ray.intersections[0].mObject : NULL;
921
922        Intersectable *sObject =
923                ray.sourceObject.mObject;
924
925        int contributingSamples = 0;
926       
927        int objects = 0;
928
929        if (sObject)
930                objects++;
931        if (tObject)
932                objects++;
933
934        for (int j = 1; j < ((int)ray.kdLeaves.size() - 1); ++ j)
935        {
936                ray.kdLeaves[j]->AddPassingRay2(ray, objects,
937                                                                                (int)ray.kdLeaves.size());
938        }
939
940        if (!objects)
941                return 0;
942       
943        for (int j=0; j < ray.kdLeaves.size(); j++)
944        {
945                KdNode *node = GetNodeForPvs(ray.kdLeaves[j]);
946
947                if (sObject)
948                        contributingSamples += sObject->mKdPvs.AddSample(node);
949                if (tObject)
950                        contributingSamples += tObject->mKdPvs.AddSample(node);
951        }
952
953        return contributingSamples;
954}
955
956
957KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
958{
959        KdNode *node = leaf;
960
961        while (node->mParent && node->mDepth > mKdPvsDepth)
962                node = node->mParent;
963        return node;
964}
965
966
967void KdViewCellsManager::PrintStatistics(ostream &s) const
968{
969}
970
971/**********************************************************************/
972/*                   VspKdViewCellsManager implementation             */
973/**********************************************************************/
974
975VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree, int constructionSamples):
976ViewCellsManager(constructionSamples),
977mVspKdTree(vspKdTree)
978{
979   mRenderSimulator = new VspKdRenderSimulator(vspKdTree);
980   InitRenderSimulator();
981}
982
983int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
984                                                                         const VssRayContainer &rays,
985                                                                         AxisAlignedBox3 *sceneBbox)
986{
987        // if view cells already constructed
988        if (ViewCellsConstructed())
989                return 0;
990               
991        VssRayContainer sampleRays;
992
993        int limit = min (mConstructionSamples, (int)rays.size());
994
995    for (int i = 0; i < limit; ++ i)
996                sampleRays.push_back(rays[i]);
997
998        Debug << "constructing vsp kd tree using " << (int)sampleRays.size() << " samples" << endl;
999        mVspKdTree->Construct(rays, sceneBbox);
1000
1001        Debug << mVspKdTree->GetStatistics() << endl;
1002
1003        return 0;
1004}
1005
1006bool VspKdViewCellsManager::ViewCellsConstructed() const
1007{
1008        return mVspKdTree->GetRoot() != NULL;
1009}
1010
1011int VspKdViewCellsManager::ComputeSampleContributions(Ray &ray, const bool castRay)
1012{
1013        // view cells not yet constructed
1014        if (!ViewCellsConstructed())
1015                return 0;
1016
1017        //if (castRay)
1018                //mVspKdTree->CastRay(ray);
1019
1020        int sampleContributions = 0;
1021
1022        return sampleContributions;
1023}
1024
1025int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
1026                                                                           const RayContainer &rays)
1027{
1028        if (!ViewCellsConstructed())
1029                return 0;
1030
1031        return 0;
1032}
1033
1034void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1035                                                                          const RayContainer &sampleRays)
1036{
1037        if (!ViewCellsConstructed())
1038                return;
1039
1040        //-- export tree leaves
1041        if (1)
1042        {
1043                Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
1044                //exporter->SetWireframe();
1045                exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1046
1047                Debug << "average PVS size: " << mVspKdTree->GetAvgPvsSize() << endl;
1048
1049                if (0)
1050                        exporter->ExportGeometry(objects);
1051
1052                bool exportRays = false;
1053
1054                if (exportRays)
1055                {
1056                        int raysSize = 2000;
1057                        float prob = raysSize / (float)sampleRays.size();
1058               
1059                        exporter->SetWireframe();
1060                       
1061                        RayContainer rays;
1062               
1063                        for (int i = 0; i < sampleRays.size(); ++ i)
1064                        {
1065                                if (RandomValue(0,1) < prob)
1066                                        rays.push_back(sampleRays[i]);
1067                        }
1068
1069                        exporter->ExportRays(rays, 1000, RgbColor(1, 0, 0));
1070                }
1071
1072                delete exporter;
1073        }
1074
1075        if (1)
1076        {
1077                vector<VspKdTreeLeaf *> leafContainer;
1078
1079                mVspKdTree->CollectLeaves(leafContainer);
1080
1081                for (int i = 0; i < 10; ++ i)
1082                {
1083                        char s[64];
1084                        sprintf(s, "vsp_leaves%04d.x3d", i);
1085                        Exporter *exporter = Exporter::GetExporter(s);
1086
1087                        // export geometry
1088                        VspKdTreeLeaf *leaf = leafContainer[Random((int)leafContainer.size())];
1089                        AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
1090
1091                        Material m;
1092                        m.mDiffuseColor = RgbColor(0, 1, 1);
1093                        exporter->SetForcedMaterial(m);
1094                        exporter->SetWireframe();
1095                        exporter->ExportBox(box);
1096
1097                        //-- export stored rays
1098                        VssRayContainer vssRays;
1099                        leaf->GetRays(vssRays);
1100
1101                        VssRayContainer rays;
1102                        VssRayContainer::const_iterator it, it_end = vssRays.end();
1103
1104                        for (it = vssRays.begin(); it != it_end; ++ it)
1105                                rays.push_back(*it);
1106                       
1107                        exporter->ExportRays(rays, RgbColor(1, 0, 0));
1108
1109                        //-- export stored PVS
1110                        ObjectContainer pvsObj;
1111                        leaf->ExtractPvs(pvsObj);
1112                               
1113                        exporter->ExportGeometry(pvsObj);
1114
1115                        delete exporter;
1116                }                       
1117        }
1118}
1119
1120int VspKdViewCellsManager::GetType() const
1121{
1122        return VSP_KD;
1123}
1124
1125void VspKdViewCellsManager::PrintStatistics(ostream &s) const
1126{
1127}
1128
1129
1130/**********************************************************************/
1131/*                 VspBspViewCellsManager implementation              */
1132/**********************************************************************/
1133
1134VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
1135                                                                                           int constructionSamples):
1136ViewCellsManager(constructionSamples),
1137mVspBspTree(vspBspTree)
1138{
1139        mRenderSimulator = new VspBspRenderSimulator(vspBspTree);
1140        InitRenderSimulator();
1141}
1142
1143bool VspBspViewCellsManager::ViewCellsConstructed() const
1144{
1145        return mVspBspTree->GetRoot() != NULL;
1146}
1147
1148ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1149{
1150        return new BspViewCell(mesh);
1151}
1152
1153int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
1154                                                                          const VssRayContainer &rays,
1155                                                                          AxisAlignedBox3 *sceneBbox)
1156{
1157        // if view cells were already constructed
1158        if (ViewCellsConstructed())
1159                return 0;
1160
1161        Debug << "Constructing bsp view cells" << endl;
1162
1163        int sampleContributions = 0;
1164       
1165        VssRayContainer sampleRays;
1166
1167        int limit = min (mConstructionSamples, (int)rays.size());
1168
1169    for (int i = 0; i < limit; ++ i)
1170                sampleRays.push_back(rays[i]);
1171
1172        mVspBspTree->Construct(sampleRays);
1173       
1174        Debug << mVspBspTree->GetStatistics() << endl;
1175
1176        return sampleContributions;
1177}
1178
1179int VspBspViewCellsManager::ComputeSampleContributions(Ray &ray, const bool castRay)
1180{
1181        // view cells not yet constructed
1182        if (!ViewCellsConstructed())
1183                return 0;
1184
1185        int contributingSamples = 0;
1186
1187        if (castRay)
1188                mVspBspTree->CastRay(ray);
1189
1190        Intersectable *tObject =
1191                !ray.intersections.empty() ? ray.intersections[0].mObject : NULL;
1192
1193        Intersectable *sObject = ray.sourceObject.mObject;
1194
1195        if (sObject || tObject)
1196        {
1197                // object can be seen from the view cell => add to view cell pvs
1198                for (int j = 0; j < (int)ray.bspIntersections.size(); ++ j)
1199                {       
1200                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
1201               
1202                        // if ray not in unbounded space
1203                        if (leaf->GetViewCell() != mVspBspTree->GetRootCell())
1204                        {
1205                                if (sObject)
1206                                {
1207                                        contributingSamples +=
1208                                                leaf->GetViewCell()->GetPvs().AddSample(sObject);
1209                                }
1210
1211                                if (tObject)
1212                                {
1213                                        contributingSamples +=
1214                                                leaf->GetViewCell()->GetPvs().AddSample(tObject);
1215                                }
1216                        }
1217                }
1218        }
1219
1220        // rays passing through this viewcell
1221        if (0)
1222                for (int j = 1; j < ((int)ray.bspIntersections.size() - 1); ++ j)
1223                {
1224                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
1225
1226                        if (leaf->GetViewCell() != mVspBspTree->GetRootCell())
1227                                leaf->GetViewCell()->
1228                                        AddPassingRay(ray, contributingSamples ? 1 : 0);
1229                }
1230
1231        return contributingSamples;
1232}
1233
1234int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
1235                                                                                const RayContainer &rays)
1236{
1237        if (!ViewCellsConstructed())
1238        {
1239                Debug << "view cells not constructed" << endl;
1240                return 0;
1241        }
1242
1243
1244        //-- post processing of bsp view cells
1245    int vcSize = 0;
1246        int pvsSize = 0;
1247
1248       
1249        BspViewCellsStatistics vcStats;
1250        mVspBspTree->EvaluateViewCellsStats(vcStats);
1251        Debug << "original view cell partition:\n" << vcStats << endl;
1252               
1253        if (1) // export view cells
1254        {
1255                cout << "exporting initial view cells (=leaves) ... ";
1256                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
1257       
1258                if (exporter)
1259                {
1260                        exporter->SetWireframe();
1261                        exporter->ExportBspViewCellPartition(*mVspBspTree, vcStats.maxPvs);
1262                               
1263                        if (0)
1264                        {
1265                                Material m;
1266                                m.mDiffuseColor = RgbColor(0, 1, 0);
1267                                exporter->SetForcedMaterial(m);
1268                                exporter->SetWireframe();
1269
1270                                exporter->ExportGeometry(objects);
1271                        }
1272
1273                        delete exporter;
1274                }
1275                cout << "finished" << endl;
1276        }
1277
1278        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1279               
1280        long startTime = GetTime();
1281
1282
1283        //-- merge or subdivide view cells
1284        int merged = 0;
1285
1286        RayContainer::const_iterator rit, rit_end = rays.end();
1287        vector<Ray::BspIntersection>::const_iterator iit;
1288
1289        int limit = min((int)rays.size(), mPostProcessSamples);
1290
1291        for (int i = 0; i < limit; ++ i)
1292        { 
1293                Ray *ray = rays[i];
1294
1295                // traverse leaves stored in the rays and compare and merge consecutive
1296                // leaves (i.e., the neighbors in the tree)
1297                if (ray->bspIntersections.size() < 2)
1298                        continue;
1299
1300                iit = ray->bspIntersections.begin();
1301
1302                BspLeaf *previousLeaf = (*iit).mLeaf;
1303                ++ iit;
1304               
1305                for (; iit != ray->bspIntersections.end(); ++ iit)
1306                {
1307                        BspLeaf *leaf = (*iit).mLeaf;
1308
1309                        if (ShouldMerge(leaf, previousLeaf))
1310                        {                       
1311                                MergeVspBspLeafViewCells(leaf, previousLeaf);
1312
1313                                ++ merged;
1314                        }
1315               
1316                        previousLeaf = leaf;
1317                }
1318        }
1319
1320        //-- stats and visualizations
1321        cout << "finished" << endl;
1322        cout << "merged " << merged << " view cells in "
1323                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1324
1325
1326        return merged;
1327}
1328
1329int VspBspViewCellsManager::GetType() const
1330{
1331        return VSP_BSP;
1332}
1333
1334
1335void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
1336                                                                           const RayContainer &sampleRays)
1337{
1338        if (!ViewCellsConstructed())
1339                return;
1340
1341        //-- recount pvs
1342        BspViewCellsStatistics vcStats;
1343        mVspBspTree->EvaluateViewCellsStats(vcStats);
1344
1345        if (1) // export view cells
1346        {
1347                cout << "exporting view cells after merge ... ";
1348                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1349
1350                if (exporter)
1351                {
1352                        exporter->ExportBspViewCellPartition(*mVspBspTree, vcStats.maxPvs);
1353                        delete exporter;
1354                }
1355               
1356                cout << "finished" << endl;
1357        }       
1358
1359        //-- visualization of the BSP splits
1360        bool exportSplits = false;
1361        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1362       
1363        if (exportSplits)
1364        {
1365                cout << "exporting splits ... ";
1366                ExportSplits(objects, sampleRays);
1367                cout << "finished" << endl;
1368        }
1369
1370        ExportBspPvs(objects, sampleRays);
1371}
1372
1373
1374void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
1375                                                                                  const RayContainer &sampleRays)
1376{
1377        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1378
1379        if (exporter)
1380        {       
1381                Material m;
1382                m.mDiffuseColor = RgbColor(1, 0, 0);
1383                exporter->SetForcedMaterial(m);
1384                exporter->SetWireframe();
1385               
1386                exporter->ExportBspSplits(*mVspBspTree, true);
1387
1388                // take forced material, else big scenes cannot be viewed
1389                m.mDiffuseColor = RgbColor(0, 1, 0);
1390                exporter->SetForcedMaterial(m);
1391                exporter->SetFilled();
1392
1393                exporter->ResetForcedMaterial();
1394               
1395                // export rays
1396                if (0)
1397                {
1398                        RayContainer outRays;
1399               
1400                        int raysSize = min((int)sampleRays.size(), mVisualizationSamples);
1401
1402                        for (int i = 0; i < raysSize; ++ i)
1403                        {
1404                                // only rays piercing geometry
1405                                if (!sampleRays[i]->intersections.empty())
1406                                        outRays.push_back(sampleRays[i]);
1407                        }
1408                       
1409                        // export rays
1410                        exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
1411                }
1412
1413                if (0)
1414                        exporter->ExportGeometry(objects);
1415
1416                delete exporter;
1417        }
1418}
1419
1420void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
1421                                                                                  const RayContainer &sampleRays)
1422{
1423        const int leafOut = 10;
1424       
1425        ViewCell::NewMail();
1426
1427        //-- some rays for output
1428        const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1429        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1430       
1431        if (1)
1432        {
1433                //-- some random view cells and rays for output
1434                vector<BspLeaf *> vspBspLeaves;
1435
1436                for (int i = 0; i < leafOut; ++ i)
1437                        vspBspLeaves.push_back(mVspBspTree->GetRandomLeaf());   
1438               
1439                for (int i = 0; i < (int)vspBspLeaves.size(); ++ i)
1440                {
1441                        RayContainer vcRays;
1442                        cout << "creating output for view cell " << i << " ... ";
1443                       
1444                        // check whether we can add the current ray to the output rays
1445                        for (int k = 0; k < raysOut; ++ k)
1446                        {
1447                                Ray *ray = sampleRays[k];
1448
1449                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1450                                {
1451                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
1452
1453                                        if (vspBspLeaves[i]->GetViewCell() == leaf->GetViewCell())
1454                                        {
1455                                                vcRays.push_back(ray);
1456                                        }
1457                                }
1458                        }
1459                       
1460
1461                        Intersectable::NewMail();
1462
1463                        BspViewCell *vc = dynamic_cast<BspViewCell *>
1464                                (vspBspLeaves[i]->GetViewCell());
1465
1466                        //bspLeaves[j]->Mail();
1467                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1468
1469                        Exporter *exporter = Exporter::GetExporter(s);
1470                        exporter->SetFilled();
1471
1472                        ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
1473
1474                        exporter->SetWireframe();
1475                        //exporter->SetFilled();
1476
1477                        Material m;//= RandomMaterial();
1478                        m.mDiffuseColor = RgbColor(0, 1, 0);
1479                        exporter->SetForcedMaterial(m);
1480
1481                        if (vc->GetMesh())
1482                                exporter->ExportViewCell(vc);
1483                        else
1484                        {
1485                                PolygonContainer vcGeom;
1486
1487                                // export view cell geometry
1488                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1489                                exporter->ExportPolygons(vcGeom);
1490                                CLEAR_CONTAINER(vcGeom);
1491                        }
1492
1493                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1494                                        << ", piercing rays=" << (int)vcRays.size() << endl;
1495
1496                        // export rays piercing this view cell
1497                        exporter->ExportRays(vcRays, 1000, RgbColor(1, 0, 0));
1498                        exporter->ExportRays(vspBspLeaves[i]->mVssRays, RgbColor(1, 1, 1));
1499                       
1500                        m.mDiffuseColor = RgbColor(0, 1, 1);
1501                        exporter->SetForcedMaterial(m);
1502
1503                        exporter->SetWireframe();
1504                        //exporter->SetFilled();
1505
1506                        // output PVS of view cell
1507                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
1508                        {
1509                                Intersectable *intersect = (*it).first;
1510                                if (!intersect->Mailed())
1511                                {
1512                                        exporter->ExportIntersectable(intersect);
1513                                        intersect->Mail();
1514                                }                       
1515                        }
1516                               
1517                        // output rest of the objects
1518                        if (0)
1519                        {
1520                                Material m;//= RandomMaterial();
1521                                m.mDiffuseColor = RgbColor(0, 0, 1);
1522                                exporter->SetForcedMaterial(m);
1523
1524                                for (int j = 0; j < objects.size(); ++ j)
1525                                        if (!objects[j]->Mailed())
1526                                        {
1527                                                exporter->SetForcedMaterial(m);
1528                                                exporter->ExportIntersectable(objects[j]);
1529                                                objects[j]->Mail();
1530                                        }
1531                        }
1532                        DEL_PTR(exporter);
1533                        cout << "finished" << endl;
1534                }
1535        }
1536        else
1537        {
1538                ViewCellContainer viewCells;
1539
1540                mVspBspTree->CollectViewCells(viewCells);
1541                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
1542
1543                int limit = min(leafOut, (int)viewCells.size());
1544               
1545                for (int i = 0; i < limit; ++ i)
1546                {
1547                        cout << "creating output for view cell " << i << " ... ";
1548                        RayContainer vcRays;
1549            Intersectable::NewMail();
1550                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
1551
1552                        cout << "creating output for view cell " << i << " ... ";
1553                        // check whether we can add the current ray to the output rays
1554                        for (int k = 0; k < raysOut; ++ k)
1555                        {
1556                                Ray *ray = sampleRays[k];
1557
1558                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1559                                {
1560                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
1561
1562                                        if (vc == leaf->GetViewCell())
1563                                        {
1564                                                vcRays.push_back(ray);
1565                                        }
1566                                }
1567                        }
1568
1569                        //bspLeaves[j]->Mail();
1570                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1571
1572                        Exporter *exporter = Exporter::GetExporter(s);
1573                       
1574                        exporter->SetWireframe();
1575
1576                        Material m;//= RandomMaterial();
1577                        m.mDiffuseColor = RgbColor(0, 1, 0);
1578                        exporter->SetForcedMaterial(m);
1579
1580                        if (vc->GetMesh())
1581                                exporter->ExportViewCell(vc);
1582                        else
1583                        {
1584                                PolygonContainer vcGeom;
1585                                // export view cell
1586                                mVspBspTree->ConstructGeometry(vc, vcGeom);
1587                                exporter->ExportPolygons(vcGeom);
1588                                CLEAR_CONTAINER(vcGeom);
1589                        }
1590
1591                       
1592                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1593                                        << ", piercing rays=" << (int)vcRays.size() << endl;
1594
1595                       
1596                        // export rays piercing this view cell
1597                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1598       
1599                        m.mDiffuseColor = RgbColor(1, 0, 0);
1600                        exporter->SetForcedMaterial(m);
1601
1602                        ViewCellPvsMap::const_iterator it,
1603                                it_end = vc->GetPvs().mEntries.end();
1604
1605                        // output PVS of view cell
1606                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1607                        {
1608                                Intersectable *intersect = (*it).first;
1609
1610                                if (!intersect->Mailed())
1611                                {
1612                                        Material m = RandomMaterial();
1613                       
1614                                        exporter->SetForcedMaterial(m);
1615
1616                                        exporter->ExportIntersectable(intersect);
1617                                        intersect->Mail();
1618                                }                       
1619                        }
1620                               
1621                        DEL_PTR(exporter);
1622                        cout << "finished" << endl;
1623                }
1624        }
1625}
1626
1627
1628void VspBspViewCellsManager::PrintStatistics(ostream &s) const
1629{
1630        BspViewCellsStatistics vcStats;
1631        mVspBspTree->EvaluateViewCellsStats(vcStats);
1632        s << vcStats << endl;
1633}
1634
1635bool VspBspViewCellsManager::MergeVspBspLeafViewCells(BspLeaf *front,
1636                                                                                                          BspLeaf *back) const
1637{
1638        BspViewCell *viewCell =
1639                dynamic_cast<BspViewCell *>(MergeViewCells(*front->GetViewCell(),
1640                                                                                                   *back->GetViewCell()));
1641       
1642        if (!viewCell)
1643                return false;
1644
1645        // change view cells of all leaves associated with the
1646        // previous view cells
1647
1648        BspViewCell *fVc = front->GetViewCell();
1649        BspViewCell *bVc = back->GetViewCell();
1650
1651        vector<BspLeaf *> fLeaves = fVc->mBspLeaves;
1652        vector<BspLeaf *> bLeaves = bVc->mBspLeaves;
1653
1654        vector<BspLeaf *>::const_iterator it;
1655       
1656        for (it = fLeaves.begin(); it != fLeaves.end(); ++ it)
1657        {
1658                (*it)->SetViewCell(viewCell);
1659                viewCell->mBspLeaves.push_back(*it);
1660        }
1661        for (it = bLeaves.begin(); it != bLeaves.end(); ++ it)
1662        {
1663                (*it)->SetViewCell(viewCell);
1664                viewCell->mBspLeaves.push_back(*it);
1665        }
1666       
1667        DEL_PTR(fVc);
1668        DEL_PTR(bVc);
1669
1670        return true;
1671}
1672
1673bool VspBspViewCellsManager::ShouldMerge(BspLeaf *front, BspLeaf *back) const
1674{
1675        ViewCell *fvc = front->GetViewCell();
1676        ViewCell *bvc = back->GetViewCell();
1677
1678        if ((fvc == mVspBspTree->GetRootCell()) ||
1679                (bvc == mVspBspTree->GetRootCell()) ||
1680                (fvc == bvc))
1681                return false;
1682
1683        const int fdiff = fvc->GetPvs().Diff(bvc->GetPvs());
1684
1685        if (fvc->GetPvs().GetSize() + fdiff < mMaxPvs)
1686        {
1687                if ((fvc->GetPvs().GetSize() < mMinPvs) ||     
1688                        (bvc->GetPvs().GetSize() < mMinPvs) ||
1689                        ((fdiff < mMinPvsDif) && (bvc->GetPvs().Diff(fvc->GetPvs()) < mMinPvsDif)))
1690                {
1691                        return true;
1692                }
1693        }
1694       
1695        return false;
1696}
1697
Note: See TracBrowser for help on using the repository browser.