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

Revision 583, 70.9 KB checked in by mattausch, 18 years ago (diff)

added compression

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