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

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

added switch for loading polys as meshes

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                        if (0 && mExportRays)
1054                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
1055                       
1056                        if (mExportGeometry)
1057                                exporter->ExportGeometry(objects);
1058
1059                        //exporter->SetWireframe();
1060                        exporter->SetFilled();
1061                        ExportViewCellsForViz(exporter);
1062
1063
1064                        delete exporter;
1065                }
1066                cout << "finished" << endl;
1067        }
1068
1069
1070        return sampleContributions;
1071}
1072
1073
1074void BspViewCellsManager::CollectViewCells()
1075{
1076        // view cells tree constructed
1077        if (!ViewCellsTreeConstructed())
1078        {               
1079                mBspTree->CollectViewCells(mViewCells);
1080        }
1081        else
1082        {
1083                // we can use the view cells tree hierarchy to get the right set
1084                mViewCellsTree->CollectBestViewCellSet(mViewCells,
1085                                                                                           mNumActiveViewCells);
1086        }
1087}
1088
1089
1090float BspViewCellsManager::GetProbability(ViewCell *viewCell)
1091{
1092        // compute view cell area as subsititute for probability
1093        if (1)
1094                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1095        else
1096                return GetArea(viewCell) / GetAccVcArea();
1097}
1098
1099
1100
1101int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1102                                                                                 const Vector3 &termination,
1103                                                                                 ViewCellContainer &viewcells)
1104{
1105        return mBspTree->CastLineSegment(origin, termination, viewcells);
1106}
1107
1108
1109int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
1110                                                                         const VssRayContainer &rays)
1111{
1112        if (!ViewCellsConstructed())
1113        {
1114                Debug << "view cells not constructed" << endl;
1115                return 0;
1116        }
1117
1118       
1119        // view cells already finished before post processing step (i.e. because they were loaded)
1120        if (mViewCellsFinished)
1121        {
1122                FinalizeViewCells(true);
1123                EvaluateViewCellsStats();
1124
1125                return 0;
1126        }
1127
1128        //-- post processing of bsp view cells
1129
1130    int vcSize = 0;
1131        int pvsSize = 0;
1132
1133        EvaluateViewCellsStats();
1134        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
1135
1136        mRenderer->RenderScene();
1137        SimulationStatistics ss;
1138        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
1139
1140    Debug << ss << endl;
1141
1142       
1143
1144        //-- merge view cells
1145        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1146        long startTime = GetTime();
1147       
1148        VssRayContainer postProcessRays;
1149        GetRaySets(rays, mPostProcessSamples, postProcessRays);
1150
1151        if (mMergeViewCells)
1152        {
1153                Debug << "constructing visibility based merge tree" << endl;
1154                mViewCellsTree->ConstructMergeTree(rays, objects);
1155        }
1156        else
1157        {
1158                Debug << "constructing spatial merge tree" << endl;
1159                // create spatial merge hierarchy
1160                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mBspTree->GetRoot()));
1161        }
1162
1163        mViewCellsTree->ExportStats();
1164
1165        //-- stats and visualizations
1166        cout << "finished" << endl;
1167        cout << "merged view cells in "
1168                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
1169
1170        Debug << "Postprocessing: Merged view cells in "
1171                << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1172       
1173
1174    // reset view cells and stats
1175        ResetViewCells();
1176        Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
1177
1178        int savedColorCode  = mColorCode;
1179       
1180        //BspLeaf::NewMail();
1181        if (1) // export merged view cells
1182        {
1183                mColorCode = 0;
1184               
1185                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
1186               
1187
1188                cout << "exporting view cells after merge ... ";
1189
1190                if (exporter)
1191                {
1192                        if (mExportGeometry)
1193                                exporter->ExportGeometry(objects);
1194
1195                        //exporter->SetWireframe();
1196                        exporter->SetFilled();
1197                        ExportViewCellsForViz(exporter);
1198
1199
1200                        delete exporter;
1201                }
1202                cout << "finished" << endl;
1203        }
1204
1205        if (1) // export merged view cells
1206        {
1207                mColorCode = 1;
1208
1209                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
1210       
1211                cout << "exporting view cells after merge (pvs size) ... ";     
1212
1213                if (exporter)
1214                {
1215                        //exporter->SetWireframe();
1216                       
1217                        if (mExportGeometry)
1218                                exporter->ExportGeometry(objects);
1219
1220                        //exporter->SetWireframe();
1221                        exporter->SetFilled();
1222                        ExportViewCellsForViz(exporter);
1223
1224                        delete exporter;
1225                }
1226                cout << "finished" << endl;
1227        }
1228
1229        mColorCode = savedColorCode;
1230
1231        FinalizeViewCells(true);
1232       
1233        // write view cells to disc
1234        if (mExportViewCells)
1235        {
1236                char buff[100];
1237                environment->GetStringValue("ViewCells.filename", buff);
1238                string vcFilename(buff);
1239
1240                ExportViewCells(buff);
1241        }
1242
1243        return 0;
1244}
1245
1246
1247BspViewCellsManager::~BspViewCellsManager()
1248{
1249}
1250
1251
1252int BspViewCellsManager::GetType() const
1253{
1254        return BSP;
1255}
1256
1257
1258void BspViewCellsManager::Visualize(const ObjectContainer &objects,
1259                                                                        const VssRayContainer &sampleRays)
1260{
1261        if (!ViewCellsConstructed())
1262                return;
1263       
1264        int savedColorCode = mColorCode;
1265
1266       
1267       
1268        if (1) // export final view cells
1269        {
1270                mColorCode = 1;
1271
1272                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
1273       
1274                cout << "exporting view cells after merge (pvs size) ... ";     
1275
1276                if (exporter)
1277                {
1278                        //exporter->SetWireframe();
1279                       
1280                        if (mExportGeometry)
1281                                exporter->ExportGeometry(objects);
1282
1283                        //exporter->SetWireframe();
1284                        exporter->SetFilled();
1285                        ExportViewCellsForViz(exporter);
1286
1287                        delete exporter;
1288                }
1289                cout << "finished" << endl;
1290        }
1291
1292        mColorCode = savedColorCode;
1293
1294        //-- visualization of the BSP splits
1295        bool exportSplits = false;
1296        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
1297
1298        if (exportSplits)
1299        {
1300                cout << "exporting splits ... ";
1301                ExportSplits(objects);
1302                cout << "finished" << endl;
1303        }
1304
1305        // export single view cells
1306        ExportBspPvs(objects);
1307}
1308
1309
1310inline bool vc_gt(ViewCell *a, ViewCell *b)
1311{
1312        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1313}
1314
1315
1316void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
1317{
1318        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1319
1320        if (exporter)
1321        {
1322                //exporter->SetFilled();
1323
1324                if (mExportGeometry)
1325                        exporter->ExportGeometry(objects);
1326
1327                Material m;
1328                m.mDiffuseColor = RgbColor(1, 0, 0);
1329                exporter->SetForcedMaterial(m);
1330                exporter->SetWireframe();
1331
1332                exporter->ExportBspSplits(*mBspTree, true);
1333
1334                //NOTE: take forced material, else big scenes cannot be viewed
1335                m.mDiffuseColor = RgbColor(0, 1, 0);
1336                exporter->SetForcedMaterial(m);
1337                //exporter->ResetForcedMaterial();
1338
1339                delete exporter;
1340        }
1341}
1342
1343
1344void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
1345{
1346        const int leafOut = 10;
1347
1348        ViewCell::NewMail();
1349
1350        //-- some rays for output
1351        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
1352
1353        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1354        Debug << "\nOutput view cells: " << endl;
1355
1356        // sort view cells to get largest view cells
1357        if (0)
1358                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1359
1360        int limit = min(leafOut, (int)mViewCells.size());
1361
1362        for (int i = 0; i < limit; ++ i)
1363        {
1364                cout << "creating output for view cell " << i << " ... ";
1365                VssRayContainer vcRays;
1366                Intersectable::NewMail();
1367                ViewCell *vc;
1368
1369                if (0)
1370                        vc = mViewCells[i];
1371                else
1372                        vc = mViewCells[Random((int)mViewCells.size())];
1373
1374                cout << "creating output for view cell " << i << " ... ";
1375
1376                if(0)
1377                {
1378                        // check whether we can add the current ray to the output rays
1379                        for (int k = 0; k < raysOut; ++ k)
1380                        {
1381                                BspRay *ray = mBspRays[k];
1382                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1383                                {
1384                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1385                                        if (vc == leaf->GetViewCell())
1386                                                vcRays.push_back(ray->vssRay);
1387                                }
1388                        }
1389                }
1390
1391                //bspLeaves[j]->Mail();
1392                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
1393
1394                Exporter *exporter = Exporter::GetExporter(s);
1395
1396                exporter->SetWireframe();
1397
1398                Material m;//= RandomMaterial();
1399                m.mDiffuseColor = RgbColor(0, 1, 0);
1400                exporter->SetForcedMaterial(m);
1401
1402                ExportViewCellGeometry(exporter, vc);
1403               
1404                // export rays piercing this view cell
1405                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
1406
1407                m.mDiffuseColor = RgbColor(1, 0, 0);
1408                exporter->SetForcedMaterial(m);
1409
1410                ObjectPvsMap::const_iterator it,
1411                        it_end = vc->GetPvs().mEntries.end();
1412
1413                exporter->SetFilled();
1414
1415                // output PVS of view cell
1416                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1417                {
1418                        Intersectable *intersect = (*it).first;
1419
1420                        if (!intersect->Mailed())
1421                        {
1422                                Material m = RandomMaterial();
1423                                exporter->SetForcedMaterial(m);
1424
1425                                exporter->ExportIntersectable(intersect);
1426                                intersect->Mail();
1427                        }
1428                }
1429
1430                DEL_PTR(exporter);
1431                cout << "finished" << endl;
1432        }
1433
1434        Debug << endl;
1435}
1436
1437
1438void BspViewCellsManager::ExportColor(Exporter *exporter,
1439                                                                          ViewCell *vc) const
1440{
1441        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
1442
1443        float importance = 0;
1444        static Material m;
1445
1446        switch (mColorCode)
1447        {
1448        case 0: // Random
1449                {
1450                        if (vcValid)
1451                        {
1452                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
1453                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
1454                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
1455                        }
1456                        else
1457                        {
1458                                m.mDiffuseColor.r = 0.0f;
1459                                m.mDiffuseColor.g = 1.0f;
1460                                m.mDiffuseColor.b = 0.0f;
1461                        }
1462
1463                        exporter->SetForcedMaterial(m);
1464                        return;
1465                }
1466               
1467        case 1: // pvs
1468                {
1469                        importance = (float)vc->GetPvs().GetSize() /
1470                                (float)mViewCellsStats.maxPvs;
1471
1472                }
1473                break;
1474        case 2: // merges
1475                {
1476            int lSize = mViewCellsTree->GetSize(vc);
1477                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
1478                }
1479                //break;
1480        case 3: // merge tree differene
1481                {
1482                        // TODO
1483                        //importance = (float)GetMaxTreeDiff(vc) /
1484                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
1485
1486                }
1487                break;
1488        default:
1489                break;
1490        }
1491
1492        // special color code for invalid view cells
1493        m.mDiffuseColor.r = importance;
1494        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1495        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
1496
1497        //Debug << "importance: " << importance << endl;
1498        exporter->SetForcedMaterial(m);
1499}
1500
1501
1502void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1503                                                                                                 ViewCell *vc,
1504                                                                                                 const Plane3 *cuttingPlane) const
1505{
1506        if (vc->GetMesh())
1507        {
1508                exporter->ExportMesh(vc->GetMesh());
1509                return;
1510        }
1511
1512        BspNodeGeometry geom;
1513        mBspTree->ConstructGeometry(vc, geom);
1514
1515
1516        if (cuttingPlane)
1517        {
1518                BspNodeGeometry front;
1519                BspNodeGeometry back;
1520
1521                geom.SplitGeometry(front,
1522                                                   back,
1523                                                   *cuttingPlane,
1524                                                   mViewSpaceBox,
1525                                                   0.0001f);
1526
1527                if ((int)back.mPolys.size() >= 3)
1528                        exporter->ExportPolygons(back.mPolys);
1529        }
1530        else
1531        {
1532               
1533                exporter->ExportPolygons(geom.mPolys);
1534        }
1535}
1536
1537
1538void BspViewCellsManager::CreateMesh(ViewCell *vc)
1539{
1540        if (vc->GetMesh())
1541                delete vc->GetMesh();
1542
1543        BspNodeGeometry geom;
1544       
1545        mBspTree->ConstructGeometry(vc, geom);
1546
1547        Mesh *mesh = new Mesh();
1548        geom.AddToMesh(*mesh);
1549        vc->SetMesh(mesh);
1550        mMeshContainer.push_back(mesh);
1551}
1552
1553
1554void BspViewCellsManager::Finalize(ViewCell *viewCell,
1555                                                                   const bool createMesh)
1556{
1557        CreateMesh(viewCell);
1558
1559        float area = 0;
1560        float volume = 0;
1561
1562        ViewCellContainer leaves;
1563        mViewCellsTree->CollectLeaves(viewCell, leaves);
1564
1565        ViewCellContainer::const_iterator it, it_end = leaves.end();
1566
1567        for (it = leaves.begin(); it != it_end; ++ it)
1568        {
1569                BspNodeGeometry geom;
1570                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
1571                mBspTree->ConstructGeometry(leaf, geom);
1572
1573                area += geom.GetArea();
1574                volume += geom.GetVolume();
1575        }
1576
1577        viewCell->SetVolume(volume);
1578        viewCell->SetArea(area);
1579}
1580
1581
1582ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
1583{
1584        if (!mBspTree)
1585                return NULL;
1586
1587        if (!mViewSpaceBox.IsInside(point))
1588                return NULL;
1589       
1590        return mBspTree->GetViewCell(point);
1591}
1592
1593
1594void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
1595                                                                                                 vector<MergeCandidate> &candidates)
1596{
1597        cout << "collecting merge candidates ... " << endl;
1598
1599        if (mUseRaysForMerge)
1600        {
1601                mBspTree->CollectMergeCandidates(rays, candidates);
1602        }
1603        else
1604        {
1605                vector<BspLeaf *> leaves;
1606                mBspTree->CollectLeaves(leaves);
1607                mBspTree->CollectMergeCandidates(leaves, candidates);
1608        }
1609
1610        cout << "fininshed collecting candidates" << endl;
1611}
1612
1613
1614
1615bool BspViewCellsManager::ExportViewCells(const string filename)
1616{
1617        cout << "exporting view cells to xml ... ";
1618        std::ofstream stream;
1619
1620        // for output we need unique ids for each view cell
1621        CreateUniqueViewCellIds();
1622
1623
1624        stream.open(filename.c_str());
1625        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
1626        stream << "<Visibility_Solution>" << endl;
1627
1628        //-- the view space bounding box
1629        stream << "<ViewSpaceBox"
1630                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
1631                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
1632
1633        //-- the type of the view cells hierarchy
1634        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
1635        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
1636        //-- load the view cells itself, i.e., the ids and the pvs
1637        stream << "<ViewCells>" << endl;
1638
1639#if 0
1640       
1641        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1642               
1643        for (it = mViewCells.begin(); it != it_end; ++ it)
1644                ExportViewCell(*it, stream);
1645#else
1646        mViewCellsTree->Export(stream);
1647#endif
1648
1649        stream << "</ViewCells>" << endl;
1650
1651        //-- load the hierarchy
1652        stream << "<Hierarchy>" << endl;
1653        mBspTree->Export(stream);
1654        stream << endl << "</Hierarchy>" << endl;
1655
1656        stream << "</Visibility_Solution>" << endl;
1657        stream.close();
1658
1659        cout << "finished" << endl;
1660
1661        return true;
1662}
1663
1664
1665void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
1666{
1667        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1668        for (it = mViewCells.begin(); it != it_end; ++ it)
1669        {
1670                ViewCell *vc = *it;
1671                ViewCellContainer leaves;
1672                mViewCellsTree->CollectLeaves(vc, leaves);
1673               
1674                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
1675
1676                for (lit = leaves.begin(); lit != lit_end; ++ lit)
1677                {
1678                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
1679                        bspVc->mLeaf->SetViewCell(vc);
1680                }
1681        }
1682}
1683
1684
1685ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
1686{
1687        if (root->IsLeaf())
1688        {
1689                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
1690
1691                viewCell->SetMergeCost(0.0f);
1692
1693                return viewCell;
1694        }
1695       
1696        BspInterior *interior = dynamic_cast<BspInterior *>(root);
1697        ViewCellInterior *viewCellInterior = new ViewCellInterior();
1698               
1699        float mergeCost = 1.0f / (float)root->mTimeStamp;
1700        //Debug << "timestamp: " << root->mTimeStamp;
1701        //Debug << "merge cost: " << mergeCost << endl;
1702
1703        viewCellInterior->SetMergeCost(mergeCost);
1704
1705        float volume = 0;
1706       
1707        BspNode *front = interior->GetFront();
1708        BspNode *back = interior->GetBack();
1709
1710        // recursivly compute child hierarchies
1711        ViewCell *backVc = ConstructSpatialMergeTree(back);
1712        ViewCell *frontVc = ConstructSpatialMergeTree(front);
1713
1714        viewCellInterior->SetupChildLink(frontVc);
1715        viewCellInterior->SetupChildLink(backVc);
1716
1717
1718        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
1719        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
1720
1721        volume += backVc->GetVolume();
1722        volume += frontVc->GetVolume();
1723
1724        viewCellInterior->SetVolume(volume);
1725
1726        return viewCellInterior;
1727}
1728
1729
1730/************************************************************************/
1731/*                   KdViewCellsManager implementation                  */
1732/************************************************************************/
1733
1734
1735
1736KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
1737ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
1738{
1739}
1740
1741
1742float KdViewCellsManager::GetProbability(ViewCell *viewCell)
1743{
1744        // compute view cell area / volume as subsititute for probability
1745        if (0)
1746                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1747        else
1748                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1749}
1750
1751
1752
1753
1754void KdViewCellsManager::CollectViewCells()
1755{
1756        //mKdTree->CollectViewCells(mViewCells); TODO
1757}
1758
1759
1760int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1761                                                                  const VssRayContainer &rays)
1762{
1763        // if view cells already constructed
1764        if (ViewCellsConstructed())
1765                return 0;
1766
1767        mKdTree->Construct();
1768
1769        mTotalAreaValid = false;
1770        // create the view cells
1771        mKdTree->CreateAndCollectViewCells(mViewCells);
1772
1773        // cast rays
1774        ComputeSampleContributions(rays, true, false);
1775
1776        EvaluateViewCellsStats();
1777        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1778
1779        return 0;
1780}
1781
1782
1783bool KdViewCellsManager::ViewCellsConstructed() const
1784{
1785        return mKdTree->GetRoot() != NULL;
1786}
1787
1788int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1789                                                                        const VssRayContainer &rays)
1790{
1791        return 0;
1792}
1793
1794void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1795                                                                   const VssRayContainer &sampleRays)
1796{
1797        if (!ViewCellsConstructed())
1798                return;
1799
1800        // using view cells instead of the kd PVS of objects
1801        const bool useViewCells = true;
1802        bool exportRays = false;
1803
1804        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1805        const int pvsOut = min((int)objects.size(), 10);
1806        VssRayContainer *rays = new VssRayContainer[pvsOut];
1807
1808        if (useViewCells)
1809        {
1810                const int leafOut = 10;
1811
1812                ViewCell::NewMail();
1813
1814                //-- some rays for output
1815                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1816                Debug << "visualization using " << raysOut << " samples" << endl;
1817
1818                //-- some random view cells and rays for output
1819                vector<KdLeaf *> kdLeaves;
1820
1821                for (int i = 0; i < leafOut; ++ i)
1822                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1823
1824                for (int i = 0; i < kdLeaves.size(); ++ i)
1825                {
1826                        KdLeaf *leaf = kdLeaves[i];
1827                        RayContainer vcRays;
1828
1829                        cout << "creating output for view cell " << i << " ... ";
1830#if 0
1831                        // check whether we can add the current ray to the output rays
1832                        for (int k = 0; k < raysOut; ++ k)
1833                        {
1834                                Ray *ray = sampleRays[k];
1835
1836                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1837                                {
1838                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1839
1840                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1841                                        {
1842                                                vcRays.push_back(ray);
1843                                        }
1844                                }
1845                        }
1846#endif
1847                        Intersectable::NewMail();
1848
1849                        ViewCell *vc = leaf->mViewCell;
1850
1851                        //bspLeaves[j]->Mail();
1852                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1853
1854                        Exporter *exporter = Exporter::GetExporter(s);
1855                        exporter->SetFilled();
1856
1857                        exporter->SetWireframe();
1858                        //exporter->SetFilled();
1859
1860                        Material m;//= RandomMaterial();
1861                        m.mDiffuseColor = RgbColor(1, 1, 0);
1862                        exporter->SetForcedMaterial(m);
1863
1864                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1865                        exporter->ExportBox(box);
1866
1867                        // export rays piercing this view cell
1868                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1869
1870                        m.mDiffuseColor = RgbColor(1, 0, 0);
1871                        exporter->SetForcedMaterial(m);
1872
1873                        // exporter->SetWireframe();
1874                        exporter->SetFilled();
1875
1876                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1877                        // output PVS of view cell
1878                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1879                        {
1880                                Intersectable *intersect = (*it).first;
1881                                if (!intersect->Mailed())
1882                                {
1883                                        exporter->ExportIntersectable(intersect);
1884                                        intersect->Mail();
1885                                }
1886                        }
1887
1888                        DEL_PTR(exporter);
1889                        cout << "finished" << endl;
1890                }
1891
1892                DEL_PTR(rays);
1893        }
1894        else // using kd PVS of objects
1895        {
1896                for (int i = 0; i < limit; ++ i)
1897                {
1898                        VssRay *ray = sampleRays[i];
1899
1900                        // check whether we can add this to the rays
1901                        for (int j = 0; j < pvsOut; j++)
1902                        {
1903                                if (objects[j] == ray->mTerminationObject)
1904                                {
1905                                        rays[j].push_back(ray);
1906                                }
1907                        }
1908                }
1909
1910                if (exportRays)
1911                {
1912                        Exporter *exporter = NULL;
1913                        exporter = Exporter::GetExporter("sample-rays.x3d");
1914                        exporter->SetWireframe();
1915                        exporter->ExportKdTree(*mKdTree);
1916
1917                        for (i=0; i < pvsOut; i++)
1918                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1919
1920                        exporter->SetFilled();
1921
1922                        delete exporter;
1923                }
1924
1925                for (int k=0; k < pvsOut; k++)
1926                {
1927                        Intersectable *object = objects[k];
1928                        char s[64];
1929                        sprintf(s, "sample-pvs%04d.x3d", k);
1930
1931                        Exporter *exporter = Exporter::GetExporter(s);
1932                        exporter->SetWireframe();
1933
1934                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1935                        Intersectable::NewMail();
1936
1937                        // avoid adding the object to the list
1938                        object->Mail();
1939                        ObjectContainer visibleObjects;
1940
1941                        for (; i != object->mKdPvs.mEntries.end(); i++)
1942                        {
1943                                KdNode *node = (*i).first;
1944                                exporter->ExportBox(mKdTree->GetBox(node));
1945
1946                                mKdTree->CollectObjects(node, visibleObjects);
1947                        }
1948
1949                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1950                        exporter->SetFilled();
1951
1952                        for (int j = 0; j < visibleObjects.size(); j++)
1953                                exporter->ExportIntersectable(visibleObjects[j]);
1954
1955                        Material m;
1956                        m.mDiffuseColor = RgbColor(1, 0, 0);
1957                        exporter->SetForcedMaterial(m);
1958                        exporter->ExportIntersectable(object);
1959
1960                        delete exporter;
1961                }
1962        }
1963}
1964
1965
1966void KdViewCellsManager::ExportColor(Exporter *exporter,
1967                                                                         ViewCell *vc) const
1968{
1969        // TODO
1970}
1971
1972ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1973{
1974        return new KdViewCell(mesh);
1975}
1976
1977
1978void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
1979                                                                                                ViewCell *vc,
1980                                                                                                const Plane3 *cuttingPlane) const
1981{
1982        ViewCellContainer leaves;
1983
1984        mViewCellsTree->CollectLeaves(vc, leaves);
1985        ViewCellContainer::const_iterator it, it_end = leaves.end();
1986
1987        for (it = leaves.begin(); it != it_end; ++ it)
1988        {
1989                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
1990       
1991                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
1992        }
1993}
1994
1995
1996int KdViewCellsManager::GetType() const
1997{
1998        return ViewCellsManager::KD;
1999}
2000
2001
2002
2003KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
2004{
2005        KdNode *node = leaf;
2006
2007        while (node->mParent && node->mDepth > mKdPvsDepth)
2008                node = node->mParent;
2009        return node;
2010}
2011
2012int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
2013                                                                                const Vector3 &termination,
2014                                                                                ViewCellContainer &viewcells)
2015{
2016        return mKdTree->CastLineSegment(origin, termination, viewcells);
2017}
2018
2019
2020void KdViewCellsManager::CreateMesh(ViewCell *vc)
2021{
2022        // TODO
2023}
2024
2025
2026
2027void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2028                                                                                                vector<MergeCandidate> &candidates)
2029{
2030        // TODO
2031}
2032
2033
2034/**********************************************************************/
2035/*                   VspKdViewCellsManager implementation             */
2036/**********************************************************************/
2037
2038
2039VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
2040ViewCellsManager(), mVspKdTree(vspKdTree)
2041{
2042        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
2043        mVspKdTree->SetViewCellsManager(this);
2044}
2045
2046float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
2047{
2048        // compute view cell area / volume as subsititute for probability
2049        if (0)
2050                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2051        else
2052                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
2053}
2054
2055
2056
2057
2058void VspKdViewCellsManager::CollectViewCells()
2059{
2060        mVspKdTree->CollectViewCells(mViewCells);
2061}
2062
2063
2064int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2065                                                                                                const VssRayContainer &rays)
2066{
2067        // if view cells already constructed
2068        if (ViewCellsConstructed())
2069                return 0;
2070
2071        VssRayContainer constructionRays;
2072        VssRayContainer savedRays;
2073
2074        GetRaySets(rays,
2075                           mInitialSamples,
2076                           constructionRays,
2077                           &savedRays);
2078
2079        Debug << "constructing vsp kd tree using "
2080                  << (int)constructionRays.size() << " samples" << endl;
2081
2082        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
2083        Debug << mVspKdTree->GetStatistics() << endl;
2084
2085        // export leaf building blocks
2086        ExportLeaves(objects, rays);
2087
2088        // finally merge kd leaf building blocks to view cells
2089        const int merged = mVspKdTree->MergeViewCells(rays);
2090
2091        // collapse siblings belonging to the same view cell
2092        mVspKdTree->RefineViewCells(rays);
2093
2094        // collapse siblings belonging to the same view cell
2095        mVspKdTree->CollapseTree();
2096
2097        // evaluale view cell stats
2098        ResetViewCells();
2099
2100        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2101
2102        long startTime = GetTime();
2103        // recast rest of rays
2104        ComputeSampleContributions(savedRays, true, false);
2105
2106        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2107                  << " secs" << endl;
2108
2109        return merged;
2110}
2111
2112bool VspKdViewCellsManager::ViewCellsConstructed() const
2113{
2114        return mVspKdTree->GetRoot() != NULL;
2115}
2116
2117
2118ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2119{
2120        return new VspKdViewCell(mesh);
2121}
2122
2123int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
2124                                                                           const VssRayContainer &rays)
2125{
2126        if (!ViewCellsConstructed())
2127                return 0;
2128
2129        // recalculate stats
2130        EvaluateViewCellsStats();
2131
2132        return 0;
2133}
2134
2135
2136void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2137                                                                                 const VssRayContainer &sampleRays)
2138{
2139        if (!ViewCellsConstructed())
2140                return;
2141
2142        //-- export leaf building blocks
2143        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
2144        if (!exporter)
2145                return;
2146
2147        if (mExportGeometry)
2148                exporter->ExportGeometry(objects);
2149       
2150        //exporter->SetWireframe();
2151        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2152        exporter->ExportVspKdTree(*mVspKdTree);
2153
2154        if (mExportRays)
2155        {
2156                const float prob = (float)mVisualizationSamples
2157                        / ((float)sampleRays.size() + Limits::Small);
2158
2159                exporter->SetWireframe();
2160
2161                //-- collect uniformly distributed rays
2162                VssRayContainer rays;
2163
2164                for (int i = 0; i < sampleRays.size(); ++ i)
2165                {
2166                        if (RandomValue(0,1) < prob)
2167                                rays.push_back(sampleRays[i]);
2168                }
2169                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2170        }
2171
2172        delete exporter;
2173}
2174
2175void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2176                                                                          const VssRayContainer &sampleRays)
2177{
2178        if (!ViewCellsConstructed())
2179                return;
2180
2181        //-- export single view cells
2182        for (int i = 0; i < 10; ++ i)
2183        {
2184                char s[64];
2185                sprintf(s, "vsp_viewcell%04d.x3d", i);
2186                Exporter *exporter = Exporter::GetExporter(s);
2187                const int idx =
2188                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
2189
2190                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
2191
2192                //-- export geometry
2193                Material m;
2194                m.mDiffuseColor = RgbColor(0, 1, 1);
2195
2196                exporter->SetForcedMaterial(m);
2197                exporter->SetWireframe();
2198
2199                ExportViewCellGeometry(exporter, vc);
2200
2201                //-- export stored rays
2202               
2203                if (mExportRays)
2204                {
2205                        ViewCellContainer leaves;
2206                        mViewCellsTree->CollectLeaves(vc, leaves);
2207
2208                        ViewCellContainer::const_iterator it,
2209                                it_end = leaves.end();
2210
2211                        for (it = leaves.begin(); it != it_end; ++ it)
2212                        {
2213                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2214                                VspKdLeaf *leaf = vspKdVc->mLeaf;
2215                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
2216
2217                                VssRayContainer vssRays;
2218
2219                                VssRayContainer castRays;
2220                                VssRayContainer initRays;
2221
2222                                leaf->GetRays(vssRays);
2223
2224                                VssRayContainer::const_iterator it, it_end = vssRays.end();
2225                                const float prop = 200.0f / (float)vssRays.size();
2226
2227                                for (it = vssRays.begin(); it != it_end; ++ it)
2228                                {
2229                                        if (Random(1) < prop)
2230                                                if ((*it)->mTerminationObject == NULL)
2231                                                        castRays.push_back(*it);
2232                                                else
2233                                                        initRays.push_back(*it);
2234                                }
2235
2236                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2237                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
2238                        }
2239                }
2240       
2241                //-- output PVS of view cell
2242                m.mDiffuseColor = RgbColor(1, 0, 0);
2243                exporter->SetForcedMaterial(m);
2244
2245                Intersectable::NewMail();
2246
2247                ObjectPvsMap::const_iterator it,
2248                        it_end = vc->GetPvs().mEntries.end();
2249
2250                exporter->SetFilled();
2251
2252                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2253                {
2254                        Intersectable *intersect = (*it).first;
2255
2256                        if (!intersect->Mailed())
2257                        {
2258                                Material m = RandomMaterial();
2259                                exporter->SetForcedMaterial(m);
2260
2261                                exporter->ExportIntersectable(intersect);
2262                                intersect->Mail();
2263                        }
2264                }
2265
2266                delete exporter;
2267        }
2268
2269        //-- export final view cells
2270        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2271
2272        //if (exportGeometry) exporter->SetWireframe();
2273        //else exporter->SetFilled();
2274
2275        ExportViewCellsForViz(exporter);
2276
2277        if (mExportGeometry)
2278        {
2279                exporter->SetFilled();
2280                exporter->ExportGeometry(objects);
2281        }
2282
2283        if (mExportRays)
2284        {
2285                const float prob = (float)mVisualizationSamples
2286                        / ((float)sampleRays.size() + Limits::Small);
2287
2288                exporter->SetWireframe();
2289
2290                VssRayContainer rays;
2291
2292                for (int i = 0; i < sampleRays.size(); ++ i)
2293                {
2294                  if (RandomValue(0,1) < prob)
2295                        rays.push_back(sampleRays[i]);
2296                }
2297                exporter->ExportRays(rays, RgbColor(1, 0, 0));
2298        }
2299
2300        delete exporter;
2301}
2302
2303int VspKdViewCellsManager::GetType() const
2304{
2305        return VSP_KD;
2306}
2307
2308
2309int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2310                                                                                   const Vector3 &termination,
2311                                                                                   ViewCellContainer &viewcells)
2312{
2313        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
2314}
2315
2316
2317void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2318                                                                                ViewCell *vc) const
2319{
2320        if (mColorCode == 0) // Random color
2321                return;
2322
2323        float importance = 0;
2324
2325        switch (mColorCode)
2326        {
2327        case 1: // pvs
2328                {
2329                        importance = (float)vc->GetPvs().GetSize() /
2330                                (float)mViewCellsStats.maxPvs;
2331                }
2332                break;
2333        case 2: // merged leaves
2334                {
2335                int lSize = mViewCellsTree->GetSize(vc);
2336                        importance = (float)lSize /
2337                                (float)mViewCellsStats.maxLeaves;
2338                }
2339                break;
2340        case 3: // merged tree depth difference
2341                {
2342                        //importance = (float)GetMaxTreeDiff(vc) /
2343                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2344                }
2345                break;
2346        default:
2347                break;
2348        }
2349
2350        Material m;
2351        m.mDiffuseColor.b = 1.0f;
2352        m.mDiffuseColor.r = importance;
2353        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2354        //Debug << "importance: " << importance << endl;
2355        exporter->SetForcedMaterial(m);
2356}
2357
2358
2359void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
2360                                                                                                   ViewCell *vc,
2361                                                                                                   const Plane3 *cuttingPlane) const
2362{
2363        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2364
2365        Mesh m;
2366
2367        ViewCellContainer leaves;
2368        mViewCellsTree->CollectLeaves(vc, leaves);
2369
2370        ViewCellContainer::const_iterator it, it_end = leaves.end();
2371
2372        for (it = leaves.begin(); it != it_end; ++ it)
2373        {
2374                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2375                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
2376        }
2377
2378        exporter->ExportMesh(&m);
2379}
2380
2381
2382void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2383{
2384        //TODO
2385}
2386
2387
2388void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2389                                                                                                   vector<MergeCandidate> &candidates)
2390{
2391        // TODO
2392}
2393
2394
2395/**************************************************************************/
2396/*                   VspBspViewCellsManager implementation                */
2397/**************************************************************************/
2398
2399
2400VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
2401ViewCellsManager(), mVspBspTree(vspBspTree)
2402{
2403        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
2404        mVspBspTree->SetViewCellsManager(this);
2405        mVspBspTree->mViewCellsTree = mViewCellsTree;
2406}
2407
2408
2409VspBspViewCellsManager::~VspBspViewCellsManager()
2410{
2411}
2412
2413
2414float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
2415{
2416        if (0 && mVspBspTree->mUseAreaForPvs)
2417                return GetArea(viewCell) / GetAccVcArea();
2418        else
2419                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
2420}
2421
2422
2423void VspBspViewCellsManager::CollectViewCells()
2424{
2425        // view cells tree constructed
2426        if (!ViewCellsTreeConstructed())
2427        {
2428                mVspBspTree->CollectViewCells(mViewCells, false);
2429        }
2430        else
2431        {
2432                // we can use the view cells tree hierarchy to get the right set
2433                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
2434        }
2435
2436}
2437
2438
2439
2440bool VspBspViewCellsManager::ViewCellsConstructed() const
2441{
2442        return mVspBspTree->GetRoot() != NULL;
2443}
2444
2445
2446ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2447{
2448        return new BspViewCell(mesh);
2449}
2450
2451
2452/*void VspBspViewCellsManager::CollectNodes(ViewCell *vc, vector<BspNode *>nodes)
2453{
2454        void ViewCellsTree::CollectLeaves(ViewCell *vc, vector<BspNode *> &nodes) const
2455       
2456        if (vc->IsLeaf())
2457        {
2458                BspViewCell *bvc = dynamic_cast<BspViewCell *>(vc);
2459                nodes->push_back(bvc->mLeaf);
2460        }
2461        else
2462        {
2463                ViewCellContainer::const_iterator it, it_end = interior->mChildren.end();
2464
2465                for (it = interior->mChildren.begin; it != it_end; ++ it)
2466                {
2467                        vector<BspNode *> mynodes;
2468                        CollectNodes(*it, mynodes);
2469
2470                        if (mynodes[0]->GetParent() && (mynodes[0]->GetParent() == mynodes[1]->GetParent()))
2471                        {
2472                                nodes.push_back(nodes[0]->GetParent());
2473                        }
2474
2475                }
2476        }
2477}*/
2478
2479
2480int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2481                                                                                                 const VssRayContainer &rays)
2482{
2483        // if view cells were already constructed
2484        if (ViewCellsConstructed())
2485                return 0;
2486
2487        Debug << "Constructing bsp view cells" << endl;
2488
2489        int sampleContributions = 0;
2490
2491        VssRayContainer sampleRays;
2492
2493        int limit = min (mInitialSamples, (int)rays.size());
2494
2495        VssRayContainer constructionRays;
2496        VssRayContainer savedRays;
2497
2498        Debug << "samples used for subdivision: " << mInitialSamples
2499                  << " rays: " << (int)rays.size() << endl;
2500
2501        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
2502
2503        Debug << "initial rays: " << (int)constructionRays.size() << endl;
2504        Debug << "saved rays: " << (int)savedRays.size() << endl;
2505
2506        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
2507
2508        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
2509
2510        Debug << mVspBspTree->GetStatistics() << endl;
2511
2512        // collapse invalid regions
2513        cout << "collapsing invalid tree regions ... ";
2514        long startTime = GetTime();
2515        int collapsedLeaves = mVspBspTree->CollapseTree();
2516        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
2517                  << " seconds" << endl;
2518
2519    cout << "finished" << endl;
2520
2521        cout << "reseting view cell stats ... ";
2522        ResetViewCells();
2523        cout << "finished" << endl;
2524
2525        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2526
2527        if (0) // export initial view cells
2528        {
2529                cout << "exporting initial view cells (=leaves) ... ";
2530                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
2531
2532                if (exporter)
2533                {
2534                        if (0 && mExportRays)
2535                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
2536
2537                        if (mExportGeometry)
2538                                exporter->ExportGeometry(objects);
2539
2540                        //exporter->SetWireframe();
2541                        exporter->SetFilled();
2542                        ExportViewCellsForViz(exporter);
2543
2544                        delete exporter;
2545                }
2546                cout << "finished" << endl;
2547        }
2548
2549        startTime = GetTime();
2550
2551        // reset view cells and stats
2552        ResetViewCells();
2553
2554        cout << "Computing remaining ray contributions ... ";
2555
2556        // recast rest of rays
2557        if (SAMPLE_AFTER_SUBDIVISION)
2558                ComputeSampleContributions(savedRays, true, false);
2559        cout << "finished" << endl;
2560
2561        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2562                  << " secs" << endl;
2563
2564        cout << "construction finished" << endl;
2565
2566        return sampleContributions;
2567}
2568
2569
2570void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2571                                                                                        const ObjectContainer &objects)
2572{
2573        //-- post processing of bsp view cells
2574    int vcSize = 0;
2575        int pvsSize = 0;
2576
2577        mRenderer->RenderScene();
2578        SimulationStatistics ss;
2579        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2580    Debug << ss << endl;
2581
2582        //-- merge view cells
2583       
2584        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
2585        long startTime = GetTime();
2586
2587
2588        if (mMergeViewCells)
2589        {
2590                Debug << "merging view cells" << endl;
2591                // TODO: should be done BEFORE the ray casting
2592                mViewCellsTree->ConstructMergeTree(rays, objects);
2593        }
2594        else
2595        {
2596                Debug << "spatial merge" << endl;
2597                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mVspBspTree->GetRoot()));
2598        }
2599
2600        mViewCellsTree->ExportStats();
2601
2602        //-- stats and visualizations
2603        cout << "finished merging" << endl;
2604        cout << "merged view cells in "
2605                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2606
2607        Debug << "Postprocessing: Merged view cells in "
2608                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2609       
2610
2611        int savedColorCode = mColorCode;
2612       
2613        //BspLeaf::NewMail();
2614        if (0) // export merged view cells
2615        {
2616                mColorCode = 0;
2617                cout << "reseting view cells ... ";
2618                ResetViewCells();
2619
2620                cout << "finished" << endl;
2621
2622                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2623                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
2624
2625                cout << "exporting view cells after merge ... ";
2626
2627                if (exporter)
2628                {
2629                        if (0)
2630                                exporter->SetWireframe();
2631                        else
2632                                exporter->SetFilled();
2633
2634                        ExportViewCellsForViz(exporter);
2635
2636                        if (mExportGeometry)
2637                        {
2638                                Material m;
2639                                m.mDiffuseColor = RgbColor(0, 1, 0);
2640                                exporter->SetForcedMaterial(m);
2641                                exporter->SetFilled();
2642
2643                                exporter->ExportGeometry(objects);
2644                        }
2645
2646                        delete exporter;
2647                }
2648                cout << "finished" << endl;
2649        }
2650
2651        if (0) // export merged view cells using pvs coding
2652        {
2653                mColorCode = 1;
2654
2655                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
2656       
2657                cout << "exporting view cells after merge (pvs size) ... ";     
2658
2659                if (exporter)
2660                {
2661                        if (0)
2662                                exporter->SetWireframe();
2663                        else
2664                                exporter->SetFilled();
2665
2666                        ExportViewCellsForViz(exporter);
2667
2668                        if (mExportGeometry)
2669                        {
2670                                Material m;
2671                                m.mDiffuseColor = RgbColor(0, 1, 0);
2672                                exporter->SetForcedMaterial(m);
2673                                exporter->SetFilled();
2674
2675                                exporter->ExportGeometry(objects);
2676                        }
2677
2678                        delete exporter;
2679                }
2680                cout << "finished" << endl;
2681        }
2682
2683        mColorCode = savedColorCode;
2684
2685}
2686
2687
2688bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
2689{
2690        return GetSpatialNode(viewCell) != NULL;
2691}
2692
2693
2694BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
2695{
2696        if (!viewCell->IsLeaf())
2697        {
2698                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
2699
2700                return bspVc->mLeaf;
2701        }
2702        else
2703        {
2704                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
2705
2706                // cannot be node of binary tree
2707                if (interior->mChildren.size() != 2)
2708                        return NULL;
2709
2710                ViewCell *left = interior->mChildren[0];
2711                ViewCell *right = interior->mChildren[1];
2712
2713                BspNode *leftNode = GetSpatialNode(left);
2714                BspNode *rightNode = GetSpatialNode(right);
2715
2716                if (leftNode && rightNode && leftNode->IsSibling(rightNode))
2717                {
2718                        return leftNode->GetParent();
2719                }
2720        }
2721
2722        return NULL;
2723}
2724
2725
2726void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2727                                                                                         const ObjectContainer &objects)
2728{
2729        Debug << "render time before refine:" << endl;
2730        mRenderer->RenderScene();
2731        SimulationStatistics ss;
2732        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2733    Debug << ss << endl;
2734
2735        cout << "Refining the merged view cells ... ";
2736        long startTime = GetTime();
2737
2738        // refining the merged view cells
2739        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
2740
2741        //-- stats and visualizations
2742        cout << "finished" << endl;
2743        cout << "refined " << refined << " view cells in "
2744                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2745
2746        Debug << "Postprocessing: refined " << refined << " view cells in "
2747                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2748}
2749
2750
2751int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2752                                                                                const VssRayContainer &rays)
2753{
2754        if (!ViewCellsConstructed())
2755        {
2756                Debug << "postprocess error: no view cells constructed" << endl;
2757                return 0;
2758        }
2759
2760
2761        // view cells already finished before post processing step
2762        // (i.e. because they were loaded)
2763        if (mViewCellsFinished)
2764        {
2765                FinalizeViewCells(true);
2766                EvaluateViewCellsStats();
2767
2768                return 0;
2769        }
2770
2771
2772        // check if new view cells turned invalid
2773        SetValidity(mMinPvsSize, mMaxPvsSize);
2774        // update valid view space according to valid view cells
2775        mVspBspTree->ValidateTree();
2776
2777        // recompute view cell statistics
2778        mViewCellsStats.Reset();
2779        EvaluateViewCellsStats();
2780
2781        // has to be recomputed
2782        mTotalAreaValid = false;
2783
2784
2785        VssRayContainer postProcessRays;
2786
2787        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2788
2789        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
2790
2791        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2792
2793        // should maybe be done here to allow merge working with area or volume
2794        // and to correct the rendering statistics
2795        if (0)
2796        {
2797                FinalizeViewCells(false);
2798        }
2799
2800        //-- merge the individual view cells
2801        MergeViewCells(postProcessRays, objects);
2802       
2803
2804        //-- refines the merged view cells
2805        if (0)
2806                RefineViewCells(postProcessRays, objects);
2807
2808        //-- render simulation after merge
2809        cout << "\nevaluating bsp view cells render time before compress ... ";
2810        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
2811        SimulationStatistics ss;
2812        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2813 
2814
2815        cout << " finished" << endl;
2816        cout << ss << endl;
2817        Debug << ss << endl;
2818
2819
2820
2821        //-- compression
2822
2823        if (ViewCellsTreeConstructed() && mCompressViewCells)
2824        {
2825                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2826                Debug << "number of entries before compress: " << pvsEntries << endl;
2827
2828                mViewCellsTree->CompressViewCellsPvs();
2829
2830                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
2831                Debug << "number of entries after compress: " << pvsEntries << endl;
2832        }
2833
2834        // collapse sibling leaves that share the same view cell
2835        if (0)
2836                mVspBspTree->CollapseTree();
2837
2838        // recompute view cell list and statistics
2839        ResetViewCells();
2840
2841        // real meshes are only contructed only at this stage
2842        FinalizeViewCells(true);
2843
2844        // write view cells to disc
2845        if (mExportViewCells)
2846        {
2847                char buff[100];
2848                environment->GetStringValue("ViewCells.filename", buff);
2849                string vcFilename(buff);
2850
2851                ExportViewCells(buff);
2852        }
2853
2854        return 0;
2855}
2856
2857
2858int VspBspViewCellsManager::GetType() const
2859{
2860        return VSP_BSP;
2861}
2862
2863
2864ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
2865{
2866        if (root->IsLeaf())
2867        {
2868                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
2869
2870                viewCell->SetMergeCost(0.0f);
2871
2872                return viewCell;
2873        }
2874       
2875        BspInterior *interior = dynamic_cast<BspInterior *>(root);
2876        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2877               
2878        float mergeCost = 1.0f / (float)root->mTimeStamp;
2879        //Debug << "timestamp: " << root->mTimeStamp;
2880        //Debug << "merge cost: " << mergeCost << endl;
2881
2882        viewCellInterior->SetMergeCost(mergeCost);
2883
2884        float volume = 0;
2885       
2886        BspNode *front = interior->GetFront();
2887        BspNode *back = interior->GetBack();
2888
2889        // recursivly compute child hierarchies
2890        ViewCell *backVc = ConstructSpatialMergeTree(back);
2891        ViewCell *frontVc = ConstructSpatialMergeTree(front);
2892
2893        viewCellInterior->SetupChildLink(frontVc);
2894        viewCellInterior->SetupChildLink(backVc);
2895
2896
2897        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2898        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
2899
2900        volume += backVc->GetVolume();
2901        volume += frontVc->GetVolume();
2902
2903        viewCellInterior->SetVolume(volume);
2904
2905        return viewCellInterior;
2906}
2907
2908
2909bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2910{
2911        if (!ViewCellsConstructed())
2912                return ViewCellsManager::GetViewPoint(viewPoint);
2913
2914        // TODO: set reasonable limit
2915        const int limit = 20;
2916
2917        for (int i = 0; i < limit; ++ i)
2918        {
2919                viewPoint = mViewSpaceBox.GetRandomPoint();
2920                if (mVspBspTree->ViewPointValid(viewPoint))
2921                {
2922                        return true;
2923                }
2924        }
2925        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2926        return false;
2927}
2928
2929
2930bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2931{
2932  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2933  // validy update in preprocessor for all managers)
2934  return ViewCellsManager::ViewPointValid(viewPoint);
2935
2936  //    return mViewSpaceBox.IsInside(viewPoint) &&
2937  //               mVspBspTree->ViewPointValid(viewPoint);
2938}
2939
2940
2941void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2942                                                                           const VssRayContainer &sampleRays)
2943{
2944        if (!ViewCellsConstructed())
2945                return;
2946
2947        VssRayContainer visRays;
2948        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2949
2950       
2951        if (1) // export view cells
2952        {       // hack pvs
2953                int savedColorCode = mColorCode;
2954                mColorCode = 0;
2955                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2956               
2957                if (exporter)
2958                {
2959                        cout << "exporting view cells after post process ... ";
2960
2961                        if (0)
2962                        {
2963                                exporter->SetWireframe();
2964                                exporter->ExportBox(mViewSpaceBox);
2965                                exporter->SetFilled();
2966                        }
2967
2968                        if (mExportGeometry)
2969                        {
2970                                exporter->ExportGeometry(objects);
2971                        }
2972
2973                        // export rays
2974                        if (mExportRays)
2975                        {
2976                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2977                        }
2978
2979                        ExportViewCellsForViz(exporter);
2980                        delete exporter;
2981                        cout << "finished" << endl;
2982                }
2983
2984                mColorCode = savedColorCode;
2985        }
2986
2987        if (0)
2988        {
2989                cout << "exporting depth map ... ";
2990
2991                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
2992                if (exporter)
2993                {
2994                        if (1)
2995                        {
2996                                exporter->SetWireframe();
2997                                exporter->ExportBox(mViewSpaceBox);
2998                                exporter->SetFilled();
2999                        }
3000
3001                        if (mExportGeometry)
3002                        {
3003                                exporter->ExportGeometry(objects);
3004                        }
3005
3006                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
3007
3008                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
3009
3010                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
3011                        {
3012                                ViewCell *vc = *vit;
3013
3014                                ViewCellContainer leaves;
3015                                mViewCellsTree->CollectLeaves(vc, leaves);
3016
3017                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3018
3019                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
3020                                {
3021                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
3022
3023                                        Material m;
3024
3025                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
3026                                        m.mDiffuseColor.r = relDepth;
3027                                        m.mDiffuseColor.g = 0.0f;
3028                                        m.mDiffuseColor.b = 1.0f - relDepth;
3029
3030                    exporter->SetForcedMaterial(m);
3031                               
3032
3033                                        BspNodeGeometry geom;
3034                                        mVspBspTree->ConstructGeometry(leaf, geom);
3035                                        exporter->ExportPolygons(geom.mPolys);
3036                                }
3037                        }
3038
3039                        delete exporter;
3040                }
3041
3042
3043                cout << "finished" << endl;
3044        }
3045
3046        //-- visualization of the BSP splits
3047        bool exportSplits = false;
3048        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
3049
3050        if (exportSplits)
3051        {
3052                cout << "exporting splits ... ";
3053                ExportSplits(objects, visRays);
3054                cout << "finished" << endl;
3055        }
3056
3057        //-- export single view cells
3058        ExportBspPvs(objects, visRays);
3059}
3060
3061
3062void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3063                                                                                  const VssRayContainer &rays)
3064{
3065        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3066
3067        if (exporter)
3068        {
3069                Material m;
3070                m.mDiffuseColor = RgbColor(1, 0, 0);
3071                exporter->SetForcedMaterial(m);
3072                exporter->SetWireframe();
3073
3074                exporter->ExportBspSplits(*mVspBspTree, true);
3075
3076                // take forced material, else big scenes cannot be viewed
3077                m.mDiffuseColor = RgbColor(0, 1, 0);
3078                exporter->SetForcedMaterial(m);
3079                exporter->SetFilled();
3080
3081                exporter->ResetForcedMaterial();
3082
3083                // export rays
3084                if (mExportRays)
3085                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
3086
3087                if (mExportGeometry)
3088                        exporter->ExportGeometry(objects);
3089
3090                delete exporter;
3091        }
3092}
3093
3094
3095void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3096                                                                                  const VssRayContainer &rays)
3097{
3098        const int leafOut = 20;
3099
3100        ViewCell::NewMail();
3101
3102        cout << "visualization using " << (int)rays.size() << " samples" << endl;
3103        Debug << "visualization using " << (int)rays.size() << " samples" << endl;
3104        Debug << "\nOutput view cells: " << endl;
3105
3106        // sort view cells to visualize the largest view cells
3107        if (0)
3108                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
3109       
3110        int limit = min(leafOut, (int)mViewCells.size());
3111
3112        int raysOut = 0;
3113
3114        //-- some rays for output
3115        for (int i = 0; i < limit; ++ i)
3116        {
3117                cout << "creating output for view cell " << i << " ... ";
3118
3119       
3120                ViewCell *vc;
3121       
3122                if (0) // largest view cell pvs first
3123                        vc = mViewCells[i];
3124                else
3125                        vc = mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
3126
3127                //bspLeaves[j]->Mail();
3128                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3129                Exporter *exporter = Exporter::GetExporter(s);
3130               
3131                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc) << endl;
3132
3133                if (1 || mExportRays)
3134                {
3135                        if (0)
3136                        {
3137                                VssRayContainer vcRays;
3138                VssRayContainer collectRays;
3139
3140                                raysOut = min((int)rays.size(), 100);
3141
3142                                // collect intial view cells
3143                                ViewCellContainer leaves;
3144                                mViewCellsTree->CollectLeaves(vc, leaves);
3145
3146                                ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3147       
3148                                for (vit = leaves.begin(); vit != vit_end; ++ vit)
3149                                {
3150                                        BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaf;
3151                               
3152                                        VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
3153
3154                                        for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
3155                                        {
3156                                                collectRays.push_back(*rit);
3157                                        }
3158                                }
3159
3160                                VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3161
3162                                for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3163                                {
3164                                        float p = RandomValue(0.0f, (float)collectRays.size());
3165                       
3166                                        if (p < raysOut)
3167                                                vcRays.push_back(*rit);
3168                                }
3169                                //-- export rays piercing this view cell
3170                                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
3171                        }
3172               
3173
3174                        if (1)
3175                        {
3176                                VssRayContainer vcRays;
3177                                raysOut = min((int)rays.size(), mVisualizationSamples);
3178                                // check whether we can add the current ray to the output rays
3179                                for (int k = 0; k < raysOut; ++ k)
3180                                {
3181                                        VssRay *ray = rays[k];
3182                                        for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3183                                        {
3184                                                ViewCell *rayvc = ray->mViewCells[j];
3185       
3186                                                if (rayvc == vc)
3187                                                        vcRays.push_back(ray);
3188                                        }
3189                                }       
3190                               
3191                                //-- export rays piercing this view cell
3192                                exporter->ExportRays(vcRays, RgbColor(1, 1, 0));
3193                        }
3194
3195                }
3196               
3197
3198                exporter->SetWireframe();
3199
3200                Material m;//= RandomMaterial();
3201                m.mDiffuseColor = RgbColor(0, 1, 0);
3202                exporter->SetForcedMaterial(m);
3203
3204                ExportViewCellGeometry(exporter, vc);
3205       
3206                exporter->SetFilled();
3207
3208
3209                if (1)
3210                {
3211                        ObjectPvsMap::const_iterator oit,
3212                                oit_end = vc->GetPvs().mEntries.end();
3213
3214
3215                        exporter->SetFilled();
3216
3217                        Intersectable::NewMail();
3218       
3219                        // output PVS of view cell
3220                        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
3221                        {               
3222                                Intersectable *intersect = (*oit).first;
3223
3224                                if (!intersect->Mailed())
3225                                {
3226                                        m = RandomMaterial();
3227                                        exporter->SetForcedMaterial(m);
3228
3229                                        exporter->ExportIntersectable(intersect);
3230                                        intersect->Mail();
3231                                }
3232                        }
3233                }
3234                else
3235                {
3236                        m.mDiffuseColor = RgbColor(1, 0, 0);
3237                        exporter->SetForcedMaterial(m);
3238
3239                        exporter->ExportGeometry(objects);
3240                }
3241
3242                DEL_PTR(exporter);
3243                cout << "finished" << endl;
3244        }
3245
3246        Debug << endl;
3247}
3248
3249
3250int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3251                                                                                        const Vector3 &termination,
3252                                                                                        ViewCellContainer &viewcells)
3253{
3254        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
3255}
3256
3257
3258void VspBspViewCellsManager::ExportColor(Exporter *exporter,
3259                                                                                 ViewCell *vc) const
3260{
3261        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
3262
3263        float importance = 0;
3264        static Material m;
3265
3266        switch (mColorCode)
3267        {
3268        case 0: // Random
3269                {
3270                        if (vcValid)
3271                        {
3272                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3273                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3274                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
3275                        }
3276                        else
3277                        {
3278                                m.mDiffuseColor.r = 0.0f;
3279                                m.mDiffuseColor.g = 1.0f;
3280                                m.mDiffuseColor.b = 0.0f;
3281                        }
3282
3283                        exporter->SetForcedMaterial(m);
3284                        return;
3285                }
3286               
3287        case 1: // pvs
3288                {
3289                        importance = (float)vc->GetPvs().GetSize() /
3290                                (float)mViewCellsStats.maxPvs;
3291
3292                }
3293                break;
3294        case 2: // merges
3295                {
3296            int lSize = mViewCellsTree->GetSize(vc);
3297                        importance = (float)lSize / (float)mViewCellsStats.maxLeaves;
3298                }
3299                break;
3300        case 3: // merge tree differene
3301                {
3302                        importance = (float)GetMaxTreeDiff(vc) /
3303                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
3304
3305                }
3306                break;
3307        default:
3308                break;
3309        }
3310
3311        // special color code for invalid view cells
3312        m.mDiffuseColor.r = importance;
3313        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
3314        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
3315
3316        //Debug << "importance: " << importance << endl;
3317        exporter->SetForcedMaterial(m);
3318}
3319
3320
3321void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
3322                                                    ViewCell *vc,
3323                                                                                                        const Plane3 *cuttingPlane) const
3324{
3325        if (vc->GetMesh())
3326        {
3327                exporter->ExportMesh(vc->GetMesh());
3328       
3329                return;
3330        }
3331
3332       
3333        if (cuttingPlane)
3334        {
3335                ViewCellContainer leaves;
3336                mViewCellsTree->CollectLeaves(vc, leaves);
3337                ViewCellContainer::const_iterator it, it_end = leaves.end();
3338
3339                for (it = leaves.begin(); it != it_end; ++ it)
3340                {
3341                        BspNodeGeometry geom;
3342
3343                        BspNodeGeometry front;
3344                        BspNodeGeometry back;
3345
3346       
3347                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3348
3349                        mVspBspTree->ConstructGeometry(leaf, geom);
3350                       
3351                        geom.SplitGeometry(front,
3352                                                           back,
3353                                                           *cuttingPlane,
3354                                                           mViewSpaceBox,
3355                                                           0.0001f);
3356
3357                        if ((int)back.mPolys.size() >= 3)
3358                                exporter->ExportPolygons(back.mPolys);
3359                }
3360        }
3361        else
3362        {
3363                BspNodeGeometry geom;
3364                mVspBspTree->ConstructGeometry(vc, geom);
3365                       
3366                exporter->ExportPolygons(geom.mPolys);
3367        }
3368}
3369
3370
3371int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3372{
3373        ViewCellContainer leaves;
3374        mViewCellsTree->CollectLeaves(vc, leaves);
3375
3376        int maxDist = 0;
3377       
3378        // compute max height difference
3379        for (int i = 0; i < (int)leaves.size(); ++ i)
3380                for (int j = 0; j < (int)leaves.size(); ++ j)
3381        {
3382                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
3383
3384                if (i != j)
3385                {
3386                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
3387                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3388                        if (dist > maxDist)
3389                                maxDist = dist;
3390                }
3391        }
3392
3393        return maxDist;
3394}
3395
3396
3397ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
3398{
3399        if (!mVspBspTree)
3400                return NULL;
3401
3402        if (!mViewSpaceBox.IsInside(point))
3403          return NULL;
3404
3405        return mVspBspTree->GetViewCell(point);
3406}
3407
3408
3409void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3410{
3411        if (vc->GetMesh())
3412                delete vc->GetMesh();
3413
3414       
3415        BspNodeGeometry geom;
3416
3417        mVspBspTree->ConstructGeometry(vc, geom);
3418       
3419        Mesh *mesh = new Mesh();
3420        geom.AddToMesh(*mesh);
3421        vc->SetMesh(mesh);
3422        mMeshContainer.push_back(mesh);
3423}
3424
3425
3426ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3427                                                                                                  ObjectContainer *objects)
3428{
3429        ViewCellsParser parser;
3430
3431        ViewCellsManager *vm = NULL;
3432
3433        if (parser.ParseFile(filename, &vm, objects))
3434        {
3435                //vm->PrepareLoadedViewCells();
3436                vm->ResetViewCells();
3437
3438                vm->mViewCellsFinished = true;
3439                vm->mMaxPvsSize = (int)objects->size();
3440
3441                vm->FinalizeViewCells(true);
3442
3443                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3444        }
3445        else
3446        {
3447                Debug << "failed loading view cells" << endl;
3448                DEL_PTR(vm);
3449        }
3450
3451
3452        return vm;
3453}
3454
3455
3456inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3457{
3458        return obj1->mId < obj2->mId;
3459}
3460
3461
3462bool VspBspViewCellsManager::ExportViewCells(const string filename)
3463{
3464        cout << "exporting view cells to xml ... ";
3465        std::ofstream stream;
3466
3467        // for output we need unique ids for each view cell
3468        CreateUniqueViewCellIds();
3469
3470
3471        stream.open(filename.c_str());
3472        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
3473        stream << "<Visibility_Solution>" << endl;
3474
3475        //-- the view space bounding box
3476        stream << "<ViewSpaceBox"
3477                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3478                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
3479
3480        //-- the type of the view cells hierarchy
3481        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
3482
3483        //-- load the view cells itself, i.e., the ids and the pvs
3484        stream << "<ViewCells>" << endl;
3485       
3486#if 0
3487       
3488        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3489               
3490        for (it = mViewCells.begin(); it != it_end; ++ it)
3491                ExportViewCell(*it, stream);
3492#else
3493        mViewCellsTree->Export(stream);
3494#endif
3495
3496        stream << "</ViewCells>" << endl;
3497
3498        //-- load the hierarchy
3499        stream << "<Hierarchy>" << endl;
3500        mVspBspTree->Export(stream);
3501        stream << endl << "</Hierarchy>" << endl;
3502
3503        stream << "</Visibility_Solution>" << endl;
3504        stream.close();
3505
3506        cout << "finished" << endl;
3507
3508        return true;
3509}
3510
3511
3512int VspBspViewCellsManager::CastBeam(Beam &beam)
3513{
3514        return mVspBspTree->CastBeam(beam);
3515}
3516
3517
3518void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
3519                                                                          const bool createMesh)
3520{
3521        CreateMesh(viewCell);
3522
3523        float area = 0;
3524        float volume = 0;
3525
3526        ViewCellContainer leaves;
3527        mViewCellsTree->CollectLeaves(viewCell, leaves);
3528
3529        ViewCellContainer::const_iterator it, it_end = leaves.end();
3530
3531        for (it = leaves.begin(); it != it_end; ++ it)
3532        {
3533                BspNodeGeometry geom;
3534                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3535                mVspBspTree->ConstructGeometry(leaf, geom);
3536
3537                area += geom.GetArea();
3538                volume += geom.GetVolume();
3539        }
3540
3541        viewCell->SetVolume(volume);
3542        viewCell->SetArea(area);
3543}
3544
3545
3546void VspBspViewCellsManager::PrepareLoadedViewCells()
3547{
3548        // TODO: do I still need this here?
3549        if (0)
3550        mVspBspTree->RepairViewCellsLeafLists();
3551}
3552
3553
3554
3555void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3556                                                                                                        vector<MergeCandidate> &candidates)
3557{       
3558        cout << "collecting merge candidates ... " << endl;
3559
3560        if (mUseRaysForMerge)
3561        {
3562                mVspBspTree->CollectMergeCandidates(rays, candidates);
3563        }
3564        else
3565        {
3566                vector<BspLeaf *> leaves;
3567                mVspBspTree->CollectLeaves(leaves);
3568                mVspBspTree->CollectMergeCandidates(leaves, candidates);
3569        }
3570
3571        cout << "fininshed collecting candidates" << endl;
3572}
3573
3574
3575void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
3576{
3577        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
3578        for (it = mViewCells.begin(); it != it_end; ++ it)
3579        {
3580        }
3581}
3582
3583//////////////////////////////////
3584ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
3585{
3586        //TODO
3587        return NULL;// new VspBspViewCellsManager();
3588}
3589
Note: See TracBrowser for help on using the repository browser.