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

Revision 569, 62.4 KB checked in by bittner, 18 years ago (diff)

viewcell validy setting functions extended

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