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

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