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

Revision 572, 63.2 KB checked in by bittner, 18 years ago (diff)

gl render error estimation changes for backface culling empty viewspace detection

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
1271  if (!mViewSpaceBox.IsInside(point))
1272        return NULL;
1273
1274  return mBspTree->GetViewCell(point);
1275}
1276
1277/**********************************************************************/
1278/*                   KdViewCellsManager implementation               */
1279/**********************************************************************/
1280
1281
1282
1283KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
1284ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
1285{
1286}
1287
1288float KdViewCellsManager::GetProbability(ViewCell *viewCell)
1289{
1290        // compute view cell area / volume as subsititute for probability
1291#if 0
1292        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1293#endif
1294#if 1
1295        return GetArea(viewCell) / GetAccVcArea();
1296#endif
1297#if 0
1298        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1299#endif
1300}
1301
1302
1303float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1304{
1305        return viewCell->GetPvs().GetSize() * objRendercost;
1306}
1307
1308
1309void KdViewCellsManager::CollectViewCells()
1310{
1311        //mKdTree->CollectViewCells(mViewCells); TODO
1312}
1313
1314
1315int KdViewCellsManager::Construct(const ObjectContainer &objects,
1316                                                                  const VssRayContainer &rays)
1317{
1318        // if view cells already constructed
1319        if (ViewCellsConstructed())
1320                return 0;
1321
1322        mKdTree->Construct();
1323
1324        mTotalAreaValid = false;
1325        // create the view cells
1326        mKdTree->CreateAndCollectViewCells(mViewCells);
1327
1328        // cast rays
1329        ComputeSampleContributions(rays);
1330
1331        EvaluateViewCellsStats();
1332        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1333
1334        return 0;
1335}
1336
1337bool KdViewCellsManager::ViewCellsConstructed() const
1338{
1339        return mKdTree->GetRoot() != NULL;
1340}
1341
1342int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
1343                                                                        const VssRayContainer &rays)
1344{
1345        return 0;
1346}
1347
1348void KdViewCellsManager::Visualize(const ObjectContainer &objects,
1349                                                                   const VssRayContainer &sampleRays)
1350{
1351        if (!ViewCellsConstructed())
1352                return;
1353
1354        // using view cells instead of the kd PVS of objects
1355        const bool useViewCells = true;
1356        bool exportRays = false;
1357
1358        int limit = min(mVisualizationSamples, (int)sampleRays.size());
1359        const int pvsOut = min((int)objects.size(), 10);
1360        VssRayContainer *rays = new VssRayContainer[pvsOut];
1361
1362        if (useViewCells)
1363        {
1364                const int leafOut = 10;
1365
1366                ViewCell::NewMail();
1367
1368                //-- some rays for output
1369                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
1370                Debug << "visualization using " << raysOut << " samples" << endl;
1371
1372                //-- some random view cells and rays for output
1373                vector<KdLeaf *> kdLeaves;
1374
1375                for (int i = 0; i < leafOut; ++ i)
1376                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
1377
1378                for (int i = 0; i < kdLeaves.size(); ++ i)
1379                {
1380                        KdLeaf *leaf = kdLeaves[i];
1381                        RayContainer vcRays;
1382
1383                        cout << "creating output for view cell " << i << " ... ";
1384#if 0
1385                        // check whether we can add the current ray to the output rays
1386                        for (int k = 0; k < raysOut; ++ k)
1387                        {
1388                                Ray *ray = sampleRays[k];
1389
1390                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1391                                {
1392                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
1393
1394                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
1395                                        {
1396                                                vcRays.push_back(ray);
1397                                        }
1398                                }
1399                        }
1400#endif
1401                        Intersectable::NewMail();
1402
1403                        ViewCell *vc = leaf->mViewCell;
1404
1405                        //bspLeaves[j]->Mail();
1406                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
1407
1408                        Exporter *exporter = Exporter::GetExporter(s);
1409                        exporter->SetFilled();
1410
1411                        exporter->SetWireframe();
1412                        //exporter->SetFilled();
1413
1414                        Material m;//= RandomMaterial();
1415                        m.mDiffuseColor = RgbColor(1, 1, 0);
1416                        exporter->SetForcedMaterial(m);
1417
1418                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1419                        exporter->ExportBox(box);
1420
1421                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1422                                << ", piercing rays=" << (int)vcRays.size() << endl;
1423
1424                        // export rays piercing this view cell
1425                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1426
1427                        m.mDiffuseColor = RgbColor(1, 0, 0);
1428                        exporter->SetForcedMaterial(m);
1429
1430                        // exporter->SetWireframe();
1431                        exporter->SetFilled();
1432
1433                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1434                        // output PVS of view cell
1435                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
1436                        {
1437                                Intersectable *intersect = (*it).first;
1438                                if (!intersect->Mailed())
1439                                {
1440                                        exporter->ExportIntersectable(intersect);
1441                                        intersect->Mail();
1442                                }
1443                        }
1444
1445                        DEL_PTR(exporter);
1446                        cout << "finished" << endl;
1447                }
1448
1449                DEL_PTR(rays);
1450        }
1451        else // using kd PVS of objects
1452        {
1453                for (int i = 0; i < limit; ++ i)
1454                {
1455                        VssRay *ray = sampleRays[i];
1456
1457                        // check whether we can add this to the rays
1458                        for (int j = 0; j < pvsOut; j++)
1459                        {
1460                                if (objects[j] == ray->mTerminationObject)
1461                                {
1462                                        rays[j].push_back(ray);
1463                                }
1464                        }
1465                }
1466
1467                if (exportRays)
1468                {
1469                        Exporter *exporter = NULL;
1470                        exporter = Exporter::GetExporter("sample-rays.x3d");
1471                        exporter->SetWireframe();
1472                        exporter->ExportKdTree(*mKdTree);
1473
1474                        for (i=0; i < pvsOut; i++)
1475                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1476
1477                        exporter->SetFilled();
1478
1479                        delete exporter;
1480                }
1481
1482                for (int k=0; k < pvsOut; k++)
1483                {
1484                        Intersectable *object = objects[k];
1485                        char s[64];
1486                        sprintf(s, "sample-pvs%04d.x3d", k);
1487
1488                        Exporter *exporter = Exporter::GetExporter(s);
1489                        exporter->SetWireframe();
1490
1491                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1492                        Intersectable::NewMail();
1493
1494                        // avoid adding the object to the list
1495                        object->Mail();
1496                        ObjectContainer visibleObjects;
1497
1498                        for (; i != object->mKdPvs.mEntries.end(); i++)
1499                        {
1500                                KdNode *node = (*i).first;
1501                                exporter->ExportBox(mKdTree->GetBox(node));
1502
1503                                mKdTree->CollectObjects(node, visibleObjects);
1504                        }
1505
1506                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1507                        exporter->SetFilled();
1508
1509                        for (int j = 0; j < visibleObjects.size(); j++)
1510                                exporter->ExportIntersectable(visibleObjects[j]);
1511
1512                        Material m;
1513                        m.mDiffuseColor = RgbColor(1, 0, 0);
1514                        exporter->SetForcedMaterial(m);
1515                        exporter->ExportIntersectable(object);
1516
1517                        delete exporter;
1518                }
1519        }
1520}
1521
1522
1523void KdViewCellsManager::ExportColor(Exporter *exporter,
1524                                                                         ViewCell *vc) const
1525{
1526        // TODO
1527}
1528
1529
1530void KdViewCellsManager::ExportVcGeometry(Exporter *exporter,
1531                                                                                  ViewCell *vc) const
1532{
1533        KdViewCell *kdVc = dynamic_cast<KdViewCell *>(vc);
1534        vector<KdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1535
1536        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
1537                exporter->ExportBox(mKdTree->GetBox(*it));
1538}
1539
1540
1541int KdViewCellsManager::GetType() const
1542{
1543        return ViewCellsManager::KD;
1544}
1545
1546
1547
1548KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
1549{
1550        KdNode *node = leaf;
1551
1552        while (node->mParent && node->mDepth > mKdPvsDepth)
1553                node = node->mParent;
1554        return node;
1555}
1556
1557int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1558                                                                                const Vector3 &termination,
1559                                                                                ViewCellContainer &viewcells)
1560{
1561        return mKdTree->CastLineSegment(origin, termination, viewcells);
1562}
1563
1564
1565void KdViewCellsManager::CreateMesh(ViewCell *vc)
1566{
1567        // TODO
1568}
1569
1570/**********************************************************************/
1571/*                   VspKdViewCellsManager implementation             */
1572/**********************************************************************/
1573
1574
1575VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
1576                                                                                         int constructionSamples):
1577ViewCellsManager(constructionSamples),
1578mVspKdTree(vspKdTree)
1579{
1580        mVspKdTree->SetViewCellsManager(this);
1581}
1582
1583float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
1584{
1585        // volume or area substitutes for view point probability
1586#if 0
1587        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
1588#else
1589        return GetArea(viewCell) / GetAccVcArea();
1590#endif
1591}
1592
1593
1594float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1595{
1596        return viewCell->GetPvs().GetSize() * objRendercost;
1597}
1598
1599
1600void VspKdViewCellsManager::CollectViewCells()
1601{
1602        mVspKdTree->CollectViewCells(mViewCells);
1603}
1604
1605
1606int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
1607                                                                         const VssRayContainer &rays)
1608{
1609        // if view cells already constructed
1610        if (ViewCellsConstructed())
1611                return 0;
1612
1613        VssRayContainer constructionRays;
1614        VssRayContainer savedRays;
1615
1616        GetRaySets(rays,
1617                           mConstructionSamples,
1618                           constructionRays,
1619                           &savedRays);
1620
1621        Debug << "constructing vsp kd tree using "
1622                  << (int)constructionRays.size() << " samples" << endl;
1623
1624        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
1625        Debug << mVspKdTree->GetStatistics() << endl;
1626
1627        // export leaf building blocks
1628        ExportLeaves(objects, rays);
1629
1630        // finally merge kd leaf building blocks to view cells
1631        const int merged = mVspKdTree->MergeViewCells(rays);
1632
1633        // collapse siblings belonging to the same view cell
1634        mVspKdTree->RefineViewCells(rays);
1635
1636        // collapse siblings belonging to the same view cell
1637        mVspKdTree->CollapseTree();
1638
1639        // evaluale view cell stats
1640        ResetViewCells();
1641
1642        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1643
1644        long startTime = GetTime();
1645        // recast rest of rays
1646        ComputeSampleContributions(savedRays);
1647
1648        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
1649                  << " secs" << endl;
1650
1651        return merged;
1652}
1653
1654bool VspKdViewCellsManager::ViewCellsConstructed() const
1655{
1656        return mVspKdTree->GetRoot() != NULL;
1657}
1658
1659
1660ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1661{
1662        return new VspKdViewCell(mesh);
1663}
1664
1665int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
1666                                                                           const VssRayContainer &rays)
1667{
1668        if (!ViewCellsConstructed())
1669                return 0;
1670
1671        // recalculate stats
1672        EvaluateViewCellsStats();
1673
1674        return 0;
1675}
1676
1677
1678void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
1679                                                                                 const VssRayContainer &sampleRays)
1680{
1681        if (!ViewCellsConstructed())
1682                return;
1683
1684        //-- export leaf building blocks
1685        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
1686        if (!exporter)
1687                return;
1688
1689        //exporter->SetWireframe();
1690        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1691        exporter->ExportVspKdTree(*mVspKdTree);
1692
1693        if (mExportGeometry)
1694                exporter->ExportGeometry(objects);
1695
1696        if (mExportRays)
1697        {
1698                const float prob = (float)mVisualizationSamples
1699                        / ((float)sampleRays.size() + Limits::Small);
1700
1701                exporter->SetWireframe();
1702
1703                //-- collect uniformly distributed rays
1704                VssRayContainer rays;
1705
1706                for (int i = 0; i < sampleRays.size(); ++ i)
1707                {
1708                        if (RandomValue(0,1) < prob)
1709                                rays.push_back(sampleRays[i]);
1710                }
1711                exporter->ExportRays(rays, RgbColor(1, 0, 0));
1712        }
1713
1714        delete exporter;
1715}
1716
1717void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1718                                                                          const VssRayContainer &sampleRays)
1719{
1720        if (!ViewCellsConstructed())
1721                return;
1722
1723        //-- export single view cells
1724        for (int i = 0; i < 10; ++ i)
1725        {
1726                char s[64];
1727                sprintf(s, "vsp_viewcell%04d.x3d", i);
1728                Exporter *exporter = Exporter::GetExporter(s);
1729                const int idx =
1730                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
1731
1732                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
1733
1734                cout << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
1735                Debug << "Output view cell " << i << " with pvs size " << vc->GetPvs().GetSize() << endl;
1736                //-- export geometry
1737                Material m;
1738                m.mDiffuseColor = RgbColor(0, 1, 1);
1739
1740                exporter->SetForcedMaterial(m);
1741                exporter->SetWireframe();
1742
1743                ExportVcGeometry(exporter, vc);
1744
1745                //-- export stored rays
1746                if (mExportRays)
1747                {
1748                        vector<VspKdLeaf *>::const_iterator it,
1749                                it_end = vc->mLeaves.end();
1750
1751                        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
1752                        {
1753                                VspKdLeaf *leaf = *it;
1754                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
1755
1756                                VssRayContainer vssRays;
1757
1758                                VssRayContainer castRays;
1759                                VssRayContainer initRays;
1760
1761                                leaf->GetRays(vssRays);
1762
1763                                VssRayContainer::const_iterator it, it_end = vssRays.end();
1764                                const float prop = 200.0f / (float)vssRays.size();
1765
1766                                for (it = vssRays.begin(); it != it_end; ++ it)
1767                                {
1768                                        if (Random(1) < prop)
1769                                                if ((*it)->mTerminationObject == NULL)
1770                                                        castRays.push_back(*it);
1771                                                else
1772                                                        initRays.push_back(*it);
1773                                }
1774
1775                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
1776                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
1777                        }
1778                }
1779
1780                //-- output PVS of view cell
1781                m.mDiffuseColor = RgbColor(1, 0, 0);
1782                exporter->SetForcedMaterial(m);
1783
1784                Intersectable::NewMail();
1785
1786                ObjectPvsMap::const_iterator it,
1787                        it_end = vc->GetPvs().mEntries.end();
1788
1789                exporter->SetFilled();
1790
1791                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1792                {
1793                        Intersectable *intersect = (*it).first;
1794
1795                        if (!intersect->Mailed())
1796                        {
1797                                Material m = RandomMaterial();
1798                                exporter->SetForcedMaterial(m);
1799
1800                                exporter->ExportIntersectable(intersect);
1801                                intersect->Mail();
1802                        }
1803                }
1804
1805                delete exporter;
1806        }
1807
1808        //-- export final view cells
1809        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
1810
1811        //if (exportGeometry) exporter->SetWireframe();
1812        //else exporter->SetFilled();
1813
1814        ExportViewCellsForViz(exporter);
1815
1816        if (mExportGeometry)
1817        {
1818                exporter->SetFilled();
1819                exporter->ExportGeometry(objects);
1820        }
1821
1822        if (mExportRays)
1823        {
1824                const float prob = (float)mVisualizationSamples
1825                        / ((float)sampleRays.size() + Limits::Small);
1826
1827                exporter->SetWireframe();
1828
1829                VssRayContainer rays;
1830
1831                for (int i = 0; i < sampleRays.size(); ++ i)
1832                {
1833                  if (RandomValue(0,1) < prob)
1834                        rays.push_back(sampleRays[i]);
1835                }
1836                exporter->ExportRays(rays, RgbColor(1, 0, 0));
1837        }
1838
1839        delete exporter;
1840}
1841
1842int VspKdViewCellsManager::GetType() const
1843{
1844        return VSP_KD;
1845}
1846
1847
1848int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1849                                                                                   const Vector3 &termination,
1850                                                                                   ViewCellContainer &viewcells)
1851{
1852        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
1853}
1854
1855
1856void VspKdViewCellsManager::ExportColor(Exporter *exporter,
1857                                                                                ViewCell *vc) const
1858{
1859        if (mColorCode == 0) // Random color
1860                return;
1861
1862        float importance = 0;
1863
1864        switch (mColorCode)
1865        {
1866        case 1: // pvs
1867                {
1868                        importance = (float)vc->GetPvs().GetSize() /
1869                                (float)mViewCellsStats.maxPvs;
1870                }
1871                break;
1872        case 2: // merges
1873                {
1874            VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(vc);
1875
1876                        importance = (float)vspKdVc->mLeaves.size() /
1877                                (float)mViewCellsStats.maxLeaves;
1878                }
1879                break;
1880        case 3: // merged tree depth difference
1881                {
1882                        //importance = (float)GetMaxTreeDiff(vc) /
1883                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
1884                }
1885                break;
1886        default:
1887                break;
1888        }
1889
1890        Material m;
1891        m.mDiffuseColor.b = 1.0f;
1892        m.mDiffuseColor.r = importance;
1893        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
1894        //Debug << "importance: " << importance << endl;
1895        exporter->SetForcedMaterial(m);
1896}
1897
1898
1899void VspKdViewCellsManager::ExportVcGeometry(Exporter *exporter,
1900                                                                                   ViewCell *vc) const
1901{
1902        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
1903        vector<VspKdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1904
1905        Mesh m;
1906        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
1907        {
1908                mVspKdTree->GetBBox(*it).AddBoxToMesh(&m);
1909        }
1910
1911        exporter->ExportMesh(&m);
1912}
1913
1914
1915void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
1916{
1917        //TODO
1918}
1919
1920/**************************************************************************/
1921/*                   VspBspViewCellsManager implementation                */
1922/**************************************************************************/
1923
1924
1925VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
1926                                                                                           int constructionSamples):
1927ViewCellsManager(constructionSamples),
1928mVspBspTree(vspBspTree)
1929{
1930        mVspBspTree->SetViewCellsManager(this);
1931}
1932
1933
1934VspBspViewCellsManager::~VspBspViewCellsManager()
1935{
1936}
1937
1938
1939float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
1940{
1941        if (0 && mVspBspTree->mUseAreaForPvs)
1942                return GetArea(viewCell) / GetAccVcArea();
1943        else
1944                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
1945}
1946
1947
1948void VspBspViewCellsManager::CollectViewCells()
1949{
1950        mVspBspTree->CollectViewCells(mViewCells, mOnlyValidViewCells);
1951}
1952
1953
1954float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
1955                                                                                        float objRendercost) const
1956{
1957        return viewCell->GetPvs().GetSize() * objRendercost;
1958}
1959
1960
1961bool VspBspViewCellsManager::ViewCellsConstructed() const
1962{
1963        return mVspBspTree->GetRoot() != NULL;
1964}
1965
1966
1967ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1968{
1969        return new BspViewCell(mesh);
1970}
1971
1972
1973int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
1974                                                                          const VssRayContainer &rays)
1975{
1976        // if view cells were already constructed
1977        if (ViewCellsConstructed())
1978                return 0;
1979
1980        Debug << "Constructing bsp view cells" << endl;
1981
1982        int sampleContributions = 0;
1983
1984        VssRayContainer sampleRays;
1985
1986        int limit = min (mConstructionSamples, (int)rays.size());
1987
1988        VssRayContainer constructionRays;
1989        VssRayContainer savedRays;
1990
1991        Debug << "construction samples: " << mConstructionSamples << " rays: " << (int)rays.size() << endl;
1992        GetRaySets(rays, mConstructionSamples, constructionRays, &savedRays);
1993
1994        Debug << "construction rays: " << (int)constructionRays.size() << endl;
1995        Debug << "saved rays: " << (int)savedRays.size() << endl;
1996
1997        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
1998
1999        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
2000
2001        Debug << mVspBspTree->GetStatistics() << endl;
2002
2003        // collapse invalid regions
2004        cout << "collapsing invalid tree regions ... ";
2005        long startTime = GetTime();
2006        int collapsedLeaves = mVspBspTree->CollapseTree();
2007        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3 << " seconds" << endl;
2008    cout << "finished" << endl;
2009
2010        cout << "reseting view cell stats ... ";
2011        ResetViewCells();
2012        cout << "finished" << endl;
2013
2014        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
2015
2016        if (1) // export initial view cells
2017        {
2018                cout << "exporting initial view cells (=leaves) ... ";
2019                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
2020
2021                if (exporter)
2022                {
2023                        //exporter->SetWireframe();
2024                        exporter->SetFilled();
2025                        ExportViewCellsForViz(exporter);
2026
2027                        if (0 && mExportRays)
2028                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
2029
2030                        if (mExportGeometry)
2031                                exporter->ExportGeometry(objects);
2032
2033                        delete exporter;
2034                }
2035                cout << "finished" << endl;
2036        }
2037
2038        startTime = GetTime();
2039
2040        // reset view cells and stats
2041        ResetViewCells();
2042
2043        cout << "Computing remaining ray contributions ... ";
2044        // recast rest of rays
2045        ComputeSampleContributions(savedRays);
2046        cout << "finished" << endl;
2047
2048        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
2049                  << " secs" << endl;
2050
2051        cout << "construction finished" << endl;
2052
2053        return sampleContributions;
2054}
2055
2056
2057void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2058                                                                                        const ObjectContainer &objects)
2059{
2060        //-- post processing of bsp view cells
2061    int vcSize = 0;
2062        int pvsSize = 0;
2063
2064        mRenderer->RenderScene();
2065        SimulationStatistics ss;
2066        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2067    Debug << ss << endl;
2068
2069        //-- merge or subdivide view cells
2070        int merged = 0;
2071
2072        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
2073        long startTime = GetTime();
2074
2075        // TODO: should be done BEFORE the ray casting
2076        merged = mVspBspTree->MergeViewCells(rays, objects);
2077
2078        //-- stats and visualizations
2079        cout << "finished merging" << endl;
2080        cout << "merged " << merged << " view cells in "
2081                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2082
2083        Debug << "Postprocessing: Merged " << merged << " view cells in "
2084                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2085
2086        cout << "reseting view cell stats ... ";
2087        ResetViewCells();
2088        cout << "finished" << endl;
2089
2090        //BspLeaf::NewMail();
2091        if (1) // export merged view cells
2092        {
2093                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2094                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
2095
2096                cout << "exporting view cells after merge ... ";
2097
2098                if (exporter)
2099                {
2100                        if (0)
2101                                exporter->SetWireframe();
2102                        else
2103                                exporter->SetFilled();
2104                        ExportViewCellsForViz(exporter);
2105
2106                        if (mExportGeometry)
2107                        {
2108                                Material m;
2109                                m.mDiffuseColor = RgbColor(0, 1, 0);
2110                                exporter->SetForcedMaterial(m);
2111                                exporter->SetFilled();
2112
2113                                exporter->ExportGeometry(objects);
2114                        }
2115
2116                        delete exporter;
2117                }
2118                cout << "finished" << endl;
2119        }
2120}
2121
2122
2123void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2124                                                                                         const ObjectContainer &objects)
2125{
2126        Debug << "render time before refine:" << endl;
2127        mRenderer->RenderScene();
2128        SimulationStatistics ss;
2129        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2130    Debug << ss << endl;
2131
2132        cout << "Refining the merged view cells ... ";
2133        long startTime = GetTime();
2134
2135        // refining the merged view cells
2136        const int refined = mVspBspTree->RefineViewCells(rays, objects);
2137
2138        //-- stats and visualizations
2139        cout << "finished" << endl;
2140        cout << "refined " << refined << " view cells in "
2141                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2142
2143        Debug << "Postprocessing: refined " << refined << " view cells in "
2144                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
2145}
2146
2147
2148int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2149                                                                                const VssRayContainer &rays)
2150{
2151        if (!ViewCellsConstructed())
2152        {
2153                Debug << "postprocess error: no view cells constructed" << endl;
2154                return 0;
2155        }
2156
2157
2158        // view cells already finished before post processing step (i.e. because they were loaded)
2159        if (mViewCellsFinished)
2160        {
2161                FinalizeViewCells(true);
2162                EvaluateViewCellsStats();
2163                return 0;
2164        }
2165
2166
2167        // check if new view cells turned invalid
2168        mVspBspTree->ValidateTree();
2169        ResetViewCells();
2170
2171
2172        VssRayContainer postProcessRays;
2173        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2174
2175        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
2176
2177        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2178
2179        // should maybe be done here to allow merge working with area or volume
2180        // and to correct the rendering statistics
2181        if (0)
2182        {
2183                FinalizeViewCells(false);
2184        }
2185
2186        //-- merge the individual view cells
2187        MergeViewCells(postProcessRays, objects);
2188        //-- refines the merged view cells
2189        RefineViewCells(postProcessRays, objects);
2190
2191        //-- export shuffled view cells
2192        if (1)
2193        {
2194                cout << "exporting shuffled view cells ... ";
2195
2196                Exporter *exporter = Exporter::GetExporter("shuffled_view_cells.x3d");
2197                if (exporter)
2198                {
2199                        if (1)
2200                        {
2201                                exporter->SetWireframe();
2202                                exporter->ExportBox(mViewSpaceBox);
2203                                exporter->SetFilled();
2204                        }
2205
2206                        if (mExportGeometry)
2207                        {
2208                                exporter->ExportGeometry(objects);
2209                        }
2210
2211                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2212
2213                        Material vm, lm;
2214
2215                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
2216                        {
2217                                BspViewCell *vc = dynamic_cast<BspViewCell *>(*vit);
2218
2219                                vm = RandomMaterial();
2220
2221                                lm = vm;
2222
2223                                vm.mDiffuseColor.r -= 0.45f;
2224                                vm.mDiffuseColor.g -= 0.45f;
2225                                vm.mDiffuseColor.b -= 0.45f;
2226
2227                                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
2228
2229                                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2230                                {
2231                                        BspLeaf *leaf = *lit;
2232
2233                                        if (leaf->Mailed())
2234                                                exporter->SetForcedMaterial(lm);
2235                                        else
2236                                                exporter->SetForcedMaterial(vm);
2237
2238                                        BspNodeGeometry geom;
2239                                        mVspBspTree->ConstructGeometry(leaf, geom);
2240                                        exporter->ExportPolygons(geom.mPolys);
2241                                }
2242                        }
2243
2244                        delete exporter;
2245                }
2246
2247
2248                cout << "finished" << endl;
2249        }
2250
2251        // collapse sibling leaves that share the same view cell
2252        mVspBspTree->CollapseTree();
2253
2254        ResetViewCells();
2255
2256        // real meshes are only contructed only at this stage
2257        FinalizeViewCells(true);
2258
2259        // write view cells to disc
2260        if (mExportViewCells)
2261        {
2262                char buff[100];
2263                environment->GetStringValue("ViewCells.filename", buff);
2264                string vcFilename(buff);
2265
2266                ExportViewCells(buff);
2267        }
2268
2269        return 0;
2270}
2271
2272
2273int VspBspViewCellsManager::GetType() const
2274{
2275        return VSP_BSP;
2276}
2277
2278
2279bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
2280{
2281        if (!ViewCellsConstructed())
2282                return ViewCellsManager::GetViewPoint(viewPoint);
2283
2284        // TODO: set reasonable limit
2285        const int limit = 20;
2286
2287        for (int i = 0; i < limit; ++ i)
2288        {
2289                viewPoint = mViewSpaceBox.GetRandomPoint();
2290                if (mVspBspTree->ViewPointValid(viewPoint))
2291                {
2292                        return true;
2293                }
2294        }
2295        Debug << "failed to find valid view point, taking " << viewPoint << endl;
2296        return false;
2297}
2298
2299
2300bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
2301{
2302  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
2303  // validy update in preprocessor for all managers)
2304  return ViewCellsManager::ViewPointValid(viewPoint);
2305
2306  //    return mViewSpaceBox.IsInside(viewPoint) &&
2307  //               mVspBspTree->ViewPointValid(viewPoint);
2308}
2309
2310
2311void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
2312                                                                           const VssRayContainer &sampleRays)
2313{
2314        if (!ViewCellsConstructed())
2315                return;
2316
2317        VssRayContainer visRays;
2318        GetRaySets(sampleRays, mVisualizationSamples, visRays);
2319
2320        if (1) // export view cells
2321        {
2322                cout << "exporting view cells after post process ... ";
2323                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
2324
2325                if (exporter)
2326                {
2327                        if (1)
2328                        {
2329                                exporter->SetWireframe();
2330                                exporter->ExportBox(mViewSpaceBox);
2331                                exporter->SetFilled();
2332                        }
2333
2334                        if (mExportGeometry)
2335                        {
2336                                exporter->ExportGeometry(objects);
2337                        }
2338
2339                        // export rays
2340                        if (mExportRays)
2341                        {
2342                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2343                        }
2344
2345                        ExportViewCellsForViz(exporter);
2346                        delete exporter;
2347                }
2348        }
2349
2350        //-- visualization of the BSP splits
2351        bool exportSplits = false;
2352        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
2353
2354        if (exportSplits)
2355        {
2356                cout << "exporting splits ... ";
2357                ExportSplits(objects, visRays);
2358                cout << "finished" << endl;
2359        }
2360
2361        //-- export single view cells
2362        ExportBspPvs(objects, visRays);
2363}
2364
2365
2366void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2367                                                                                  const VssRayContainer &rays)
2368{
2369        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2370
2371        if (exporter)
2372        {
2373                Material m;
2374                m.mDiffuseColor = RgbColor(1, 0, 0);
2375                exporter->SetForcedMaterial(m);
2376                exporter->SetWireframe();
2377
2378                exporter->ExportBspSplits(*mVspBspTree, true);
2379
2380                // take forced material, else big scenes cannot be viewed
2381                m.mDiffuseColor = RgbColor(0, 1, 0);
2382                exporter->SetForcedMaterial(m);
2383                exporter->SetFilled();
2384
2385                exporter->ResetForcedMaterial();
2386
2387                // export rays
2388                if (mExportRays)
2389                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
2390
2391                if (mExportGeometry)
2392                        exporter->ExportGeometry(objects);
2393
2394                delete exporter;
2395        }
2396}
2397
2398
2399void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2400                                                                                  const VssRayContainer &rays)
2401{
2402        const int leafOut = 10;
2403
2404        ViewCell::NewMail();
2405
2406        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
2407        Debug << "\nOutput view cells: " << endl;
2408
2409        // sort view cells to visualize the largest view cells
2410#if 0
2411        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2412#endif
2413        int limit = min(leafOut, (int)mViewCells.size());
2414
2415#if 1
2416        //-- some rays for output
2417        vector<BspRay *> bspRays;
2418        mVspBspTree->ConstructBspRays(bspRays, rays);
2419
2420        const int raysOut = min((int)bspRays.size(), mVisualizationSamples);
2421#endif
2422
2423        for (int i = 0; i < limit; ++ i)
2424        {
2425                cout << "creating output for view cell " << i << " ... ";
2426
2427                VssRayContainer vcRays;
2428                Intersectable::NewMail();
2429#if 0 // largest view cell pvs first
2430                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
2431#else
2432                BspViewCell *vc = dynamic_cast<BspViewCell *>
2433                        (mViewCells[Random((int)mViewCells.size())]);
2434#endif
2435
2436#if 1
2437                // check whether we can add the current ray to the output rays
2438                for (int k = 0; k < raysOut; ++ k)
2439                {
2440                        BspRay *ray = bspRays[k];
2441                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
2442                        {
2443                                BspLeaf *leaf = ray->intersections[j].mLeaf;
2444                                if (vc == leaf->GetViewCell())
2445                                        vcRays.push_back(ray->vssRay);
2446                        }
2447                }
2448#endif
2449                //bspLeaves[j]->Mail();
2450                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
2451                Exporter *exporter = Exporter::GetExporter(s);
2452                exporter->SetWireframe();
2453
2454                Material m;//= RandomMaterial();
2455                m.mDiffuseColor = RgbColor(0, 1, 0);
2456                exporter->SetForcedMaterial(m);
2457
2458                ExportVcGeometry(exporter, vc);
2459
2460
2461                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
2462                          << ", piercing rays=" << (int)vcRays.size()
2463                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
2464
2465                //-- export rays piercing this view cell
2466#if 1
2467                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
2468#endif
2469#if 0
2470                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
2471
2472                for (lit = vc->mLeaves.begin(); lit != lit_end; ++ lit)
2473                        exporter->ExportRays((*lit)->mVssRays);
2474#endif
2475                m.mDiffuseColor = RgbColor(1, 0, 0);
2476                exporter->SetForcedMaterial(m);
2477
2478                ObjectPvsMap::const_iterator it,
2479                        it_end = vc->GetPvs().mEntries.end();
2480
2481                exporter->SetFilled();
2482
2483                // output PVS of view cell
2484                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
2485                {
2486                        Intersectable *intersect = (*it).first;
2487
2488                        if (!intersect->Mailed())
2489                        {
2490                                Material m = RandomMaterial();
2491                                exporter->SetForcedMaterial(m);
2492
2493                                exporter->ExportIntersectable(intersect);
2494                                intersect->Mail();
2495                        }
2496                }
2497
2498                DEL_PTR(exporter);
2499                cout << "finished" << endl;
2500        }
2501
2502#if 1
2503        CLEAR_CONTAINER(bspRays);
2504#endif
2505        Debug << endl;
2506}
2507
2508
2509int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2510                                                                                        const Vector3 &termination,
2511                                                                                        ViewCellContainer &viewcells)
2512{
2513        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
2514}
2515
2516
2517void VspBspViewCellsManager::ExportColor(Exporter *exporter,
2518                                                                                 ViewCell *vc) const
2519{
2520        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
2521
2522        float importance = 0;
2523        static Material m;
2524
2525        switch (mColorCode)
2526        {
2527        case 0: // Random
2528                {
2529                        if (vcValid)
2530                        {
2531                                m = RandomMaterial();
2532                        }
2533                        else
2534                        {
2535                                m.mDiffuseColor.r = 0.0f;
2536                                m.mDiffuseColor.g = 1.0f;
2537                                m.mDiffuseColor.b = 0.0f;
2538                        }
2539                }
2540                return;
2541        case 1: // pvs
2542                {
2543                        importance = (float)vc->GetPvs().GetSize() /
2544                                (float)mViewCellsStats.maxPvs;
2545
2546                }
2547                break;
2548        case 2: // merges
2549                {
2550            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2551
2552                        importance = (float)bspVc->mLeaves.size() /
2553                                (float)mViewCellsStats.maxLeaves;
2554                }
2555                break;
2556        case 3: // merge tree differene
2557                {
2558                        importance = (float)GetMaxTreeDiff(vc) /
2559                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2560
2561                }
2562                break;
2563        default:
2564                break;
2565        }
2566
2567        // special color code for invalid view cells
2568        m.mDiffuseColor.r = importance;
2569        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2570        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
2571
2572        //Debug << "importance: " << importance << endl;
2573        exporter->SetForcedMaterial(m);
2574}
2575
2576
2577void VspBspViewCellsManager::ExportVcGeometry(Exporter *exporter,
2578                                                                                          ViewCell *vc) const
2579{
2580        if (vc->GetMesh())
2581        {
2582                exporter->ExportMesh(vc->GetMesh());
2583                return;
2584        }
2585
2586        BspNodeGeometry geom;
2587        mVspBspTree->
2588                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom);
2589        exporter->ExportPolygons(geom.mPolys);
2590}
2591
2592
2593int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
2594{
2595        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2596
2597        int maxDist = 0;
2598        // compute max height difference
2599        for (int i = 0; i < (int)bspVc->mLeaves.size(); ++ i)
2600                for (int j = 0; j < (int)bspVc->mLeaves.size(); ++ j)
2601        {
2602                BspLeaf *leaf = bspVc->mLeaves[i];
2603
2604                if (i != j)
2605                {
2606                        BspLeaf *leaf2 = bspVc->mLeaves[j];
2607                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
2608                        if (dist > maxDist)
2609                                maxDist = dist;
2610                }
2611        }
2612        return maxDist;
2613}
2614
2615
2616ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
2617{
2618        if (!mVspBspTree)
2619                return NULL;
2620
2621        if (!mViewSpaceBox.IsInside(point))
2622          return NULL;
2623
2624        return mVspBspTree->GetViewCell(point);
2625}
2626
2627
2628void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
2629{
2630        BspNodeGeometry geom;
2631        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2632        mVspBspTree->ConstructGeometry(bspVc, geom);
2633
2634        Mesh *mesh = new Mesh();
2635        geom.AddToMesh(*mesh);
2636        vc->SetMesh(mesh);
2637        mMeshContainer.push_back(mesh);
2638}
2639
2640
2641bool VspBspViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
2642{
2643        ViewCellsParser parser;
2644
2645        DEL_PTR(mVspBspTree);
2646        mVspBspTree = new VspBspTree();
2647
2648        bool success = parser.ParseFile(filename, mVspBspTree, this, objects);
2649        mVspBspTree->RepairViewCellsLeafLists();
2650        mVspBspTree->mBox = GetViewSpaceBox();
2651        ResetViewCells();
2652
2653        mViewCellsFinished = true;
2654        mMaxPvsSize = (int)objects->size();
2655
2656        FinalizeViewCells(true);
2657
2658        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
2659
2660        return success;
2661}
2662
2663
2664inline bool ilt(Intersectable *obj1, Intersectable *obj2)
2665{
2666        return obj1->mId < obj2->mId;
2667}
2668
2669
2670bool VspBspViewCellsManager::ExportViewCells(const string filename)
2671{
2672        cout << "exporting view cells to xml ... ";
2673        std::ofstream stream;
2674
2675        // for output we need unique ids
2676        CreateUniqueViewCellIds();
2677
2678        stream.open(filename.c_str());
2679        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2680        stream << "<Visibility_Solution>" << endl;
2681
2682        //-- load the view cells itself, i.e., the ids and the pvs
2683        stream << "<ViewCells>" << endl;
2684        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2685        for (it = mViewCells.begin(); it != it_end; ++ it)
2686                ExportViewCell(*it, stream);
2687
2688        stream << "</ViewCells>" << endl;
2689
2690        //-- load the hierarchy
2691        stream << "<BspTree>" << endl;
2692        mVspBspTree->Export(stream);
2693        stream << endl << "</BspTree>" << endl;
2694
2695        stream << "</Visibility_Solution>" << endl;
2696        stream.close();
2697
2698        cout << "finished" << endl;
2699
2700        return true;
2701}
2702
2703
2704int VspBspViewCellsManager::CastBeam(Beam &beam)
2705{
2706        return mVspBspTree->CastBeam(beam);
2707}
2708
2709
2710void VspBspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
2711{
2712        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCell);
2713        CreateMesh(vc);
2714
2715        vector<BspLeaf *>::const_iterator it, it_end = vc->mLeaves.end();
2716
2717        float area = 0;
2718        float volume = 0;
2719
2720        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
2721        {
2722                BspNodeGeometry geom;
2723                BspLeaf *leaf = *it;
2724                mVspBspTree->ConstructGeometry(leaf, geom);
2725
2726                area += geom.GetArea();
2727                volume += geom.GetVolume();
2728        }
2729
2730        viewCell->SetVolume(volume);
2731        viewCell->SetArea(area);
2732}
Note: See TracBrowser for help on using the repository browser.