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

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