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

Revision 601, 80.8 KB checked in by mattausch, 19 years ago (diff)
Line 
1#include "ViewCellsManager.h"
2#include "RenderSimulator.h"
3#include "Mesh.h"
4#include "Triangle3.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "X3dParser.h"
8#include "ViewCellBsp.h"
9#include "KdTree.h"
10#include "VspKdTree.h"
11#include "Exporter.h"
12#include "VspBspTree.h"
13#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                if(0)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        if(0)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        if(0)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        if (0)
2519        ComputeSampleContributions(savedRays, true, false);
2520        cout << "finished" << endl;
2521
2522        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2523                  << " secs" << endl;
2524
2525        cout << "construction finished" << endl;
2526
2527        return sampleContributions;
2528}
2529
2530
2531void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2532                                                                                        const ObjectContainer &objects)
2533{
2534        //-- post processing of bsp view cells
2535    int vcSize = 0;
2536        int pvsSize = 0;
2537
2538        mRenderer->RenderScene();
2539        SimulationStatistics ss;
2540        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2541    Debug << ss << endl;
2542
2543        //-- merge or subdivide view cells
2544        int merged = 0;
2545        if (mMergeViewCells)
2546        {
2547                cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
2548                long startTime = GetTime();
2549
2550       
2551                // TODO: should be done BEFORE the ray casting
2552                merged = mViewCellsTree->ConstructMergeTree(rays, objects);
2553
2554                //-- stats and visualizations
2555                cout << "finished merging" << endl;
2556                cout << "merged " << merged << " view cells in "
2557                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2558
2559                Debug << "Postprocessing: Merged " << merged << " view cells in "
2560                          << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2561        }
2562
2563        int savedColorCode = mColorCode;
2564       
2565        //BspLeaf::NewMail();
2566        if (1) // export merged view cells
2567        {
2568                mColorCode = 0;
2569                cout << "reseting view cells ... ";
2570                ResetViewCells();
2571
2572                cout << "finished" << endl;
2573
2574                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2575                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
2576
2577                cout << "exporting view cells after merge ... ";
2578
2579                if (exporter)
2580                {
2581                        if (0)
2582                                exporter->SetWireframe();
2583                        else
2584                                exporter->SetFilled();
2585
2586                        ExportViewCellsForViz(exporter);
2587
2588                        if (mExportGeometry)
2589                        {
2590                                Material m;
2591                                m.mDiffuseColor = RgbColor(0, 1, 0);
2592                                exporter->SetForcedMaterial(m);
2593                                exporter->SetFilled();
2594
2595                                exporter->ExportGeometry(objects);
2596                        }
2597
2598                        delete exporter;
2599                }
2600                cout << "finished" << endl;
2601        }
2602
2603        if (1) // export merged view cells
2604        {
2605                mColorCode = 1;
2606
2607                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
2608       
2609                cout << "exporting view cells after merge (pvs size) ... ";     
2610
2611                if (exporter)
2612                {
2613                        if (0)
2614                                exporter->SetWireframe();
2615                        else
2616                                exporter->SetFilled();
2617
2618                        ExportViewCellsForViz(exporter);
2619
2620                        if (mExportGeometry)
2621                        {
2622                                Material m;
2623                                m.mDiffuseColor = RgbColor(0, 1, 0);
2624                                exporter->SetForcedMaterial(m);
2625                                exporter->SetFilled();
2626
2627                                exporter->ExportGeometry(objects);
2628                        }
2629
2630                        delete exporter;
2631                }
2632                cout << "finished" << endl;
2633        }
2634
2635        mColorCode = savedColorCode;
2636
2637}
2638
2639
2640void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2641                                                                                         const ObjectContainer &objects)
2642{
2643        Debug << "render time before refine:" << endl;
2644        mRenderer->RenderScene();
2645        SimulationStatistics ss;
2646        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2647    Debug << ss << endl;
2648
2649        cout << "Refining the merged view cells ... ";
2650        long startTime = GetTime();
2651
2652        // refining the merged view cells
2653        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
2654
2655        //-- stats and visualizations
2656        cout << "finished" << endl;
2657        cout << "refined " << refined << " view cells in "
2658                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2659
2660        Debug << "Postprocessing: refined " << refined << " view cells in "
2661                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2662}
2663
2664
2665int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2666                                                                                const VssRayContainer &rays)
2667{
2668        if (!ViewCellsConstructed())
2669        {
2670                Debug << "postprocess error: no view cells constructed" << endl;
2671                return 0;
2672        }
2673
2674
2675        // view cells already finished before post processing step (i.e. because they were loaded)
2676        if (mViewCellsFinished)
2677        {
2678                FinalizeViewCells(true);
2679                EvaluateViewCellsStats();
2680
2681                return 0;
2682        }
2683
2684
2685        // check if new view cells turned invalid
2686        SetValidity(mMinPvsSize, mMaxPvsSize);
2687        // update valid view space according to valid view cells
2688        mVspBspTree->ValidateTree();
2689
2690        // recompute view cell statistics
2691        mViewCellsStats.Reset();
2692        EvaluateViewCellsStats();
2693
2694        // has to be recomputed
2695        mTotalAreaValid = false;
2696
2697
2698        VssRayContainer postProcessRays;
2699        if(0)GetRaySets(rays, mPostProcessSamples, postProcessRays);
2700
2701        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
2702
2703        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2704
2705        // should maybe be done here to allow merge working with area or volume
2706        // and to correct the rendering statistics
2707        if (0)
2708        {
2709                FinalizeViewCells(false);
2710        }
2711
2712        //-- merge the individual view cells
2713        MergeViewCells(postProcessRays, objects);
2714       
2715
2716        //-- refines the merged view cells
2717        if (0)
2718                RefineViewCells(postProcessRays, objects);
2719
2720       
2721        if (1)
2722        {               
2723                float totalCost, erc, var, dev, avg;
2724                int totalpvs;
2725
2726                mViewCellsStats.Reset();
2727
2728        EvaluateRenderStatistics(totalCost, erc, dev, var, totalpvs, avg);
2729               
2730                Debug << "statistics after merge " 
2731                          << " erc: " << erc
2732                          << " dev: " << dev
2733                          << " totalpvs: " << totalpvs
2734                          << " avg: " << avg << endl;
2735        }
2736
2737        //-- render simulation after merge
2738  cout << "\nevaluating bsp view cells render time before compress ... ";
2739  dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
2740  SimulationStatistics ss;
2741  dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2742 
2743  cout << " finished" << endl;
2744  cout << ss << endl;
2745  Debug << ss << endl;
2746
2747
2748
2749        //-- compression
2750
2751        if (ViewCellsTreeConstructed() && mCompressViewCells)
2752        {
2753                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2754                Debug << "number of entries before compress: " << pvsEntries << endl;
2755
2756                mViewCellsTree->CompressViewCellsPvs();
2757
2758                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2759                Debug << "number of entries after compress: " << pvsEntries << endl;
2760        }
2761
2762
2763        //-- export refined (shuffled) view cells
2764        if (0)
2765        {
2766                cout << "exporting shuffled view cells ... ";
2767
2768                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2769                if (exporter)
2770                {
2771                        if (1)
2772                        {
2773                                exporter->SetWireframe();
2774                                exporter->ExportBox(mViewSpaceBox);
2775                                exporter->SetFilled();
2776                        }
2777
2778                        if (mExportGeometry)
2779                        {
2780                                exporter->ExportGeometry(objects);
2781                        }
2782
2783                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2784
2785                        Material vm, lm;
2786
2787                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2788                        {
2789                                ViewCell *vc = *vit;
2790
2791                                vm = RandomMaterial();
2792
2793                                lm = vm;
2794
2795                                vm.mDiffuseColor.r -= 0.45f;
2796                                vm.mDiffuseColor.g -= 0.45f;
2797                                vm.mDiffuseColor.b -= 0.45f;
2798
2799
2800                                ViewCellContainer leaves;
2801                                mViewCellsTree->CollectLeaves(vc, leaves);
2802
2803                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2804
2805                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2806                                {
2807                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2808
2809                                        if (leaf->Mailed())
2810                                                exporter->SetForcedMaterial(lm);
2811                                        else
2812                                                exporter->SetForcedMaterial(vm);
2813
2814                                        BspNodeGeometry geom;
2815                                        mVspBspTree->ConstructGeometry(leaf, geom);
2816                                        exporter->ExportPolygons(geom.mPolys);
2817                                }
2818                        }
2819
2820                        delete exporter;
2821                }
2822
2823
2824                cout << "finished" << endl;
2825        }
2826
2827        // collapse sibling leaves that share the same view cell
2828        if (0)
2829                mVspBspTree->CollapseTree();
2830
2831        // recompute view cell list and statistics
2832        ResetViewCells();
2833
2834        // real meshes are only contructed only at this stage
2835        FinalizeViewCells(true);
2836
2837        // write view cells to disc
2838        if (mExportViewCells)
2839        {
2840                char buff[100];
2841                environment->GetStringValue("ViewCells.filename", buff);
2842                string vcFilename(buff);
2843
2844                ExportViewCells(buff);
2845        }
2846
2847        return 0;
2848}
2849
2850
2851int VspBspViewCellsManager::GetType() const
2852{
2853        return VSP_BSP;
2854}
2855
2856
2857bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2858{
2859        if (!ViewCellsConstructed())
2860                return ViewCellsManager::GetViewPoint(viewPoint);
2861
2862        // TODO: set reasonable limit
2863        const int limit = 20;
2864
2865        for (int i = 0; i < limit; ++ i)
2866        {
2867                viewPoint = mViewSpaceBox.GetRandomPoint();
2868                if (mVspBspTree->ViewPointValid(viewPoint))
2869                {
2870                        return true;
2871                }
2872        }
2873        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2874        return false;
2875}
2876
2877
2878bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2879{
2880  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2881  // validy update in preprocessor for all managers)
2882  return ViewCellsManager::ViewPointValid(viewPoint);
2883
2884  //    return mViewSpaceBox.IsInside(viewPoint) &&
2885  //               mVspBspTree->ViewPointValid(viewPoint);
2886}
2887
2888
2889void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2890                                                                           const VssRayContainer &sampleRays)
2891{
2892        if (!ViewCellsConstructed())
2893                return;
2894
2895        VssRayContainer visRays;
2896        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2897
2898       
2899        if (1) // export view cells
2900        {// hack pvs
2901                int savedColorCode = mColorCode;
2902                mColorCode = 1;
2903                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2904               
2905                if (exporter)
2906                {
2907                        cout << "exporting view cells after post process ... ";
2908
2909                        if (0)
2910                        {
2911                                exporter->SetWireframe();
2912                                exporter->ExportBox(mViewSpaceBox);
2913                                exporter->SetFilled();
2914                        }
2915
2916                        if (mExportGeometry)
2917                        {
2918                                exporter->ExportGeometry(objects);
2919                        }
2920
2921                        // export rays
2922                        if (mExportRays)
2923                        {
2924                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2925                        }
2926
2927                        ExportViewCellsForViz(exporter);
2928                        delete exporter;
2929                        cout << "finished" << endl;
2930                }
2931
2932                mColorCode = savedColorCode;
2933        }
2934
2935        if (0)
2936        {
2937                cout << "exporting depth map ... ";
2938
2939                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2940                if (exporter)
2941                {
2942                        if (1)
2943                        {
2944                                exporter->SetWireframe();
2945                                exporter->ExportBox(mViewSpaceBox);
2946                                exporter->SetFilled();
2947                        }
2948
2949                        if (mExportGeometry)
2950                        {
2951                                exporter->ExportGeometry(objects);
2952                        }
2953
2954                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
2955
2956                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2957
2958                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2959                        {
2960                                ViewCell *vc = *vit;
2961
2962                                ViewCellContainer leaves;
2963                                mViewCellsTree->CollectLeaves(vc, leaves);
2964
2965                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2966
2967                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2968                                {
2969                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
2970
2971                                        Material m;
2972
2973                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
2974                                        m.mDiffuseColor.r = relDepth;
2975                                        m.mDiffuseColor.g = 0.0f;
2976                                        m.mDiffuseColor.b = 1.0f - relDepth;
2977
2978                    exporter->SetForcedMaterial(m);
2979                               
2980
2981                                        BspNodeGeometry geom;
2982                                        mVspBspTree->ConstructGeometry(leaf, geom);
2983                                        exporter->ExportPolygons(geom.mPolys);
2984                                }
2985                        }
2986
2987                        delete exporter;
2988                }
2989
2990
2991                cout << "finished" << endl;
2992        }
2993
2994        //-- visualization of the BSP splits
2995        bool exportSplits = false;
2996        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2997
2998        if (exportSplits)
2999        {
3000                cout << "exporting splits ... ";
3001                ExportSplits(objects, visRays);
3002                cout << "finished" << endl;
3003        }
3004
3005        //-- export single view cells
3006        ExportBspPvs(objects, visRays);
3007}
3008
3009
3010void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3011                                                                                  const VssRayContainer &rays)
3012{
3013        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3014
3015        if (exporter)
3016        {
3017                Material m;
3018                m.mDiffuseColor = RgbColor(1, 0, 0);
3019                exporter->SetForcedMaterial(m);
3020                exporter->SetWireframe();
3021
3022                exporter->ExportBspSplits(*mVspBspTree, true);
3023
3024                // take forced material, else big scenes cannot be viewed
3025                m.mDiffuseColor = RgbColor(0, 1, 0);
3026                exporter->SetForcedMaterial(m);
3027                exporter->SetFilled();
3028
3029                exporter->ResetForcedMaterial();
3030
3031                // export rays
3032                if (mExportRays)
3033                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
3034
3035                if (mExportGeometry)
3036                        exporter->ExportGeometry(objects);
3037
3038                delete exporter;
3039        }
3040}
3041
3042
3043void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3044                                                                                  const VssRayContainer &rays)
3045{
3046        const int leafOut = 10;
3047
3048        ViewCell::NewMail();
3049
3050        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
3051        Debug << "\nOutput view cells: " << endl;
3052
3053        // sort view cells to visualize the largest view cells
3054        if (0)
3055                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
3056
3057        int limit = min(leafOut, (int)mViewCells.size());
3058
3059        int raysOut;
3060
3061        //-- some rays for output
3062        if (1)
3063                raysOut = min((int)rays.size(), mVisualizationSamples);
3064
3065        for (int i = 0; i < limit; ++ i)
3066        {
3067                cout << "creating output for view cell " << i << " ... ";
3068
3069                VssRayContainer vcRays;
3070                Intersectable::NewMail();
3071                ViewCell *vc;
3072       
3073                if (0) // largest view cell pvs first
3074                        vc = mViewCells[i];
3075                else
3076                        vc = mViewCells[Random((int)mViewCells.size())];
3077
3078                vector<ViewCell *> leaves;
3079                mViewCellsTree->CollectLeaves(vc, leaves);
3080
3081        if (1)
3082                {
3083                        // check whether we can add the current ray to the output rays
3084                        for (int k = 0; k < raysOut; ++ k)
3085                        {
3086                                VssRay *ray = rays[k];
3087                                for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3088                                {
3089                                        ViewCell *rayvc = ray->mViewCells[j];
3090
3091                                        if (leaves[0] == rayvc)
3092                                                vcRays.push_back(ray);
3093                                }
3094                        }
3095                }
3096
3097                //bspLeaves[j]->Mail();
3098                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3099                Exporter *exporter = Exporter::GetExporter(s);
3100                exporter->SetWireframe();
3101
3102                Material m;//= RandomMaterial();
3103                m.mDiffuseColor = RgbColor(0, 1, 0);
3104                exporter->SetForcedMaterial(m);
3105
3106                ExportViewCellGeometry(exporter, vc);
3107
3108
3109                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc)
3110                          << ", piercing rays=" << (int)vcRays.size() << endl;
3111                        //  << ", leaves=" << (int)vc->mLeaves.size() << endl;
3112
3113               
3114                //-- export rays piercing this view cell
3115                if (1)
3116                {
3117                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
3118                }
3119                else
3120                {
3121
3122                        ViewCellContainer leaves;
3123                        mViewCellsTree->CollectLeaves(vc, leaves);
3124
3125                        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3126
3127                        for (lit = leaves.begin(); lit != lit_end; ++ lit)
3128                        {
3129                                BspLeaf *l = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3130                                exporter->ExportRays(l->mVssRays);
3131                        }
3132                }
3133
3134       
3135                m.mDiffuseColor = RgbColor(1, 0, 0);
3136                exporter->SetForcedMaterial(m);
3137
3138                ObjectPvsMap::const_iterator it,
3139                        it_end = vc->GetPvs().mEntries.end();
3140
3141                exporter->SetFilled();
3142
3143       
3144                // output PVS of view cell
3145                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
3146                {
3147               
3148                        Intersectable *intersect = (*it).first;
3149
3150                        if (!intersect->Mailed())
3151                        {
3152                                Material m = RandomMaterial();
3153                                exporter->SetForcedMaterial(m);
3154
3155                                exporter->ExportIntersectable(intersect);
3156                                intersect->Mail();
3157                        }
3158                }
3159
3160               
3161                DEL_PTR(exporter);
3162                cout << "finished" << endl;
3163        }
3164
3165        Debug << endl;
3166}
3167
3168
3169int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3170                                                                                        const Vector3 &termination,
3171                                                                                        ViewCellContainer &viewcells)
3172{
3173        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
3174}
3175
3176
3177void VspBspViewCellsManager::ExportColor(Exporter *exporter,
3178                                                                                 ViewCell *vc) const
3179{
3180        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3181
3182        float importance = 0;
3183        static Material m;
3184
3185        switch (mColorCode)
3186        {
3187        case 0: // Random
3188                {
3189                        if (vcValid)
3190                        {
3191                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3192                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3193                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
3194                        }
3195                        else
3196                        {
3197                                m.mDiffuseColor.r = 0.0f;
3198                                m.mDiffuseColor.g = 1.0f;
3199                                m.mDiffuseColor.b = 0.0f;
3200                        }
3201
3202                        exporter->SetForcedMaterial(m);
3203                        return;
3204                }
3205               
3206        case 1: // pvs
3207                {
3208                        importance = (float)vc->GetPvs().GetSize() /
3209                                (float)mViewCellsStats.maxPvs;
3210
3211                }
3212                break;
3213        case 2: // merges
3214                {
3215            int lSize = mViewCellsTree->GetSize(vc);
3216                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
3217                }
3218                break;
3219        case 3: // merge tree differene
3220                {
3221                        importance = (float)GetMaxTreeDiff(vc) /
3222                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3223
3224                }
3225                break;
3226        default:
3227                break;
3228        }
3229
3230        // special color code for invalid view cells
3231        m.mDiffuseColor.r = importance;
3232        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3233        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
3234
3235        //Debug << "importance: " << importance << endl;
3236        exporter->SetForcedMaterial(m);
3237}
3238
3239
3240void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3241                                                    ViewCell *vc,
3242                                                                                                        const Plane3 *cuttingPlane) const
3243{
3244        if (vc->GetMesh())
3245        {
3246                exporter->ExportMesh(vc->GetMesh());
3247       
3248                return;
3249        }
3250
3251       
3252        if (cuttingPlane)
3253        {
3254                ViewCellContainer leaves;
3255                mViewCellsTree->CollectLeaves(vc, leaves);
3256                ViewCellContainer::const_iterator it, it_end = leaves.end();
3257
3258                for (it = leaves.begin(); it != it_end; ++ it)
3259                {
3260                        BspNodeGeometry geom;
3261
3262                        BspNodeGeometry front;
3263                        BspNodeGeometry back;
3264
3265       
3266                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3267
3268                        mVspBspTree->ConstructGeometry(leaf, geom);
3269                       
3270                        geom.SplitGeometry(front,
3271                                                           back,
3272                                                           *cuttingPlane,
3273                                                           mViewSpaceBox,
3274                                                           0.0001f);
3275
3276                        if ((int)back.mPolys.size() >= 3)
3277                                exporter->ExportPolygons(back.mPolys);
3278                }
3279        }
3280        else
3281        {
3282                BspNodeGeometry geom;
3283                mVspBspTree->ConstructGeometry(vc, geom);
3284                       
3285                exporter->ExportPolygons(geom.mPolys);
3286        }
3287}
3288
3289
3290int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3291{
3292        ViewCellContainer leaves;
3293        mViewCellsTree->CollectLeaves(vc, leaves);
3294
3295        int maxDist = 0;
3296       
3297        // compute max height difference
3298        for (int i = 0; i < (int)leaves.size(); ++ i)
3299                for (int j = 0; j < (int)leaves.size(); ++ j)
3300        {
3301                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
3302
3303                if (i != j)
3304                {
3305                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
3306                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3307                        if (dist > maxDist)
3308                                maxDist = dist;
3309                }
3310        }
3311
3312        return maxDist;
3313}
3314
3315
3316ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
3317{
3318        if (!mVspBspTree)
3319                return NULL;
3320
3321        if (!mViewSpaceBox.IsInside(point))
3322          return NULL;
3323
3324        return mVspBspTree->GetViewCell(point);
3325}
3326
3327
3328void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3329{
3330        if (vc->GetMesh())
3331                delete vc->GetMesh();
3332
3333       
3334        BspNodeGeometry geom;
3335
3336        mVspBspTree->ConstructGeometry(vc, geom);
3337       
3338        Mesh *mesh = new Mesh();
3339        geom.AddToMesh(*mesh);
3340        vc->SetMesh(mesh);
3341        mMeshContainer.push_back(mesh);
3342}
3343
3344
3345ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3346                                                                                                  ObjectContainer *objects)
3347{
3348        ViewCellsParser parser;
3349
3350        ViewCellsManager *vm = NULL;
3351
3352        if (parser.ParseFile(filename, &vm, objects))
3353        {
3354                //vm->PrepareLoadedViewCells();
3355                vm->ResetViewCells();
3356
3357                vm->mViewCellsFinished = true;
3358                vm->mMaxPvsSize = (int)objects->size();
3359
3360                vm->FinalizeViewCells(true);
3361
3362                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3363        }
3364        else
3365        {
3366                Debug << "failed loading view cells" << endl;
3367                DEL_PTR(vm);
3368        }
3369
3370
3371        return vm;
3372}
3373
3374
3375inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3376{
3377        return obj1->mId < obj2->mId;
3378}
3379
3380
3381bool VspBspViewCellsManager::ExportViewCells(const string filename)
3382{
3383        cout << "exporting view cells to xml ... ";
3384        std::ofstream stream;
3385
3386        // for output we need unique ids for each view cell
3387        CreateUniqueViewCellIds();
3388
3389
3390        stream.open(filename.c_str());
3391        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3392        stream << "<Visibility_Solution>" << endl;
3393
3394        //-- the view space bounding box
3395        stream << "<ViewSpaceBox"
3396                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3397                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3398
3399        //-- the type of the view cells hierarchy
3400        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3401
3402        //-- load the view cells itself, i.e., the ids and the pvs
3403        stream << "<ViewCells>" << endl;
3404        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3405        for (it = mViewCells.begin(); it != it_end; ++ it)
3406                ExportViewCell(*it, stream);
3407
3408        stream << "</ViewCells>" << endl;
3409
3410        //-- load the hierarchy
3411        stream << "<Hierarchy>" << endl;
3412        mVspBspTree->Export(stream);
3413        stream << endl << "</Hierarchy>" << endl;
3414
3415        stream << "</Visibility_Solution>" << endl;
3416        stream.close();
3417
3418        cout << "finished" << endl;
3419
3420        return true;
3421}
3422
3423
3424int VspBspViewCellsManager::CastBeam(Beam &beam)
3425{
3426        return mVspBspTree->CastBeam(beam);
3427}
3428
3429
3430void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
3431                                                                          const bool createMesh)
3432{
3433        CreateMesh(viewCell);
3434
3435        float area = 0;
3436        float volume = 0;
3437
3438        ViewCellContainer leaves;
3439        mViewCellsTree->CollectLeaves(viewCell, leaves);
3440
3441        ViewCellContainer::const_iterator it, it_end = leaves.end();
3442
3443        for (it = leaves.begin(); it != it_end; ++ it)
3444        {
3445                BspNodeGeometry geom;
3446                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3447                mVspBspTree->ConstructGeometry(leaf, geom);
3448
3449                area += geom.GetArea();
3450                volume += geom.GetVolume();
3451        }
3452
3453        viewCell->SetVolume(volume);
3454        viewCell->SetArea(area);
3455}
3456
3457
3458void VspBspViewCellsManager::PrepareLoadedViewCells()
3459{
3460        // TODO: do I still need this here?
3461        if (0)
3462        mVspBspTree->RepairViewCellsLeafLists();
3463}
3464
3465
3466
3467void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3468                                                                                                        vector<MergeCandidate> &candidates)
3469{       
3470        cout << "collecting merge candidates ... " << endl;
3471
3472        if (mUseRaysForMerge)
3473        {
3474                mVspBspTree->CollectMergeCandidates(rays, candidates);
3475        }
3476        else
3477        {
3478                vector<BspLeaf *> leaves;
3479                mVspBspTree->CollectLeaves(leaves);
3480                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3481        }
3482
3483        cout << "fininshed collecting candidates" << endl;
3484}
3485
3486
3487void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
3488{
3489        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3490        for (it = mViewCells.begin(); it != it_end; ++ it)
3491        {
3492        }
3493}
3494
3495//////////////////////////////////
3496ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3497{
3498        //TODO
3499        return NULL;// new VspBspViewCellsManager();
3500}
3501
Note: See TracBrowser for help on using the repository browser.