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

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