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

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