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

Revision 465, 42.5 KB checked in by mattausch, 19 years ago (diff)

worked on vspkd leaves merge, implemented post merge collapse

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