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

Revision 600, 80.7 KB checked in by mattausch, 18 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#include "ViewCellsParser.h"
14#include "Beam.h"
15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
17
18
19
20ViewCellsManager::ViewCellsManager():
21mRenderer(NULL),
22mInitialSamples(0),
23mConstructionSamples(0),
24mPostProcessSamples(0),
25mVisualizationSamples(0),
26mTotalAreaValid(false),
27mTotalArea(0.0f),
28mViewCellsFinished(false),
29mMaxPvsSize(9999999),
30mMinPvsSize(0), // one means only empty view cells are invalid
31mMaxPvsRatio(1.0)
32{
33        mViewSpaceBox.Initialize();
34        ParseEnvironment();
35
36        mViewCellsTree = new ViewCellsTree(this);
37}
38
39
40void ViewCellsManager::ParseEnvironment()
41{
42        // visualization stuff
43        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
44        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
45        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
46        bool emptyViewCells = false;
47        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", emptyViewCells);
48        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
49
50        environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
51        environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
52        environment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
53
54        environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
55
56        environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
57        environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
58       
59       
60        environment->GetIntValue("ViewCells.active", mNumActiveViewCells);
61        environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
62        environment->GetBoolValue("ViewCells.Visualization.useCuttingPlane", mUseCuttingPlaneForViz);
63
64        environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
65
66        mMinPvsSize = emptyViewCells ? 1 : 0;
67
68        char buf[50];
69        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
70
71        if (strcmp(buf, "PVS") == 0)
72                mColorCode = 1;
73        else if (strcmp(buf, "MergedLeaves") == 0)
74                mColorCode = 2;
75        else if (strcmp(buf, "MergedTreeDiff") == 0)
76                mColorCode = 3;
77        else
78                mColorCode = 0;
79
80        Debug << "colorCode: " << mColorCode << endl;
81}
82
83
84ViewCellsManager::~ViewCellsManager()
85{
86        DEL_PTR(mRenderer);
87
88        if (!ViewCellsTreeConstructed())
89                CLEAR_CONTAINER(mViewCells);
90        else
91                DEL_PTR(mViewCellsTree);
92
93        CLEAR_CONTAINER(mMeshContainer);
94}
95
96
97int ViewCellsManager::CastPassSamples(const int samplesPerPass,
98                                                                          const int sampleType,
99                                                                          VssRayContainer &passSamples) const
100{
101        SimpleRayContainer simpleRays;
102
103        preprocessor->GenerateRays(samplesPerPass,
104                                                           sampleType,
105                                                           simpleRays);
106
107        // shoot simple ray and add it to importance samples
108        preprocessor->CastRays(simpleRays, passSamples);
109
110        return (int)passSamples.size();
111}
112
113
114/// helper function which destroys rays or copies them into the output ray container
115inline void addOutRays(VssRayContainer &rays, VssRayContainer *outRays)
116{
117        cout << "disposing samples ... ";
118        long startTime = GetTime();
119        int n = (int)rays.size();
120
121        if (outRays)
122        {
123                VssRayContainer::const_iterator it, it_end = rays.end();
124
125                for (it = rays.begin(); it != it_end; ++ it)
126                {
127                        outRays->push_back(*it);
128                }
129        }
130        else
131        {
132                CLEAR_CONTAINER(rays);
133        }
134        cout << "finished" << endl;
135        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
136}
137
138
139int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
140{
141        int numSamples = 0;
142        SimpleRayContainer simpleRays;
143       
144        VssRayContainer initialSamples;
145
146        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
147        //-- construction rays => we use uniform samples for this
148        CastPassSamples(mInitialSamples,
149                                        //Preprocessor::DIRECTION_BASED_DISTRIBUTION,
150                                        Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION,
151                                        initialSamples);
152       
153        cout << "finished" << endl;
154
155        // construct view cells
156        const int numInitialSamples =
157                ConstructSubdivision(preprocessor->mObjects, initialSamples);
158
159        numSamples += numInitialSamples;
160
161        // rays can be passed or deleted
162        addOutRays(initialSamples, outRays);
163       
164
165        //-- guided rays are used for further sampling
166        const int n = mConstructionSamples; //+initialSamples;
167
168        bool dirSamples = false;
169
170        while (numSamples < n)
171        {
172                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
173                VssRayContainer constructionSamples;
174
175                const int samplingType =
176                        dirSamples ?
177                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
178                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
179
180                if (0)
181                dirSamples = !dirSamples; // toggle sampling method
182                numSamples += CastPassSamples(mSamplesPerPass,
183                                                                          samplingType,
184                                                                          constructionSamples);
185
186                cout << "finished" << endl;
187
188                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
189
190                // TODO: leak?
191                ComputeSampleContributions(constructionSamples, true, false);
192                cout << "finished" << endl;
193
194
195                addOutRays(constructionSamples, outRays);
196
197                cout << "total samples: " << numSamples << endl;
198        }
199       
200
201        //-- post processing
202        VssRayContainer postProcessSamples;
203
204        //-- construction rays => we use uniform samples for this
205        CastPassSamples(mPostProcessSamples,
206                                    Preprocessor::DIRECTION_BASED_DISTRIBUTION,
207                                        postProcessSamples);
208       
209        cout << "starting post processing and visualization" << endl;
210
211        // store viewCells for postprocessing
212        const bool storeViewCells = true;
213        ComputeSampleContributions(postProcessSamples, true, storeViewCells);
214        // merge the view cells
215        PostProcess(preprocessor->mObjects, postProcessSamples);
216
217
218        //-- visualization
219        VssRayContainer visualizationSamples;
220
221        //-- construction rays => we use uniform samples for this
222        CastPassSamples(mVisualizationSamples,
223                                    Preprocessor::DIRECTION_BASED_DISTRIBUTION,
224                                        visualizationSamples);
225
226        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
227
228        //Debug << "visualizationsamples: " << mVisualizationSamples << " " << visualizationSamples.size() << endl;
229        // different visualizations
230        Visualize(preprocessor->mObjects, visualizationSamples);
231
232        addOutRays(visualizationSamples, outRays);
233
234        return numSamples;
235}
236
237
238bool ViewCellsManager::CheckValidity(ViewCell *vc,
239                                                                         int minPvsSize,
240                                                                         int maxPvsSize) const
241{
242
243  if ((vc->GetPvs().GetSize() > maxPvsSize) ||
244          (vc->GetPvs().GetSize() < minPvsSize))
245        {
246          return false;
247        }
248
249  return true;
250}
251
252
253bool ViewCellsManager::ViewCellsTreeConstructed() const
254{
255        return mViewCellsTree->GetRoot();
256}
257
258
259void ViewCellsManager::SetValidity(ViewCell *vc,
260                                                                   int minPvs,
261                                                                   int maxPvs) const
262{
263        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
264}
265
266
267void
268ViewCellsManager::SetValidity(
269                                                          int minPvsSize,
270                                                          int maxPvsSize) const
271{
272  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
273
274  for (it = mViewCells.begin(); it != it_end; ++ it) {
275        SetValidity(*it, minPvsSize, maxPvsSize);
276  }
277}
278
279void
280ViewCellsManager::SetValidityPercentage(
281                                                                                const float minValid,
282                                                                                const float maxValid
283                                                                                )
284{
285  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
286
287  int start = mViewCells.size()*minValid;
288  int end = mViewCells.size()*maxValid;
289
290  for (int i=0; i < mViewCells.size(); i++)
291        mViewCells[i]->SetValid(i >= start && i <= end);
292}
293
294int
295ViewCellsManager::CountValidViewcells() const
296{
297  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
298  int valid = 0;
299  for (it = mViewCells.begin(); it != it_end; ++ it) {
300        if ((*it)->GetValid())
301          valid++;
302  }
303  return valid;
304}
305
306
307bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
308{
309        X3dParser parser;
310
311        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
312
313        bool success = parser.ParseFile(filename, *this);
314        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
315
316        return success;
317}
318
319
320bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
321{
322        viewPoint = mViewSpaceBox.GetRandomPoint();
323
324        return true;
325}
326
327
328float ViewCellsManager::GetViewSpaceVolume()
329{
330        return mViewSpaceBox.GetVolume()*(2.0f*sqr((float)M_PI));
331}
332
333
334bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
335{
336  if (!ViewCellsConstructed())
337        return mViewSpaceBox.IsInside(viewPoint);
338  else {
339        if (!mViewSpaceBox.IsInside(viewPoint))
340          return false;
341        ViewCell *viewcell = GetViewCell(viewPoint);
342        if (!viewcell || !viewcell->GetValid())
343          return false;
344  }
345  return true;
346}
347
348
349float
350ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
351                                                                                         const bool addRays,
352                                                                                         const bool storeViewCells
353                                                                                         )
354{
355  // view cells not yet constructed
356  if (!ViewCellsConstructed())
357        return 0.0f;
358
359  VssRayContainer::const_iterator it, it_end = rays.end();
360
361  float sum = 0.0f;
362  for (it = rays.begin(); it != it_end; ++ it) {
363        sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
364        //ComputeSampleContributions(*(*it), addRays);
365        //      sum += (*it)->mPvsContribution;
366  }
367  return sum;
368}
369
370
371void ViewCellsManager::EvaluateViewCellsStats()
372{
373        mViewCellsStats.Reset();
374
375        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
376
377        for (it = mViewCells.begin(); it != it_end; ++ it)
378        {
379                (*it)->UpdateViewCellsStats(mViewCellsStats);
380        }
381}
382
383
384void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
385                                                                                                float &expectedRenderCost,
386                                                                                                float &deviation,
387                                                                                                float &variance,
388                                                                                                int &totalPvs,
389                                                                                                float &avgRenderCost)
390{
391        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
392
393
394        //-- compute expected value
395
396        totalRenderCost = 0;
397        totalPvs = 0;
398
399        for (it = mViewCells.begin(); it != it_end; ++ it)
400        {
401                ViewCell *vc = *it;
402                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
403                totalPvs += (int)vc->GetPvs().GetSize();
404        }
405
406        // normalize with view space box
407        totalRenderCost /= mViewSpaceBox.GetVolume();
408        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
409        avgRenderCost = totalPvs / (float)mViewCells.size();
410
411
412        //-- compute standard defiation
413        variance = 0;
414        deviation = 0;
415
416        for (it = mViewCells.begin(); it != it_end; ++ it)
417        {
418                ViewCell *vc = *it;
419
420                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
421                float dev;
422
423                if (1)
424                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
425                else
426                        dev = fabs(expectedRenderCost - renderCost);
427
428                deviation += dev;
429                variance += dev * dev;
430        }
431
432        variance /= (float)mViewCells.size();
433        deviation /= (float)mViewCells.size();
434}
435
436
437
438void ViewCellsManager::AddViewCell(ViewCell *viewCell)
439{
440        mViewCells.push_back(viewCell);
441}
442
443
444float ViewCellsManager::GetArea(ViewCell *viewCell) const
445{
446        return viewCell->GetArea();
447}
448
449
450float ViewCellsManager::GetVolume(ViewCell *viewCell) const
451{
452        return viewCell->GetVolume();
453}
454
455
456void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
457                                                                           ViewCellContainer &viewCells,
458                                                                           const int maxViewCells) const
459{
460        // maximal max viewcells
461        int limit = maxViewCells > 0 ?
462                Min((int)objects.size(), maxViewCells) : (int)objects.size();
463
464        for (int i = 0; i < limit; ++ i)
465        {
466                Intersectable *object = objects[i];
467
468                // extract the mesh instances
469                if (object->Type() == Intersectable::MESH_INSTANCE)
470                {
471                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
472
473                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
474                        viewCells.push_back(viewCell);
475                }
476                //TODO: transformed meshes
477        }
478}
479
480
481ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
482                                                                                        const float height) const
483{
484        // one mesh per view cell
485        Mesh *mesh = new Mesh();
486
487        //-- construct prism
488
489        // bottom
490        mesh->mFaces.push_back(new Face(2,1,0));
491        // top
492    mesh->mFaces.push_back(new Face(3,4,5));
493        // sides
494        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
495        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
496        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
497
498        //--- extrude new vertices for top of prism
499        Vector3 triNorm = baseTri.GetNormal();
500
501        Triangle3 topTri;
502
503        // add base vertices and calculate top vertices
504        for (int i = 0; i < 3; ++ i)
505                mesh->mVertices.push_back(baseTri.mVertices[i]);
506
507        // add top vertices
508        for (int i = 0; i < 3; ++ i)
509                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
510
511        mesh->Preprocess();
512
513        return GenerateViewCell(mesh);
514}
515
516
517void ViewCellsManager::FinalizeViewCells(const bool createMesh)
518{
519        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
520        for (it = mViewCells.begin(); it != it_end; ++ it)
521        {
522                Finalize(*it, createMesh);
523        }
524
525        mTotalAreaValid = false;
526}
527
528
529void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
530{
531        // implemented in subclasses
532}
533
534
535ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
536{
537        // generate parent view cell
538        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
539
540        // merge pvs
541        vc->GetPvs().Merge(left->GetPvs(), right->GetPvs());
542
543        //-- merge ray sets
544        if (0)
545        {
546                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
547                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
548
549                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
550                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
551                                   vc->mPiercingRays.begin());
552        }
553
554
555        vc->SetupChildLink(left);
556        vc->SetupChildLink(right);
557
558
559        return vc;
560}
561
562
563ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
564{
565        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
566
567        ViewCellContainer::const_iterator it, it_end = children.end();
568
569        for (it = children.begin(); it != it_end; ++ it)
570        {
571                // merge pvs
572                vc->GetPvs().Merge(vc->GetPvs(), (*it)->GetPvs());
573
574                vc->SetupChildLink(*it);
575        }
576
577        return vc;
578}
579
580
581void ViewCellsManager::SetRenderer(Renderer *renderer)
582{
583        mRenderer = renderer;
584}
585
586
587ViewCellsTree *ViewCellsManager::GetViewCellsTree()
588{
589        return mViewCellsTree;
590}
591
592
593void ViewCellsManager::SetVisualizationSamples(const int visSamples)
594{
595        mVisualizationSamples = visSamples;
596}
597
598
599void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
600{
601        mConstructionSamples = constructionSamples;
602}
603
604
605void ViewCellsManager::SetInitialSamples(const int initialSamples)
606{
607        mInitialSamples = initialSamples;
608}
609
610
611void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
612{
613        mPostProcessSamples = postProcessSamples;
614}
615
616
617int ViewCellsManager::GetVisualizationSamples() const
618{
619        return mVisualizationSamples;
620}
621
622
623int ViewCellsManager::GetConstructionSamples() const
624{
625        return mConstructionSamples;
626}
627
628
629int ViewCellsManager::GetPostProcessSamples() const
630{
631        return mPostProcessSamples;
632}
633
634
635void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
636{
637  ViewCellContainer::const_iterator it = mViewCells.begin();
638  stat.viewcells = 0;
639  stat.minPvs = 100000000;
640  stat.maxPvs = 0;
641  stat.avgPvs = 0.0f;
642
643  for (; it != mViewCells.end(); ++it) {
644        ViewCell *viewcell = *it;
645        int pvsSize = viewcell->GetPvs().GetSize();
646        if ( pvsSize < stat.minPvs)
647          stat.minPvs = pvsSize;
648        if (pvsSize > stat.maxPvs)
649          stat.maxPvs = pvsSize;
650        stat.avgPvs += pvsSize;
651        stat.viewcells++;
652  }
653  if (stat.viewcells)
654        stat.avgPvs/=stat.viewcells;
655}
656
657
658void ViewCellsManager::PrintPvsStatistics(ostream &s)
659{
660  s<<"############# Viewcell PVS STAT ##################\n";
661  PvsStatistics pvsStat;
662  GetPvsStatistics(pvsStat);
663  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
664  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
665  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
666}
667
668
669int ViewCellsManager::CastBeam(Beam &beam)
670{
671        return 0;
672}
673
674
675ViewCellContainer &ViewCellsManager::GetViewCells()
676{
677        return mViewCells;
678}
679
680
681void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
682{
683        mViewSpaceBox = box;
684
685        CreateCuttingPlane();
686       
687        mTotalAreaValid = false;
688}
689
690
691void ViewCellsManager::CreateCuttingPlane()
692{
693        int axis = 0;
694
695        const float factor = 0.35;
696        Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * factor;
697
698        if (mUseCuttingPlaneForViz)
699        environment->GetIntValue("ViewCells.Visualization.cuttingPlaneAxis", axis);
700
701        Vector3 normal(0,0,0);
702        normal[axis] = 1;
703
704        mCuttingPlane = Plane3(normal, point);
705}
706
707
708AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
709{
710        return mViewSpaceBox;
711}
712
713
714void ViewCellsManager::ResetViewCells()
715{
716        mViewCells.clear();
717       
718        CollectViewCells();
719       
720        mViewCellsStats.Reset();
721        EvaluateViewCellsStats();
722
723        // has to be recomputed
724        mTotalAreaValid = false;
725}
726
727
728int ViewCellsManager::GetMaxPvsSize() const
729{
730        return mMaxPvsSize;
731}
732
733
734void
735ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
736{
737  if (!ViewCellsConstructed())
738        return;
739
740  VssRayContainer::const_iterator it, it_end = rays.end();
741
742  for (it = rays.begin(); it != it_end; ++ it) {
743        AddSampleContributions(*(*it));
744  }
745}
746
747
748int ViewCellsManager::GetMinPvsSize() const
749{
750        return mMinPvsSize;
751}
752
753
754
755float ViewCellsManager::GetMaxPvsRatio() const
756{
757        return mMaxPvsRatio;
758}
759
760
761void
762ViewCellsManager::AddSampleContributions(VssRay &ray)
763{
764  // assumes viewcells have been stored...
765  ViewCellContainer *viewcells = &ray.mViewCells;
766  ViewCellContainer::const_iterator it;
767  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
768        ViewCell *viewcell = *it;
769        if (viewcell->GetValid()) {
770          // if ray not outside of view space
771          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
772        }
773  }
774}
775
776
777float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
778                                                                                                   const bool addRays,
779                                                                                                   const bool storeViewCells)
780{
781        ViewCellContainer viewcells;
782
783        ray.mPvsContribution = 0;
784        ray.mRelativePvsContribution = 0.0f;
785
786        static Ray hray;
787        hray.Init(ray);
788        //hray.mFlags |= Ray::CULL_BACKFACES;
789        //Ray hray(ray);
790
791        float tmin = 0, tmax = 1.0;
792
793        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
794                return 0;
795
796        Vector3 origin = hray.Extrap(tmin);
797        Vector3 termination = hray.Extrap(tmax);
798
799        CastLineSegment(origin, termination, viewcells);
800        //Debug << "constribution: " << (int)viewcells.size() << endl;
801
802        // copy viewcells memory efficiently
803        //const bool storeViewcells = !addRays;
804
805        if (storeViewCells)
806        {
807                ray.mViewCells.reserve(viewcells.size());
808                ray.mViewCells = viewcells;
809        }
810
811        ViewCellContainer::const_iterator it = viewcells.begin();
812
813
814  for (; it != viewcells.end(); ++it) {
815        ViewCell *viewcell = *it;
816        if (viewcell->GetValid()) {
817          // if ray not outside of view space
818          float contribution;
819          if (viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
820                                                                                                   ray.mPdf,
821                                                                                                   contribution
822                                                                                                   ))
823                ray.mPvsContribution++;
824          ray.mRelativePvsContribution += contribution;
825        }
826  }
827
828  if (addRays)
829        for (it = viewcells.begin(); it != viewcells.end(); ++it) {
830          ViewCell *viewcell = *it;
831          if (viewcell->GetValid()) {
832                // if ray not outside of view space
833                viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
834          }
835        }
836
837        return ray.mRelativePvsContribution;
838}
839
840
841void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
842                                                                  const int maxSize,
843                                                                  VssRayContainer &usedRays,
844                                                                  VssRayContainer *savedRays) const
845{
846        const int limit = min(maxSize, (int)sourceRays.size());
847        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
848
849        VssRayContainer::const_iterator it, it_end = sourceRays.end();
850        for (it = sourceRays.begin(); it != it_end; ++ it)
851        {
852                if (Random(1.0f) < prop)
853                        usedRays.push_back(*it);
854                else if (savedRays)
855                        savedRays->push_back(*it);
856        }
857}
858
859
860float ViewCellsManager::GetAccVcArea()
861{
862        // if already computed
863        if (mTotalAreaValid)
864                return mTotalArea;
865
866        mTotalArea = 0;
867        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
868
869        for (it = mViewCells.begin(); it != it_end; ++ it)
870        {
871                //Debug << "area: " << GetArea(*it);
872        mTotalArea += GetArea(*it);
873        }
874
875        mTotalAreaValid = true;
876
877        return mTotalArea;
878}
879
880
881void ViewCellsManager::PrintStatistics(ostream &s) const
882{
883        s << mViewCellsStats << endl;
884}
885
886
887void ViewCellsManager::CreateUniqueViewCellIds()
888{
889        for (int i = 0; i < (int)mViewCells.size(); ++ i)
890                mViewCells[i]->SetId(i);
891}
892
893
894void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
895{
896        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
897
898        for (it = mViewCells.begin(); it != it_end; ++ it)
899        {
900                if (!mOnlyValidViewCells || (*it)->GetValid())
901                {
902                        ExportColor(exporter, *it);             
903                        ExportViewCellGeometry(exporter, *it,
904                                mUseCuttingPlaneForViz ? &mCuttingPlane : NULL);
905                }
906        }
907
908}
909
910
911void ViewCellsManager::CreateViewCellMeshes()
912{
913        // convert to meshes
914        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
915
916        for (it = mViewCells.begin(); it != it_end; ++ it)
917        {
918                if (!(*it)->GetMesh())
919                        CreateMesh(*it);
920        }
921}
922
923
924bool ViewCellsManager::ExportViewCells(const string filename)
925{
926        return false;
927}
928
929
930void ViewCellsManager::ExportViewCell(ViewCell *viewCell, ofstream &stream)
931{
932        stream << "<ViewCell id=\"" << viewCell->GetId() << "\" ";
933        stream << "pvs=\"";
934
935        ObjectPvsMap::iterator it, it_end = viewCell->GetPvs().mEntries.end();
936        if(0) // test with empty pvs
937        for (it = viewCell->GetPvs().mEntries.begin(); it != it_end; ++ it)
938        {
939                stream << (*it).first->GetId() << " ";
940        }
941
942        stream << "\" />" << endl;
943}
944
945
946/**********************************************************************/
947/*                   BspViewCellsManager implementation               */
948/**********************************************************************/
949
950
951BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
952ViewCellsManager(), mBspTree(bspTree)
953{
954        environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
955        mBspTree->SetViewCellsManager(this);
956        mBspTree->mViewCellsTree = mViewCellsTree;
957}
958
959
960bool BspViewCellsManager::ViewCellsConstructed() const
961{
962        return mBspTree->GetRoot() != NULL;
963}
964
965
966ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
967{
968        return new BspViewCell(mesh);
969}
970
971
972int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
973                                                                                          const VssRayContainer &rays)
974{
975        // if view cells were already constructed
976        if (ViewCellsConstructed())
977                return 0;
978
979        int sampleContributions = 0;
980
981        // construct view cells using the collected samples
982        RayContainer constructionRays;
983        VssRayContainer savedRays;
984
985        const int limit = min(mInitialSamples, (int)rays.size());
986
987        VssRayContainer::const_iterator it, it_end = rays.end();
988
989        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
990
991        for (it = rays.begin(); it != it_end; ++ it)
992        {
993                if (Random(1.0f) < prop)
994                        constructionRays.push_back(new Ray(*(*it)));
995                else
996                        savedRays.push_back(*it);
997        }
998
999    if (mViewCells.empty())
1000        {
1001                // no view cells loaded
1002                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
1003                // collect final view cells
1004                mBspTree->CollectViewCells(mViewCells);
1005        }
1006        else
1007        {
1008                mBspTree->Construct(mViewCells);
1009        }
1010
1011        // destroy rays created only for construction
1012        CLEAR_CONTAINER(constructionRays);
1013
1014        Debug << mBspTree->GetStatistics() << endl;
1015
1016        //EvaluateViewCellsStats();
1017        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1018
1019        // recast rest of the rays
1020        ComputeSampleContributions(savedRays, true, false);
1021
1022
1023        ResetViewCells();
1024   
1025        Debug << "\nView cells after " << (int)savedRays.size()
1026                  << " samples:\n" << mViewCellsStats << endl;
1027
1028        if (1) // export initial view cells
1029        {
1030                cout << "exporting initial view cells (=leaves) ... ";
1031                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
1032
1033                if (exporter)
1034                {
1035                       
1036                        if (0 && mExportRays)
1037                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
1038
1039                       
1040                        if (mExportGeometry)
1041                                exporter->ExportGeometry(objects);
1042
1043                        //exporter->SetWireframe();
1044                        exporter->SetFilled();
1045                        ExportViewCellsForViz(exporter);
1046
1047
1048                        delete exporter;
1049                }
1050                cout << "finished" << endl;
1051        }
1052
1053
1054        return sampleContributions;
1055}
1056
1057
1058void BspViewCellsManager::CollectViewCells()
1059{
1060        // view cells tree constructed
1061        if (!ViewCellsTreeConstructed())
1062        {               
1063                mBspTree->CollectViewCells(mViewCells);
1064        }
1065        else
1066        {
1067                // we can use the view cells tree hierarchy to get the right set
1068                mViewCellsTree->CollectBestViewCellSet(mViewCells,
1069                                                                                           mNumActiveViewCells);
1070        }
1071}
1072
1073
1074float BspViewCellsManager::GetProbability(ViewCell *viewCell)
1075{
1076        // compute view cell area as subsititute for probability
1077        if (1)
1078                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1079        else
1080                return GetArea(viewCell) / GetAccVcArea();
1081}
1082
1083
1084float BspViewCellsManager::GetRendercost(ViewCell *viewCell,
1085                                                                                 float objRendercost) const
1086{
1087        return viewCell->GetPvs().GetSize() * objRendercost;
1088}
1089
1090
1091int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1092                                                                                 const Vector3 &termination,
1093                                                                                 ViewCellContainer &viewcells)
1094{
1095        return mBspTree->CastLineSegment(origin, termination, viewcells);
1096}
1097
1098
1099int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
1100                                                                         const VssRayContainer &rays)
1101{
1102        if (!ViewCellsConstructed())
1103        {
1104                Debug << "view cells not constructed" << endl;
1105                return 0;
1106        }
1107
1108       
1109        // view cells already finished before post processing step (i.e. because they were loaded)
1110        if (mViewCellsFinished)
1111        {
1112                FinalizeViewCells(true);
1113                EvaluateViewCellsStats();
1114
1115                return 0;
1116        }
1117
1118        //-- post processing of bsp view cells
1119
1120    int vcSize = 0;
1121        int pvsSize = 0;
1122
1123        EvaluateViewCellsStats();
1124        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
1125
1126        mRenderer->RenderScene();
1127        SimulationStatistics ss;
1128        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1129
1130    Debug << ss << endl;
1131
1132       
1133
1134        //-- merge view cells
1135        int merged;
1136       
1137        if (mMergeViewCells)
1138        {
1139                cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1140                long startTime = GetTime();
1141       
1142                VssRayContainer postProcessRays;
1143                GetRaySets(rays, mPostProcessSamples, postProcessRays);
1144
1145                merged = mViewCellsTree->ConstructMergeTree(rays, objects);
1146
1147                //-- stats and visualizations
1148                cout << "finished" << endl;
1149                cout << "merged " << merged << " view cells in "
1150                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1151
1152                Debug << "Postprocessing: Merged " << merged << " view cells in "
1153                        << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
1154                        << "using " << (int)rays.size() << " samples" << endl << endl;
1155        }
1156
1157    // reset view cells and stats
1158        ResetViewCells();
1159
1160        int savedColorCode  = mColorCode;
1161
1162        //BspLeaf::NewMail();
1163        if (1) // export merged view cells
1164        {
1165                mColorCode = 0;
1166                cout << "reseting view cells ... ";
1167                ResetViewCells();
1168                cout << "finished" << endl;
1169
1170                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1171                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
1172
1173                cout << "exporting view cells after merge ... ";
1174
1175                if (exporter)
1176                {
1177                        if (mExportGeometry)
1178                                exporter->ExportGeometry(objects);
1179
1180                        //exporter->SetWireframe();
1181                        exporter->SetFilled();
1182                        ExportViewCellsForViz(exporter);
1183
1184
1185                        delete exporter;
1186                }
1187                cout << "finished" << endl;
1188        }
1189
1190        if (1) // export merged view cells
1191        {
1192                mColorCode = 1;
1193
1194                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
1195       
1196                cout << "exporting view cells after merge (pvs size) ... ";     
1197
1198                if (exporter)
1199                {
1200                        //exporter->SetWireframe();
1201                       
1202                        if (mExportGeometry)
1203                                exporter->ExportGeometry(objects);
1204
1205                        //exporter->SetWireframe();
1206                        exporter->SetFilled();
1207                        ExportViewCellsForViz(exporter);
1208
1209                        delete exporter;
1210                }
1211                cout << "finished" << endl;
1212        }
1213
1214        mColorCode = savedColorCode;
1215
1216        FinalizeViewCells(true);
1217       
1218        // write view cells to disc
1219        if (mExportViewCells)
1220        {
1221                char buff[100];
1222                environment->GetStringValue("ViewCells.filename", buff);
1223                string vcFilename(buff);
1224
1225                ExportViewCells(buff);
1226        }
1227
1228        return merged;
1229}
1230
1231
1232BspViewCellsManager::~BspViewCellsManager()
1233{
1234}
1235
1236
1237int BspViewCellsManager::GetType() const
1238{
1239        return BSP;
1240}
1241
1242
1243void BspViewCellsManager::Visualize(const ObjectContainer &objects,
1244                                                                        const VssRayContainer &sampleRays)
1245{
1246        if (!ViewCellsConstructed())
1247                return;
1248       
1249        int savedColorCode = mColorCode;
1250
1251       
1252       
1253        if (1) // export final view cells
1254        {
1255                mColorCode = 1;
1256
1257                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
1258       
1259                cout << "exporting view cells after merge (pvs size) ... ";     
1260
1261                if (exporter)
1262                {
1263                        //exporter->SetWireframe();
1264                       
1265                        if (mExportGeometry)
1266                                exporter->ExportGeometry(objects);
1267
1268                        //exporter->SetWireframe();
1269                        exporter->SetFilled();
1270                        ExportViewCellsForViz(exporter);
1271
1272                        delete exporter;
1273                }
1274                cout << "finished" << endl;
1275        }
1276
1277        mColorCode = savedColorCode;
1278
1279        //-- visualization of the BSP splits
1280        bool exportSplits = false;
1281        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1282
1283        if (exportSplits)
1284        {
1285                cout << "exporting splits ... ";
1286                ExportSplits(objects);
1287                cout << "finished" << endl;
1288        }
1289
1290        // export single view cells
1291        ExportBspPvs(objects);
1292}
1293
1294
1295inline bool vc_gt(ViewCell *a, ViewCell *b)
1296{
1297        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1298}
1299
1300
1301void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
1302{
1303        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1304
1305        if (exporter)
1306        {
1307                //exporter->SetFilled();
1308
1309                if (mExportGeometry)
1310                        exporter->ExportGeometry(objects);
1311
1312                Material m;
1313                m.mDiffuseColor = RgbColor(1, 0, 0);
1314                exporter->SetForcedMaterial(m);
1315                exporter->SetWireframe();
1316
1317                exporter->ExportBspSplits(*mBspTree, true);
1318
1319                //NOTE: take forced material, else big scenes cannot be viewed
1320                m.mDiffuseColor = RgbColor(0, 1, 0);
1321                exporter->SetForcedMaterial(m);
1322                //exporter->ResetForcedMaterial();
1323
1324                delete exporter;
1325        }
1326}
1327
1328
1329void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
1330{
1331        const int leafOut = 10;
1332
1333        ViewCell::NewMail();
1334
1335        //-- some rays for output
1336        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
1337
1338        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1339        Debug << "\nOutput view cells: " << endl;
1340
1341        // sort view cells to get largest view cells
1342        if (0)
1343                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1344
1345        int limit = min(leafOut, (int)mViewCells.size());
1346
1347        for (int i = 0; i < limit; ++ i)
1348        {
1349                cout << "creating output for view cell " << i << " ... ";
1350                VssRayContainer vcRays;
1351                Intersectable::NewMail();
1352                ViewCell *vc;
1353
1354                if (0)
1355                        vc = mViewCells[i];
1356                else
1357                        vc = mViewCells[Random((int)mViewCells.size())];
1358
1359                cout << "creating output for view cell " << i << " ... ";
1360
1361                if(0)
1362                {
1363                        // check whether we can add the current ray to the output rays
1364                        for (int k = 0; k < raysOut; ++ k)
1365                        {
1366                                BspRay *ray = mBspRays[k];
1367                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1368                                {
1369                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1370                                        if (vc == leaf->GetViewCell())
1371                                                vcRays.push_back(ray->vssRay);
1372                                }
1373                        }
1374                }
1375
1376                //bspLeaves[j]->Mail();
1377                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1378
1379                Exporter *exporter = Exporter::GetExporter(s);
1380
1381                exporter->SetWireframe();
1382
1383                Material m;//= RandomMaterial();
1384                m.mDiffuseColor = RgbColor(0, 1, 0);
1385                exporter->SetForcedMaterial(m);
1386
1387                ExportViewCellGeometry(exporter, vc);
1388               
1389
1390                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
1391                          << ", piercing rays=" << (int)vcRays.size() << endl;
1392                         // << ", leaves=" << (int)vc->mLeaves.size() << endl;
1393
1394
1395                // export rays piercing this view cell
1396                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1397
1398                m.mDiffuseColor = RgbColor(1, 0, 0);
1399                exporter->SetForcedMaterial(m);
1400
1401                ObjectPvsMap::const_iterator it,
1402                        it_end = vc->GetPvs().mEntries.end();
1403
1404                exporter->SetFilled();
1405
1406                // output PVS of view cell
1407                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1408                {
1409                        Intersectable *intersect = (*it).first;
1410
1411                        if (!intersect->Mailed())
1412                        {
1413                                Material m = RandomMaterial();
1414                                exporter->SetForcedMaterial(m);
1415
1416                                exporter->ExportIntersectable(intersect);
1417                                intersect->Mail();
1418                        }
1419                }
1420
1421                DEL_PTR(exporter);
1422                cout << "finished" << endl;
1423        }
1424
1425        Debug << endl;
1426}
1427
1428
1429void BspViewCellsManager::ExportColor(Exporter *exporter,
1430                                                                          ViewCell *vc) const
1431{
1432        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
1433
1434        float importance = 0;
1435        static Material m;
1436
1437        switch (mColorCode)
1438        {
1439        case 0: // Random
1440                {
1441                        if (vcValid)
1442                        {
1443                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
1444                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
1445                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
1446                        }
1447                        else
1448                        {
1449                                m.mDiffuseColor.r = 0.0f;
1450                                m.mDiffuseColor.g = 1.0f;
1451                                m.mDiffuseColor.b = 0.0f;
1452                        }
1453
1454                        exporter->SetForcedMaterial(m);
1455                        return;
1456                }
1457               
1458        case 1: // pvs
1459                {
1460                        importance = (float)vc->GetPvs().GetSize() /
1461                                (float)mViewCellsStats.maxPvs;
1462
1463                }
1464                break;
1465        case 2: // merges
1466                {
1467            int lSize = mViewCellsTree->GetSize(vc);
1468                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
1469                }
1470                //break;
1471        case 3: // merge tree differene
1472                {
1473                        // TODO
1474                        //importance = (float)GetMaxTreeDiff(vc) /
1475                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
1476
1477                }
1478                break;
1479        default:
1480                break;
1481        }
1482
1483        // special color code for invalid view cells
1484        m.mDiffuseColor.r = importance;
1485        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1486        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
1487
1488        //Debug << "importance: " << importance << endl;
1489        exporter->SetForcedMaterial(m);
1490}
1491
1492
1493void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1494                                                                                                 ViewCell *vc,
1495                                                                                                 const Plane3 *cuttingPlane) const
1496{
1497        if (vc->GetMesh())
1498        {
1499                exporter->ExportMesh(vc->GetMesh());
1500                return;
1501        }
1502
1503        BspNodeGeometry geom;
1504        mBspTree->ConstructGeometry(vc, geom);
1505
1506
1507        if (cuttingPlane)
1508        {
1509                BspNodeGeometry front;
1510                BspNodeGeometry back;
1511
1512                geom.SplitGeometry(front,
1513                                                   back,
1514                                                   *cuttingPlane,
1515                                                   mViewSpaceBox,
1516                                                   0.0001f);
1517
1518                if ((int)back.mPolys.size() >= 3)
1519                        exporter->ExportPolygons(back.mPolys);
1520        }
1521        else
1522        {
1523               
1524                exporter->ExportPolygons(geom.mPolys);
1525        }
1526}
1527
1528
1529void BspViewCellsManager::CreateMesh(ViewCell *vc)
1530{
1531        if (vc->GetMesh())
1532                delete vc->GetMesh();
1533
1534        BspNodeGeometry geom;
1535       
1536        mBspTree->ConstructGeometry(vc, geom);
1537
1538        Mesh *mesh = new Mesh();
1539        geom.AddToMesh(*mesh);
1540        vc->SetMesh(mesh);
1541        mMeshContainer.push_back(mesh);
1542}
1543
1544
1545void BspViewCellsManager::Finalize(ViewCell *viewCell,
1546                                                                   const bool createMesh)
1547{
1548        CreateMesh(viewCell);
1549
1550        float area = 0;
1551        float volume = 0;
1552
1553        ViewCellContainer leaves;
1554        mViewCellsTree->CollectLeaves(viewCell, leaves);
1555
1556        ViewCellContainer::const_iterator it, it_end = leaves.end();
1557
1558        for (it = leaves.begin(); it != it_end; ++ it)
1559        {
1560                BspNodeGeometry geom;
1561                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
1562                mBspTree->ConstructGeometry(leaf, geom);
1563
1564                area += geom.GetArea();
1565                volume += geom.GetVolume();
1566        }
1567
1568        viewCell->SetVolume(volume);
1569        viewCell->SetArea(area);
1570}
1571
1572
1573ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
1574{
1575        if (!mBspTree)
1576                return NULL;
1577
1578        if (!mViewSpaceBox.IsInside(point))
1579                return NULL;
1580       
1581        return mBspTree->GetViewCell(point);
1582}
1583
1584
1585void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1586                                                                                                 vector<MergeCandidate> &candidates)
1587{
1588        cout << "collecting merge candidates ... " << endl;
1589
1590        if (mUseRaysForMerge)
1591        {
1592                mBspTree->CollectMergeCandidates(rays, candidates);
1593        }
1594        else
1595        {
1596                vector<BspLeaf *> leaves;
1597                mBspTree->CollectLeaves(leaves);
1598                mBspTree->CollectMergeCandidates(leaves, candidates);
1599        }
1600
1601        cout << "fininshed collecting candidates" << endl;
1602}
1603
1604
1605
1606bool BspViewCellsManager::ExportViewCells(const string filename)
1607{
1608        cout << "exporting view cells to xml ... ";
1609        std::ofstream stream;
1610
1611        // for output we need unique ids for each view cell
1612        CreateUniqueViewCellIds();
1613
1614
1615        stream.open(filename.c_str());
1616        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
1617        stream << "<Visibility_Solution>" << endl;
1618
1619        //-- the view space bounding box
1620        stream << "<ViewSpaceBox"
1621                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
1622                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
1623
1624        //-- the type of the view cells hierarchy
1625        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
1626        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
1627        //-- load the view cells itself, i.e., the ids and the pvs
1628        stream << "<ViewCells>" << endl;
1629        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1630        for (it = mViewCells.begin(); it != it_end; ++ it)
1631                ExportViewCell(*it, stream);
1632
1633        stream << "</ViewCells>" << endl;
1634
1635        //-- load the hierarchy
1636        stream << "<Hierarchy>" << endl;
1637        mBspTree->Export(stream);
1638        stream << endl << "</Hierarchy>" << endl;
1639
1640        stream << "</Visibility_Solution>" << endl;
1641        stream.close();
1642
1643        cout << "finished" << endl;
1644
1645        return true;
1646}
1647
1648
1649void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
1650{
1651        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1652        for (it = mViewCells.begin(); it != it_end; ++ it)
1653        {
1654                ViewCell *vc = *it;
1655                ViewCellContainer leaves;
1656                mViewCellsTree->CollectLeaves(vc, leaves);
1657               
1658                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
1659
1660                for (lit = leaves.begin(); lit != lit_end; ++ lit)
1661                {
1662                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
1663                        bspVc->mLeaf->SetViewCell(vc);
1664                }
1665        }
1666}
1667
1668/************************************************************************/
1669/*                   KdViewCellsManager implementation                  */
1670/************************************************************************/
1671
1672
1673
1674KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
1675ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
1676{
1677}
1678
1679float KdViewCellsManager::GetProbability(ViewCell *viewCell)
1680{
1681        // compute view cell area / volume as subsititute for probability
1682#if 0
1683        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1684#endif
1685#if 1
1686        return GetArea(viewCell) / GetAccVcArea();
1687#endif
1688#if 0
1689        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1690#endif
1691}
1692
1693
1694float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1695{
1696        return viewCell->GetPvs().GetSize() * objRendercost;
1697}
1698
1699
1700void KdViewCellsManager::CollectViewCells()
1701{
1702        //mKdTree->CollectViewCells(mViewCells); TODO
1703}
1704
1705
1706int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1707                                                                  const VssRayContainer &rays)
1708{
1709        // if view cells already constructed
1710        if (ViewCellsConstructed())
1711                return 0;
1712
1713        mKdTree->Construct();
1714
1715        mTotalAreaValid = false;
1716        // create the view cells
1717        mKdTree->CreateAndCollectViewCells(mViewCells);
1718
1719        // cast rays
1720        ComputeSampleContributions(rays, true, false);
1721
1722        EvaluateViewCellsStats();
1723        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1724
1725        return 0;
1726}
1727
1728
1729bool KdViewCellsManager::ViewCellsConstructed() const
1730{
1731        return mKdTree->GetRoot() != NULL;
1732}
1733
1734int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1735                                                                        const VssRayContainer &rays)
1736{
1737        return 0;
1738}
1739
1740void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1741                                                                   const VssRayContainer &sampleRays)
1742{
1743        if (!ViewCellsConstructed())
1744                return;
1745
1746        // using view cells instead of the kd PVS of objects
1747        const bool useViewCells = true;
1748        bool exportRays = false;
1749
1750        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1751        const int pvsOut = min((int)objects.size(), 10);
1752        VssRayContainer *rays = new VssRayContainer[pvsOut];
1753
1754        if (useViewCells)
1755        {
1756                const int leafOut = 10;
1757
1758                ViewCell::NewMail();
1759
1760                //-- some rays for output
1761                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1762                Debug << "visualization using " << raysOut << " samples" << endl;
1763
1764                //-- some random view cells and rays for output
1765                vector<KdLeaf *> kdLeaves;
1766
1767                for (int i = 0; i < leafOut; ++ i)
1768                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1769
1770                for (int i = 0; i < kdLeaves.size(); ++ i)
1771                {
1772                        KdLeaf *leaf = kdLeaves[i];
1773                        RayContainer vcRays;
1774
1775                        cout << "creating output for view cell " << i << " ... ";
1776#if 0
1777                        // check whether we can add the current ray to the output rays
1778                        for (int k = 0; k < raysOut; ++ k)
1779                        {
1780                                Ray *ray = sampleRays[k];
1781
1782                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1783                                {
1784                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1785
1786                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1787                                        {
1788                                                vcRays.push_back(ray);
1789                                        }
1790                                }
1791                        }
1792#endif
1793                        Intersectable::NewMail();
1794
1795                        ViewCell *vc = leaf->mViewCell;
1796
1797                        //bspLeaves[j]->Mail();
1798                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1799
1800                        Exporter *exporter = Exporter::GetExporter(s);
1801                        exporter->SetFilled();
1802
1803                        exporter->SetWireframe();
1804                        //exporter->SetFilled();
1805
1806                        Material m;//= RandomMaterial();
1807                        m.mDiffuseColor = RgbColor(1, 1, 0);
1808                        exporter->SetForcedMaterial(m);
1809
1810                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1811                        exporter->ExportBox(box);
1812
1813                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1814                                << ", piercing rays=" << (int)vcRays.size() << endl;
1815
1816                        // export rays piercing this view cell
1817                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1818
1819                        m.mDiffuseColor = RgbColor(1, 0, 0);
1820                        exporter->SetForcedMaterial(m);
1821
1822                        // exporter->SetWireframe();
1823                        exporter->SetFilled();
1824
1825                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1826                        // output PVS of view cell
1827                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1828                        {
1829                                Intersectable *intersect = (*it).first;
1830                                if (!intersect->Mailed())
1831                                {
1832                                        exporter->ExportIntersectable(intersect);
1833                                        intersect->Mail();
1834                                }
1835                        }
1836
1837                        DEL_PTR(exporter);
1838                        cout << "finished" << endl;
1839                }
1840
1841                DEL_PTR(rays);
1842        }
1843        else // using kd PVS of objects
1844        {
1845                for (int i = 0; i < limit; ++ i)
1846                {
1847                        VssRay *ray = sampleRays[i];
1848
1849                        // check whether we can add this to the rays
1850                        for (int j = 0; j < pvsOut; j++)
1851                        {
1852                                if (objects[j] == ray->mTerminationObject)
1853                                {
1854                                        rays[j].push_back(ray);
1855                                }
1856                        }
1857                }
1858
1859                if (exportRays)
1860                {
1861                        Exporter *exporter = NULL;
1862                        exporter = Exporter::GetExporter("sample-rays.x3d");
1863                        exporter->SetWireframe();
1864                        exporter->ExportKdTree(*mKdTree);
1865
1866                        for (i=0; i < pvsOut; i++)
1867                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1868
1869                        exporter->SetFilled();
1870
1871                        delete exporter;
1872                }
1873
1874                for (int k=0; k < pvsOut; k++)
1875                {
1876                        Intersectable *object = objects[k];
1877                        char s[64];
1878                        sprintf(s, "sample-pvs%04d.x3d", k);
1879
1880                        Exporter *exporter = Exporter::GetExporter(s);
1881                        exporter->SetWireframe();
1882
1883                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1884                        Intersectable::NewMail();
1885
1886                        // avoid adding the object to the list
1887                        object->Mail();
1888                        ObjectContainer visibleObjects;
1889
1890                        for (; i != object->mKdPvs.mEntries.end(); i++)
1891                        {
1892                                KdNode *node = (*i).first;
1893                                exporter->ExportBox(mKdTree->GetBox(node));
1894
1895                                mKdTree->CollectObjects(node, visibleObjects);
1896                        }
1897
1898                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1899                        exporter->SetFilled();
1900
1901                        for (int j = 0; j < visibleObjects.size(); j++)
1902                                exporter->ExportIntersectable(visibleObjects[j]);
1903
1904                        Material m;
1905                        m.mDiffuseColor = RgbColor(1, 0, 0);
1906                        exporter->SetForcedMaterial(m);
1907                        exporter->ExportIntersectable(object);
1908
1909                        delete exporter;
1910                }
1911        }
1912}
1913
1914
1915void KdViewCellsManager::ExportColor(Exporter *exporter,
1916                                                                         ViewCell *vc) const
1917{
1918        // TODO
1919}
1920
1921ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1922{
1923        return new KdViewCell(mesh);
1924}
1925
1926
1927void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1928                                                                                                ViewCell *vc,
1929                                                                                                const Plane3 *cuttingPlane) const
1930{
1931        ViewCellContainer leaves;
1932
1933        mViewCellsTree->CollectLeaves(vc, leaves);
1934        ViewCellContainer::const_iterator it, it_end = leaves.end();
1935
1936        for (it = leaves.begin(); it != it_end; ++ it)
1937        {
1938                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
1939       
1940                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
1941        }
1942}
1943
1944
1945int KdViewCellsManager::GetType() const
1946{
1947        return ViewCellsManager::KD;
1948}
1949
1950
1951
1952KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1953{
1954        KdNode *node = leaf;
1955
1956        while (node->mParent && node->mDepth > mKdPvsDepth)
1957                node = node->mParent;
1958        return node;
1959}
1960
1961int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1962                                                                                const Vector3 &termination,
1963                                                                                ViewCellContainer &viewcells)
1964{
1965        return mKdTree->CastLineSegment(origin, termination, viewcells);
1966}
1967
1968
1969void KdViewCellsManager::CreateMesh(ViewCell *vc)
1970{
1971        // TODO
1972}
1973
1974
1975
1976void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1977                                                                                                vector<MergeCandidate> &candidates)
1978{
1979        // TODO
1980}
1981
1982
1983/**********************************************************************/
1984/*                   VspKdViewCellsManager implementation             */
1985/**********************************************************************/
1986
1987
1988VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
1989ViewCellsManager(), mVspKdTree(vspKdTree)
1990{
1991        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
1992        mVspKdTree->SetViewCellsManager(this);
1993}
1994
1995float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
1996{
1997        // volume or area substitutes for view point probability
1998#if 0
1999        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2000#else
2001        return GetArea(viewCell) / GetAccVcArea();
2002#endif
2003}
2004
2005
2006float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
2007{
2008        return viewCell->GetPvs().GetSize() * objRendercost;
2009}
2010
2011
2012void VspKdViewCellsManager::CollectViewCells()
2013{
2014        mVspKdTree->CollectViewCells(mViewCells);
2015}
2016
2017
2018int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2019                                                                                                const VssRayContainer &rays)
2020{
2021        // if view cells already constructed
2022        if (ViewCellsConstructed())
2023                return 0;
2024
2025        VssRayContainer constructionRays;
2026        VssRayContainer savedRays;
2027
2028        GetRaySets(rays,
2029                           mInitialSamples,
2030                           constructionRays,
2031                           &savedRays);
2032
2033        Debug << "constructing vsp kd tree using "
2034                  << (int)constructionRays.size() << " samples" << endl;
2035
2036        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
2037        Debug << mVspKdTree->GetStatistics() << endl;
2038
2039        // export leaf building blocks
2040        ExportLeaves(objects, rays);
2041
2042        // finally merge kd leaf building blocks to view cells
2043        const int merged = mVspKdTree->MergeViewCells(rays);
2044
2045        // collapse siblings belonging to the same view cell
2046        mVspKdTree->RefineViewCells(rays);
2047
2048        // collapse siblings belonging to the same view cell
2049        mVspKdTree->CollapseTree();
2050
2051        // evaluale view cell stats
2052        ResetViewCells();
2053
2054        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2055
2056        long startTime = GetTime();
2057        // recast rest of rays
2058        ComputeSampleContributions(savedRays, true, false);
2059
2060        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2061                  << " secs" << endl;
2062
2063        return merged;
2064}
2065
2066bool VspKdViewCellsManager::ViewCellsConstructed() const
2067{
2068        return mVspKdTree->GetRoot() != NULL;
2069}
2070
2071
2072ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2073{
2074        return new VspKdViewCell(mesh);
2075}
2076
2077int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
2078                                                                           const VssRayContainer &rays)
2079{
2080        if (!ViewCellsConstructed())
2081                return 0;
2082
2083        // recalculate stats
2084        EvaluateViewCellsStats();
2085
2086        return 0;
2087}
2088
2089
2090void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2091                                                                                 const VssRayContainer &sampleRays)
2092{
2093        if (!ViewCellsConstructed())
2094                return;
2095
2096        //-- export leaf building blocks
2097        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
2098        if (!exporter)
2099                return;
2100
2101        if (mExportGeometry)
2102                exporter->ExportGeometry(objects);
2103       
2104        //exporter->SetWireframe();
2105        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2106        exporter->ExportVspKdTree(*mVspKdTree);
2107
2108        if (mExportRays)
2109        {
2110                const float prob = (float)mVisualizationSamples
2111                        / ((float)sampleRays.size() + Limits::Small);
2112
2113                exporter->SetWireframe();
2114
2115                //-- collect uniformly distributed rays
2116                VssRayContainer rays;
2117
2118                for (int i = 0; i < sampleRays.size(); ++ i)
2119                {
2120                        if (RandomValue(0,1) < prob)
2121                                rays.push_back(sampleRays[i]);
2122                }
2123                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2124        }
2125
2126        delete exporter;
2127}
2128
2129void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2130                                                                          const VssRayContainer &sampleRays)
2131{
2132        if (!ViewCellsConstructed())
2133                return;
2134
2135        //-- export single view cells
2136        for (int i = 0; i < 10; ++ i)
2137        {
2138                char s[64];
2139                sprintf(s, "vsp_viewcell%04d.x3d", i);
2140                Exporter *exporter = Exporter::GetExporter(s);
2141                const int idx =
2142                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
2143
2144                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
2145
2146                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
2147                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
2148                //-- export geometry
2149                Material m;
2150                m.mDiffuseColor = RgbColor(0, 1, 1);
2151
2152                exporter->SetForcedMaterial(m);
2153                exporter->SetWireframe();
2154
2155                ExportViewCellGeometry(exporter, vc);
2156
2157                //-- export stored rays
2158               
2159                if (mExportRays)
2160                {
2161                        ViewCellContainer leaves;
2162                        mViewCellsTree->CollectLeaves(vc, leaves);
2163
2164                        ViewCellContainer::const_iterator it,
2165                                it_end = leaves.end();
2166
2167                        for (it = leaves.begin(); it != it_end; ++ it)
2168                        {
2169                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2170                                VspKdLeaf *leaf = vspKdVc->mLeaf;
2171                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
2172
2173                                VssRayContainer vssRays;
2174
2175                                VssRayContainer castRays;
2176                                VssRayContainer initRays;
2177
2178                                leaf->GetRays(vssRays);
2179
2180                                VssRayContainer::const_iterator it, it_end = vssRays.end();
2181                                const float prop = 200.0f / (float)vssRays.size();
2182
2183                                for (it = vssRays.begin(); it != it_end; ++ it)
2184                                {
2185                                        if (Random(1) < prop)
2186                                                if ((*it)->mTerminationObject == NULL)
2187                                                        castRays.push_back(*it);
2188                                                else
2189                                                        initRays.push_back(*it);
2190                                }
2191
2192                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2193                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
2194                        }
2195                }
2196       
2197                //-- output PVS of view cell
2198                m.mDiffuseColor = RgbColor(1, 0, 0);
2199                exporter->SetForcedMaterial(m);
2200
2201                Intersectable::NewMail();
2202
2203                ObjectPvsMap::const_iterator it,
2204                        it_end = vc->GetPvs().mEntries.end();
2205
2206                exporter->SetFilled();
2207
2208                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2209                {
2210                        Intersectable *intersect = (*it).first;
2211
2212                        if (!intersect->Mailed())
2213                        {
2214                                Material m = RandomMaterial();
2215                                exporter->SetForcedMaterial(m);
2216
2217                                exporter->ExportIntersectable(intersect);
2218                                intersect->Mail();
2219                        }
2220                }
2221
2222                delete exporter;
2223        }
2224
2225        //-- export final view cells
2226        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2227
2228        //if (exportGeometry) exporter->SetWireframe();
2229        //else exporter->SetFilled();
2230
2231        ExportViewCellsForViz(exporter);
2232
2233        if (mExportGeometry)
2234        {
2235                exporter->SetFilled();
2236                exporter->ExportGeometry(objects);
2237        }
2238
2239        if (mExportRays)
2240        {
2241                const float prob = (float)mVisualizationSamples
2242                        / ((float)sampleRays.size() + Limits::Small);
2243
2244                exporter->SetWireframe();
2245
2246                VssRayContainer rays;
2247
2248                for (int i = 0; i < sampleRays.size(); ++ i)
2249                {
2250                  if (RandomValue(0,1) < prob)
2251                        rays.push_back(sampleRays[i]);
2252                }
2253                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2254        }
2255
2256        delete exporter;
2257}
2258
2259int VspKdViewCellsManager::GetType() const
2260{
2261        return VSP_KD;
2262}
2263
2264
2265int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2266                                                                                   const Vector3 &termination,
2267                                                                                   ViewCellContainer &viewcells)
2268{
2269        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
2270}
2271
2272
2273void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2274                                                                                ViewCell *vc) const
2275{
2276        if (mColorCode == 0) // Random color
2277                return;
2278
2279        float importance = 0;
2280
2281        switch (mColorCode)
2282        {
2283        case 1: // pvs
2284                {
2285                        importance = (float)vc->GetPvs().GetSize() /
2286                                (float)mViewCellsStats.maxPvs;
2287                }
2288                break;
2289        case 2: // merged leaves
2290                {
2291                int lSize = mViewCellsTree->GetSize(vc);
2292                        importance = (float)lSize /
2293                                (float)mViewCellsStats.maxLeaves;
2294                }
2295                break;
2296        case 3: // merged tree depth difference
2297                {
2298                        //importance = (float)GetMaxTreeDiff(vc) /
2299                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2300                }
2301                break;
2302        default:
2303                break;
2304        }
2305
2306        Material m;
2307        m.mDiffuseColor.b = 1.0f;
2308        m.mDiffuseColor.r = importance;
2309        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2310        //Debug << "importance: " << importance << endl;
2311        exporter->SetForcedMaterial(m);
2312}
2313
2314
2315void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2316                                                                                                   ViewCell *vc,
2317                                                                                                   const Plane3 *cuttingPlane) const
2318{
2319        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2320
2321        Mesh m;
2322
2323        ViewCellContainer leaves;
2324        mViewCellsTree->CollectLeaves(vc, leaves);
2325
2326        ViewCellContainer::const_iterator it, it_end = leaves.end();
2327
2328        for (it = leaves.begin(); it != it_end; ++ it)
2329        {
2330                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2331                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
2332        }
2333
2334        exporter->ExportMesh(&m);
2335}
2336
2337
2338void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2339{
2340        //TODO
2341}
2342
2343
2344void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2345                                                                                                   vector<MergeCandidate> &candidates)
2346{
2347        // TODO
2348}
2349
2350
2351/**************************************************************************/
2352/*                   VspBspViewCellsManager implementation                */
2353/**************************************************************************/
2354
2355
2356VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
2357ViewCellsManager(), mVspBspTree(vspBspTree)
2358{
2359        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
2360        mVspBspTree->SetViewCellsManager(this);
2361        mVspBspTree->mViewCellsTree = mViewCellsTree;
2362}
2363
2364
2365VspBspViewCellsManager::~VspBspViewCellsManager()
2366{
2367}
2368
2369
2370float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
2371{
2372        if (0 && mVspBspTree->mUseAreaForPvs)
2373                return GetArea(viewCell) / GetAccVcArea();
2374        else
2375                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
2376}
2377
2378
2379void VspBspViewCellsManager::CollectViewCells()
2380{
2381        // view cells tree constructed
2382        if (!ViewCellsTreeConstructed())
2383        {
2384                mVspBspTree->CollectViewCells(mViewCells, false);
2385        }
2386        else
2387        {
2388                // we can use the view cells tree hierarchy to get the right set
2389                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
2390        }
2391
2392}
2393
2394
2395float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
2396                                                                                        float objRendercost) const
2397{
2398        return viewCell->GetPvs().GetSize() * objRendercost;
2399}
2400
2401
2402bool VspBspViewCellsManager::ViewCellsConstructed() const
2403{
2404        return mVspBspTree->GetRoot() != NULL;
2405}
2406
2407
2408ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2409{
2410        return new BspViewCell(mesh);
2411}
2412
2413
2414/*void VspBspViewCellsManager::CollectNodes(ViewCell *vc, vector<BspNode *>nodes)
2415{
2416        void ViewCellsTree::CollectLeaves(ViewCell *vc, vector<BspNode *> &nodes) const
2417       
2418        if (vc->IsLeaf())
2419        {
2420                BspViewCell *bvc = dynamic_cast<BspViewCell *>(vc);
2421                nodes->push_back(bvc->mLeaf);
2422        }
2423        else
2424        {
2425                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2426
2427                for (it = interior->mChildren.begin; it != it_end; ++ it)
2428                {
2429                        vector<BspNode *> mynodes;
2430                        CollectNodes(*it, mynodes);
2431
2432                        if (mynodes[0]->GetParent() && (mynodes[0]->GetParent() == mynodes[1]->GetParent()))
2433                        {
2434                                nodes.push_back(nodes[0]->GetParent());
2435                        }
2436
2437                }
2438        }
2439}*/
2440
2441
2442int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2443                                                                                                 const VssRayContainer &rays)
2444{
2445        // if view cells were already constructed
2446        if (ViewCellsConstructed())
2447                return 0;
2448
2449        Debug << "Constructing bsp view cells" << endl;
2450
2451        int sampleContributions = 0;
2452
2453        VssRayContainer sampleRays;
2454
2455        int limit = min (mInitialSamples, (int)rays.size());
2456
2457        VssRayContainer constructionRays;
2458        VssRayContainer savedRays;
2459
2460        Debug << "samples used for subdivision: " << mInitialSamples
2461                  << " rays: " << (int)rays.size() << endl;
2462
2463        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
2464
2465        Debug << "initial rays: " << (int)constructionRays.size() << endl;
2466        Debug << "saved rays: " << (int)savedRays.size() << endl;
2467
2468        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
2469
2470        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
2471
2472        Debug << mVspBspTree->GetStatistics() << endl;
2473
2474        // collapse invalid regions
2475        cout << "collapsing invalid tree regions ... ";
2476        long startTime = GetTime();
2477        int collapsedLeaves = mVspBspTree->CollapseTree();
2478        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
2479                  << " seconds" << endl;
2480
2481    cout << "finished" << endl;
2482
2483        cout << "reseting view cell stats ... ";
2484        ResetViewCells();
2485        cout << "finished" << endl;
2486
2487        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2488
2489        if (1) // export initial view cells
2490        {
2491                cout << "exporting initial view cells (=leaves) ... ";
2492                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
2493
2494                if (exporter)
2495                {
2496                        if (0 && mExportRays)
2497                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
2498
2499                        if (mExportGeometry)
2500                                exporter->ExportGeometry(objects);
2501
2502                        //exporter->SetWireframe();
2503                        exporter->SetFilled();
2504                        ExportViewCellsForViz(exporter);
2505
2506                        delete exporter;
2507                }
2508                cout << "finished" << endl;
2509        }
2510
2511        startTime = GetTime();
2512
2513        // reset view cells and stats
2514        ResetViewCells();
2515
2516        cout << "Computing remaining ray contributions ... ";
2517        // recast rest of rays
2518        ComputeSampleContributions(savedRays, true, false);
2519        cout << "finished" << endl;
2520
2521        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2522                  << " secs" << endl;
2523
2524        cout << "construction finished" << endl;
2525
2526        return sampleContributions;
2527}
2528
2529
2530void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2531                                                                                        const ObjectContainer &objects)
2532{
2533        //-- post processing of bsp view cells
2534    int vcSize = 0;
2535        int pvsSize = 0;
2536
2537        mRenderer->RenderScene();
2538        SimulationStatistics ss;
2539        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2540    Debug << ss << endl;
2541
2542        //-- merge or subdivide view cells
2543        int merged = 0;
2544        if (mMergeViewCells)
2545        {
2546                cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
2547                long startTime = GetTime();
2548
2549       
2550                // TODO: should be done BEFORE the ray casting
2551                merged = mViewCellsTree->ConstructMergeTree(rays, objects);
2552
2553                //-- stats and visualizations
2554                cout << "finished merging" << endl;
2555                cout << "merged " << merged << " view cells in "
2556                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2557
2558                Debug << "Postprocessing: Merged " << merged << " view cells in "
2559                          << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2560        }
2561
2562        int savedColorCode = mColorCode;
2563       
2564        //BspLeaf::NewMail();
2565        if (1) // export merged view cells
2566        {
2567                mColorCode = 0;
2568                cout << "reseting view cells ... ";
2569                ResetViewCells();
2570
2571                cout << "finished" << endl;
2572
2573                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2574                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
2575
2576                cout << "exporting view cells after merge ... ";
2577
2578                if (exporter)
2579                {
2580                        if (0)
2581                                exporter->SetWireframe();
2582                        else
2583                                exporter->SetFilled();
2584
2585                        ExportViewCellsForViz(exporter);
2586
2587                        if (mExportGeometry)
2588                        {
2589                                Material m;
2590                                m.mDiffuseColor = RgbColor(0, 1, 0);
2591                                exporter->SetForcedMaterial(m);
2592                                exporter->SetFilled();
2593
2594                                exporter->ExportGeometry(objects);
2595                        }
2596
2597                        delete exporter;
2598                }
2599                cout << "finished" << endl;
2600        }
2601
2602        if (1) // export merged view cells
2603        {
2604                mColorCode = 1;
2605
2606                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
2607       
2608                cout << "exporting view cells after merge (pvs size) ... ";     
2609
2610                if (exporter)
2611                {
2612                        if (0)
2613                                exporter->SetWireframe();
2614                        else
2615                                exporter->SetFilled();
2616
2617                        ExportViewCellsForViz(exporter);
2618
2619                        if (mExportGeometry)
2620                        {
2621                                Material m;
2622                                m.mDiffuseColor = RgbColor(0, 1, 0);
2623                                exporter->SetForcedMaterial(m);
2624                                exporter->SetFilled();
2625
2626                                exporter->ExportGeometry(objects);
2627                        }
2628
2629                        delete exporter;
2630                }
2631                cout << "finished" << endl;
2632        }
2633
2634        mColorCode = savedColorCode;
2635
2636}
2637
2638
2639void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2640                                                                                         const ObjectContainer &objects)
2641{
2642        Debug << "render time before refine:" << endl;
2643        mRenderer->RenderScene();
2644        SimulationStatistics ss;
2645        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2646    Debug << ss << endl;
2647
2648        cout << "Refining the merged view cells ... ";
2649        long startTime = GetTime();
2650
2651        // refining the merged view cells
2652        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
2653
2654        //-- stats and visualizations
2655        cout << "finished" << endl;
2656        cout << "refined " << refined << " view cells in "
2657                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2658
2659        Debug << "Postprocessing: refined " << refined << " view cells in "
2660                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2661}
2662
2663
2664int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2665                                                                                const VssRayContainer &rays)
2666{
2667        if (!ViewCellsConstructed())
2668        {
2669                Debug << "postprocess error: no view cells constructed" << endl;
2670                return 0;
2671        }
2672
2673
2674        // view cells already finished before post processing step (i.e. because they were loaded)
2675        if (mViewCellsFinished)
2676        {
2677                FinalizeViewCells(true);
2678                EvaluateViewCellsStats();
2679
2680                return 0;
2681        }
2682
2683
2684        // check if new view cells turned invalid
2685        SetValidity(mMinPvsSize, mMaxPvsSize);
2686        // update valid view space according to valid view cells
2687        mVspBspTree->ValidateTree();
2688
2689        // recompute view cell statistics
2690        mViewCellsStats.Reset();
2691        EvaluateViewCellsStats();
2692
2693        // has to be recomputed
2694        mTotalAreaValid = false;
2695
2696
2697        VssRayContainer postProcessRays;
2698        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2699
2700        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
2701
2702        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2703
2704        // should maybe be done here to allow merge working with area or volume
2705        // and to correct the rendering statistics
2706        if (0)
2707        {
2708                FinalizeViewCells(false);
2709        }
2710
2711        //-- merge the individual view cells
2712        MergeViewCells(postProcessRays, objects);
2713       
2714
2715        //-- refines the merged view cells
2716        if (0)
2717                RefineViewCells(postProcessRays, objects);
2718
2719       
2720        if (1)
2721        {               
2722                float totalCost, erc, var, dev, avg;
2723                int totalpvs;
2724
2725                mViewCellsStats.Reset();
2726
2727        EvaluateRenderStatistics(totalCost, erc, dev, var, totalpvs, avg);
2728               
2729                Debug << "statistics after merge " 
2730                          << " erc: " << erc
2731                          << " dev: " << dev
2732                          << " totalpvs: " << totalpvs
2733                          << " avg: " << avg << endl;
2734        }
2735
2736        //-- render simulation after merge
2737  cout << "\nevaluating bsp view cells render time before compress ... ";
2738  dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
2739  SimulationStatistics ss;
2740  dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2741 
2742  cout << " finished" << endl;
2743  cout << ss << endl;
2744  Debug << ss << endl;
2745
2746
2747
2748        //-- compression
2749
2750        if (ViewCellsTreeConstructed() && mCompressViewCells)
2751        {
2752                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2753                Debug << "number of entries before compress: " << pvsEntries << endl;
2754
2755                mViewCellsTree->CompressViewCellsPvs();
2756
2757                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2758                Debug << "number of entries after compress: " << pvsEntries << endl;
2759        }
2760
2761
2762        //-- export refined (shuffled) view cells
2763        if (0)
2764        {
2765                cout << "exporting shuffled view cells ... ";
2766
2767                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2768                if (exporter)
2769                {
2770                        if (1)
2771                        {
2772                                exporter->SetWireframe();
2773                                exporter->ExportBox(mViewSpaceBox);
2774                                exporter->SetFilled();
2775                        }
2776
2777                        if (mExportGeometry)
2778                        {
2779                                exporter->ExportGeometry(objects);
2780                        }
2781
2782                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2783
2784                        Material vm, lm;
2785
2786                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2787                        {
2788                                ViewCell *vc = *vit;
2789
2790                                vm = RandomMaterial();
2791
2792                                lm = vm;
2793
2794                                vm.mDiffuseColor.r -= 0.45f;
2795                                vm.mDiffuseColor.g -= 0.45f;
2796                                vm.mDiffuseColor.b -= 0.45f;
2797
2798
2799                                ViewCellContainer leaves;
2800                                mViewCellsTree->CollectLeaves(vc, leaves);
2801
2802                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2803
2804                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2805                                {
2806                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2807
2808                                        if (leaf->Mailed())
2809                                                exporter->SetForcedMaterial(lm);
2810                                        else
2811                                                exporter->SetForcedMaterial(vm);
2812
2813                                        BspNodeGeometry geom;
2814                                        mVspBspTree->ConstructGeometry(leaf, geom);
2815                                        exporter->ExportPolygons(geom.mPolys);
2816                                }
2817                        }
2818
2819                        delete exporter;
2820                }
2821
2822
2823                cout << "finished" << endl;
2824        }
2825
2826        // collapse sibling leaves that share the same view cell
2827        if (0)
2828                mVspBspTree->CollapseTree();
2829
2830        // recompute view cell list and statistics
2831        ResetViewCells();
2832
2833        // real meshes are only contructed only at this stage
2834        FinalizeViewCells(true);
2835
2836        // write view cells to disc
2837        if (mExportViewCells)
2838        {
2839                char buff[100];
2840                environment->GetStringValue("ViewCells.filename", buff);
2841                string vcFilename(buff);
2842
2843                ExportViewCells(buff);
2844        }
2845
2846        return 0;
2847}
2848
2849
2850int VspBspViewCellsManager::GetType() const
2851{
2852        return VSP_BSP;
2853}
2854
2855
2856bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2857{
2858        if (!ViewCellsConstructed())
2859                return ViewCellsManager::GetViewPoint(viewPoint);
2860
2861        // TODO: set reasonable limit
2862        const int limit = 20;
2863
2864        for (int i = 0; i < limit; ++ i)
2865        {
2866                viewPoint = mViewSpaceBox.GetRandomPoint();
2867                if (mVspBspTree->ViewPointValid(viewPoint))
2868                {
2869                        return true;
2870                }
2871        }
2872        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2873        return false;
2874}
2875
2876
2877bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2878{
2879  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2880  // validy update in preprocessor for all managers)
2881  return ViewCellsManager::ViewPointValid(viewPoint);
2882
2883  //    return mViewSpaceBox.IsInside(viewPoint) &&
2884  //               mVspBspTree->ViewPointValid(viewPoint);
2885}
2886
2887
2888void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2889                                                                           const VssRayContainer &sampleRays)
2890{
2891        if (!ViewCellsConstructed())
2892                return;
2893
2894        VssRayContainer visRays;
2895        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2896
2897       
2898        if (1) // export view cells
2899        {// hack pvs
2900                int savedColorCode = mColorCode;
2901                mColorCode = 1;
2902                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2903               
2904                if (exporter)
2905                {
2906                        cout << "exporting view cells after post process ... ";
2907
2908                        if (0)
2909                        {
2910                                exporter->SetWireframe();
2911                                exporter->ExportBox(mViewSpaceBox);
2912                                exporter->SetFilled();
2913                        }
2914
2915                        if (mExportGeometry)
2916                        {
2917                                exporter->ExportGeometry(objects);
2918                        }
2919
2920                        // export rays
2921                        if (mExportRays)
2922                        {
2923                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2924                        }
2925
2926                        ExportViewCellsForViz(exporter);
2927                        delete exporter;
2928                        cout << "finished" << endl;
2929                }
2930
2931                mColorCode = savedColorCode;
2932        }
2933
2934        if (0)
2935        {
2936                cout << "exporting depth map ... ";
2937
2938                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2939                if (exporter)
2940                {
2941                        if (1)
2942                        {
2943                                exporter->SetWireframe();
2944                                exporter->ExportBox(mViewSpaceBox);
2945                                exporter->SetFilled();
2946                        }
2947
2948                        if (mExportGeometry)
2949                        {
2950                                exporter->ExportGeometry(objects);
2951                        }
2952
2953                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
2954
2955                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2956
2957                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2958                        {
2959                                ViewCell *vc = *vit;
2960
2961                                ViewCellContainer leaves;
2962                                mViewCellsTree->CollectLeaves(vc, leaves);
2963
2964                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2965
2966                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2967                                {
2968                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2969
2970                                        Material m;
2971
2972                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
2973                                        m.mDiffuseColor.r = relDepth;
2974                                        m.mDiffuseColor.g = 0.0f;
2975                                        m.mDiffuseColor.b = 1.0f - relDepth;
2976
2977                    exporter->SetForcedMaterial(m);
2978                               
2979
2980                                        BspNodeGeometry geom;
2981                                        mVspBspTree->ConstructGeometry(leaf, geom);
2982                                        exporter->ExportPolygons(geom.mPolys);
2983                                }
2984                        }
2985
2986                        delete exporter;
2987                }
2988
2989
2990                cout << "finished" << endl;
2991        }
2992
2993        //-- visualization of the BSP splits
2994        bool exportSplits = false;
2995        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2996
2997        if (exportSplits)
2998        {
2999                cout << "exporting splits ... ";
3000                ExportSplits(objects, visRays);
3001                cout << "finished" << endl;
3002        }
3003
3004        //-- export single view cells
3005        ExportBspPvs(objects, visRays);
3006}
3007
3008
3009void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3010                                                                                  const VssRayContainer &rays)
3011{
3012        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3013
3014        if (exporter)
3015        {
3016                Material m;
3017                m.mDiffuseColor = RgbColor(1, 0, 0);
3018                exporter->SetForcedMaterial(m);
3019                exporter->SetWireframe();
3020
3021                exporter->ExportBspSplits(*mVspBspTree, true);
3022
3023                // take forced material, else big scenes cannot be viewed
3024                m.mDiffuseColor = RgbColor(0, 1, 0);
3025                exporter->SetForcedMaterial(m);
3026                exporter->SetFilled();
3027
3028                exporter->ResetForcedMaterial();
3029
3030                // export rays
3031                if (mExportRays)
3032                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
3033
3034                if (mExportGeometry)
3035                        exporter->ExportGeometry(objects);
3036
3037                delete exporter;
3038        }
3039}
3040
3041
3042void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3043                                                                                  const VssRayContainer &rays)
3044{
3045        const int leafOut = 10;
3046
3047        ViewCell::NewMail();
3048
3049        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
3050        Debug << "\nOutput view cells: " << endl;
3051
3052        // sort view cells to visualize the largest view cells
3053        if (0)
3054                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
3055
3056        int limit = min(leafOut, (int)mViewCells.size());
3057
3058        int raysOut;
3059
3060        //-- some rays for output
3061        if (1)
3062                raysOut = min((int)rays.size(), mVisualizationSamples);
3063
3064        for (int i = 0; i < limit; ++ i)
3065        {
3066                cout << "creating output for view cell " << i << " ... ";
3067
3068                VssRayContainer vcRays;
3069                Intersectable::NewMail();
3070                ViewCell *vc;
3071       
3072                if (0) // largest view cell pvs first
3073                        vc = mViewCells[i];
3074                else
3075                        vc = mViewCells[Random((int)mViewCells.size())];
3076
3077                vector<ViewCell *> leaves;
3078                mViewCellsTree->CollectLeaves(vc, leaves);
3079
3080        if (1)
3081                {
3082                        // check whether we can add the current ray to the output rays
3083                        for (int k = 0; k < raysOut; ++ k)
3084                        {
3085                                VssRay *ray = rays[k];
3086                                for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3087                                {
3088                                        ViewCell *rayvc = ray->mViewCells[j];
3089
3090                                        if (leaves[0] == rayvc)
3091                                                vcRays.push_back(ray);
3092                                }
3093                        }
3094                }
3095
3096                //bspLeaves[j]->Mail();
3097                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3098                Exporter *exporter = Exporter::GetExporter(s);
3099                exporter->SetWireframe();
3100
3101                Material m;//= RandomMaterial();
3102                m.mDiffuseColor = RgbColor(0, 1, 0);
3103                exporter->SetForcedMaterial(m);
3104
3105                ExportViewCellGeometry(exporter, vc);
3106
3107
3108                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
3109                          << ", piercing rays=" << (int)vcRays.size() << endl;
3110                        //  << ", leaves=" << (int)vc->mLeaves.size() << endl;
3111
3112               
3113                //-- export rays piercing this view cell
3114                if (1)
3115                {
3116                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
3117                }
3118                else
3119                {
3120
3121                        ViewCellContainer leaves;
3122                        mViewCellsTree->CollectLeaves(vc, leaves);
3123
3124                        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3125
3126                        for (lit = leaves.begin(); lit != lit_end; ++ lit)
3127                        {
3128                                BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3129                                exporter->ExportRays(l->mVssRays);
3130                        }
3131                }
3132
3133       
3134                m.mDiffuseColor = RgbColor(1, 0, 0);
3135                exporter->SetForcedMaterial(m);
3136
3137                ObjectPvsMap::const_iterator it,
3138                        it_end = vc->GetPvs().mEntries.end();
3139
3140                exporter->SetFilled();
3141
3142       
3143                // output PVS of view cell
3144                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
3145                {
3146               
3147                        Intersectable *intersect = (*it).first;
3148
3149                        if (!intersect->Mailed())
3150                        {
3151                                Material m = RandomMaterial();
3152                                exporter->SetForcedMaterial(m);
3153
3154                                exporter->ExportIntersectable(intersect);
3155                                intersect->Mail();
3156                        }
3157                }
3158
3159               
3160                DEL_PTR(exporter);
3161                cout << "finished" << endl;
3162        }
3163
3164        Debug << endl;
3165}
3166
3167
3168int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3169                                                                                        const Vector3 &termination,
3170                                                                                        ViewCellContainer &viewcells)
3171{
3172        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
3173}
3174
3175
3176void VspBspViewCellsManager::ExportColor(Exporter *exporter,
3177                                                                                 ViewCell *vc) const
3178{
3179        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3180
3181        float importance = 0;
3182        static Material m;
3183
3184        switch (mColorCode)
3185        {
3186        case 0: // Random
3187                {
3188                        if (vcValid)
3189                        {
3190                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3191                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3192                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
3193                        }
3194                        else
3195                        {
3196                                m.mDiffuseColor.r = 0.0f;
3197                                m.mDiffuseColor.g = 1.0f;
3198                                m.mDiffuseColor.b = 0.0f;
3199                        }
3200
3201                        exporter->SetForcedMaterial(m);
3202                        return;
3203                }
3204               
3205        case 1: // pvs
3206                {
3207                        importance = (float)vc->GetPvs().GetSize() /
3208                                (float)mViewCellsStats.maxPvs;
3209
3210                }
3211                break;
3212        case 2: // merges
3213                {
3214            int lSize = mViewCellsTree->GetSize(vc);
3215                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
3216                }
3217                break;
3218        case 3: // merge tree differene
3219                {
3220                        importance = (float)GetMaxTreeDiff(vc) /
3221                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3222
3223                }
3224                break;
3225        default:
3226                break;
3227        }
3228
3229        // special color code for invalid view cells
3230        m.mDiffuseColor.r = importance;
3231        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3232        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
3233
3234        //Debug << "importance: " << importance << endl;
3235        exporter->SetForcedMaterial(m);
3236}
3237
3238
3239void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3240                                                    ViewCell *vc,
3241                                                                                                        const Plane3 *cuttingPlane) const
3242{
3243        if (vc->GetMesh())
3244        {
3245                exporter->ExportMesh(vc->GetMesh());
3246       
3247                return;
3248        }
3249
3250       
3251        if (cuttingPlane)
3252        {
3253                ViewCellContainer leaves;
3254                mViewCellsTree->CollectLeaves(vc, leaves);
3255                ViewCellContainer::const_iterator it, it_end = leaves.end();
3256
3257                for (it = leaves.begin(); it != it_end; ++ it)
3258                {
3259                        BspNodeGeometry geom;
3260
3261                        BspNodeGeometry front;
3262                        BspNodeGeometry back;
3263
3264       
3265                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3266
3267                        mVspBspTree->ConstructGeometry(leaf, geom);
3268                       
3269                        geom.SplitGeometry(front,
3270                                                           back,
3271                                                           *cuttingPlane,
3272                                                           mViewSpaceBox,
3273                                                           0.0001f);
3274
3275                        if ((int)back.mPolys.size() >= 3)
3276                                exporter->ExportPolygons(back.mPolys);
3277                }
3278        }
3279        else
3280        {
3281                BspNodeGeometry geom;
3282                mVspBspTree->ConstructGeometry(vc, geom);
3283                       
3284                exporter->ExportPolygons(geom.mPolys);
3285        }
3286}
3287
3288
3289int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3290{
3291        ViewCellContainer leaves;
3292        mViewCellsTree->CollectLeaves(vc, leaves);
3293
3294        int maxDist = 0;
3295       
3296        // compute max height difference
3297        for (int i = 0; i < (int)leaves.size(); ++ i)
3298                for (int j = 0; j < (int)leaves.size(); ++ j)
3299        {
3300                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
3301
3302                if (i != j)
3303                {
3304                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
3305                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3306                        if (dist > maxDist)
3307                                maxDist = dist;
3308                }
3309        }
3310
3311        return maxDist;
3312}
3313
3314
3315ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
3316{
3317        if (!mVspBspTree)
3318                return NULL;
3319
3320        if (!mViewSpaceBox.IsInside(point))
3321          return NULL;
3322
3323        return mVspBspTree->GetViewCell(point);
3324}
3325
3326
3327void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3328{
3329        if (vc->GetMesh())
3330                delete vc->GetMesh();
3331
3332       
3333        BspNodeGeometry geom;
3334
3335        mVspBspTree->ConstructGeometry(vc, geom);
3336       
3337        Mesh *mesh = new Mesh();
3338        geom.AddToMesh(*mesh);
3339        vc->SetMesh(mesh);
3340        mMeshContainer.push_back(mesh);
3341}
3342
3343
3344ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3345                                                                                                  ObjectContainer *objects)
3346{
3347        ViewCellsParser parser;
3348
3349        ViewCellsManager *vm = NULL;
3350
3351        if (parser.ParseFile(filename, &vm, objects))
3352        {
3353                //vm->PrepareLoadedViewCells();
3354                vm->ResetViewCells();
3355
3356                vm->mViewCellsFinished = true;
3357                vm->mMaxPvsSize = (int)objects->size();
3358
3359                vm->FinalizeViewCells(true);
3360
3361                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3362        }
3363        else
3364        {
3365                Debug << "failed loading view cells" << endl;
3366                DEL_PTR(vm);
3367        }
3368
3369
3370        return vm;
3371}
3372
3373
3374inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3375{
3376        return obj1->mId < obj2->mId;
3377}
3378
3379
3380bool VspBspViewCellsManager::ExportViewCells(const string filename)
3381{
3382        cout << "exporting view cells to xml ... ";
3383        std::ofstream stream;
3384
3385        // for output we need unique ids for each view cell
3386        CreateUniqueViewCellIds();
3387
3388
3389        stream.open(filename.c_str());
3390        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3391        stream << "<Visibility_Solution>" << endl;
3392
3393        //-- the view space bounding box
3394        stream << "<ViewSpaceBox"
3395                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3396                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3397
3398        //-- the type of the view cells hierarchy
3399        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3400
3401        //-- load the view cells itself, i.e., the ids and the pvs
3402        stream << "<ViewCells>" << endl;
3403        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3404        for (it = mViewCells.begin(); it != it_end; ++ it)
3405                ExportViewCell(*it, stream);
3406
3407        stream << "</ViewCells>" << endl;
3408
3409        //-- load the hierarchy
3410        stream << "<Hierarchy>" << endl;
3411        mVspBspTree->Export(stream);
3412        stream << endl << "</Hierarchy>" << endl;
3413
3414        stream << "</Visibility_Solution>" << endl;
3415        stream.close();
3416
3417        cout << "finished" << endl;
3418
3419        return true;
3420}
3421
3422
3423int VspBspViewCellsManager::CastBeam(Beam &beam)
3424{
3425        return mVspBspTree->CastBeam(beam);
3426}
3427
3428
3429void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
3430                                                                          const bool createMesh)
3431{
3432        CreateMesh(viewCell);
3433
3434        float area = 0;
3435        float volume = 0;
3436
3437        ViewCellContainer leaves;
3438        mViewCellsTree->CollectLeaves(viewCell, leaves);
3439
3440        ViewCellContainer::const_iterator it, it_end = leaves.end();
3441
3442        for (it = leaves.begin(); it != it_end; ++ it)
3443        {
3444                BspNodeGeometry geom;
3445                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3446                mVspBspTree->ConstructGeometry(leaf, geom);
3447
3448                area += geom.GetArea();
3449                volume += geom.GetVolume();
3450        }
3451
3452        viewCell->SetVolume(volume);
3453        viewCell->SetArea(area);
3454}
3455
3456
3457void VspBspViewCellsManager::PrepareLoadedViewCells()
3458{
3459        // TODO: do I still need this here?
3460        if (0)
3461        mVspBspTree->RepairViewCellsLeafLists();
3462}
3463
3464
3465
3466void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3467                                                                                                        vector<MergeCandidate> &candidates)
3468{       
3469        cout << "collecting merge candidates ... " << endl;
3470
3471        if (mUseRaysForMerge)
3472        {
3473                mVspBspTree->CollectMergeCandidates(rays, candidates);
3474        }
3475        else
3476        {
3477                vector<BspLeaf *> leaves;
3478                mVspBspTree->CollectLeaves(leaves);
3479                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3480        }
3481
3482        cout << "fininshed collecting candidates" << endl;
3483}
3484
3485
3486void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
3487{
3488        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3489        for (it = mViewCells.begin(); it != it_end; ++ it)
3490        {
3491        }
3492}
3493
3494//////////////////////////////////
3495ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3496{
3497        //TODO
3498        return NULL;// new VspBspViewCellsManager();
3499}
3500
Note: See TracBrowser for help on using the repository browser.