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

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