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

Revision 607, 79.1 KB checked in by mattausch, 18 years ago (diff)

added method for associating spatial hierarchy leaf with view cell

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