source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp @ 651

Revision 651, 82.5 KB checked in by mattausch, 19 years ago (diff)

exporting / loading full merge hierarchy

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