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

Revision 575, 64.6 KB checked in by mattausch, 18 years ago (diff)

changed view cell parser. warning, not working yet!!

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