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

RevLine 
[440]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"
[442]12#include "VspBspTree.h"
[508]13#include "ViewCellsParser.h"
[532]14#include "Beam.h"
[540]15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
[440]17
[517]18
[532]19
[440]20ViewCellsManager::ViewCellsManager():
[480]21mRenderer(NULL),
[440]22mConstructionSamples(0),
23mPostProcessSamples(0),
[470]24mVisualizationSamples(0),
25mTotalAreaValid(false),
[517]26mTotalArea(0.0f),
[547]27mViewCellsFinished(false),
[562]28mMaxPvsSize(9999999),
[564]29mMinPvsSize(0), // one means only empty view cells are invalid
[561]30mMaxPvsRatio(1.0)
[440]31{
[542]32        mViewSpaceBox.Initialize();
[482]33        ParseEnvironment();
[440]34}
35
[517]36
[440]37ViewCellsManager::ViewCellsManager(int constructionSamples):
38mConstructionSamples(constructionSamples),
[480]39mRenderer(NULL),
[440]40mPostProcessSamples(0),
[517]41mVisualizationSamples(0),
[562]42mTotalAreaValid(false),
43mTotalArea(0.0f),
44mViewCellsFinished(false),
45mMaxPvsSize(9999999),
[564]46mMinPvsSize(0), // one means only empty view cells are invalid
[562]47mMaxPvsRatio(1.0)
[440]48{
[542]49        mViewSpaceBox.Initialize();
[482]50        ParseEnvironment();
51}
52
[517]53
[482]54void ViewCellsManager::ParseEnvironment()
55{
[503]56        // visualization stuff
[485]57        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
58        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
[547]59        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[564]60        bool emptyViewCells = false;
61        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", emptyViewCells);
62        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]63
[564]64        mMinPvsSize = emptyViewCells ? 1 : 0;
65
[482]66        char buf[50];
67        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
[503]68
[482]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;
[440]79}
80
[485]81
[440]82ViewCellsManager::~ViewCellsManager()
83{
[480]84        DEL_PTR(mRenderer);
[469]85        CLEAR_CONTAINER(mViewCells);
[503]86        CLEAR_CONTAINER(mMeshContainer);
[440]87}
88
[485]89
[527]90int ViewCellsManager::Construct(VssRayContainer &rays)
91{
[542]92/*      VssPreprocessor preprocessor;
[540]93
[542]94        VssRayContainer vssRays;
95        preprocessor->GenerateVssRays(mConstructionSamples, vssRays);
96        Construct(preprocessor->mObjects, vssRays);
[564]97
[542]98        // add rays to output rays
99        while (!vssRays.empty)
100        {
101                rays.push_back(vssRays.back());
102                vssRays.pop_back();
103        }
[540]104
[542]105        const int importanceRays = 1000000;
106        preprocessor->GenerateVssRays(max(importanceRays, mPostProcessSamples);
[540]107
[542]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();
[527]119}
120
[547]121
[564]122bool ViewCellsManager::CheckValidity(ViewCell *vc,
123                                                                         int minPvsSize,
[562]124                                                                         int maxPvsSize) const
[547]125{
[569]126
127  if ((vc->GetPvs().GetSize() > maxPvsSize) ||
128          (vc->GetPvs().GetSize() < minPvsSize))
[564]129        {
[569]130          return false;
[561]131        }
[569]132 
133  return true;
[547]134}
135
136
[564]137void ViewCellsManager::SetValidity(ViewCell *vc,
138                                                                   int minPvs,
[562]139                                                                   int maxPvs) const
140{
141        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
142}
143
[569]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}
[562]155
[569]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
[508]183bool ViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
[440]184{
185        X3dParser parser;
[503]186
[440]187        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]188
[440]189        bool success = parser.ParseFile(filename, *this);
190        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
191
192        return success;
193}
194
[485]195
[487]196bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
197{
[542]198        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]199
200        return true;
201}
202
203
[557]204float ViewCellsManager::GetViewSpaceVolume()
205{
206        return mViewSpaceBox.GetVolume()*(2.0f*sqr(M_PI));
207}
208
209
[490]210bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
211{
[569]212  if (!ViewCellsConstructed())
[542]213        return mViewSpaceBox.IsInside(viewPoint);
[569]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;
[490]222}
223
[501]224
[563]225float
226ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
227                                                                                         const bool addRays
228                                                                                         )
[440]229{
[563]230  // view cells not yet constructed
231  if (!ViewCellsConstructed())
232        return 0.0f;
[564]233
[563]234  VssRayContainer::const_iterator it, it_end = rays.end();
[503]235
[563]236  float sum = 0.0f;
237  for (it = rays.begin(); it != it_end; ++ it) {
238        sum += ComputeSampleContributions(*(*it), addRays);
[567]239        //ComputeSampleContributions(*(*it), addRays);
240        //      sum += (*it)->mPvsContribution;
[563]241  }
242  return sum;
[440]243}
244
[485]245
[479]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)
[487]253        {
[479]254                (*it)->UpdateViewCellsStats(mViewCellsStats);
[487]255        }
[479]256}
257
[485]258
[440]259void ViewCellsManager::AddViewCell(ViewCell *viewCell)
260{
261        mViewCells.push_back(viewCell);
262}
263
[485]264
[478]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
[485]276
[503]277void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
278                                                                           ViewCellContainer &viewCells,
[440]279                                                                           const int maxViewCells) const
280{
281        // maximal max viewcells
[503]282        int limit = maxViewCells > 0 ?
[440]283                Min((int)objects.size(), maxViewCells) : (int)objects.size();
284
285        for (int i = 0; i < limit; ++ i)
286        {
287                Intersectable *object = objects[i];
[503]288
[440]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
[485]301
[503]302ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]303                                                                                        const float height) const
304{
305        // one mesh per view cell
306        Mesh *mesh = new Mesh();
[503]307
[440]308        //-- construct prism
309
[503]310        // bottom
[440]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
[503]322        Triangle3 topTri;
[440]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]);
[503]327
328        // add top vertices
[440]329        for (int i = 0; i < 3; ++ i)
330                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]331
[440]332        mesh->Preprocess();
333
334        return GenerateViewCell(mesh);
335}
336
[485]337
[551]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        }
[555]345
346        mTotalAreaValid = false;
[551]347}
348
349
350void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
351{
352        // implemented in subclasses
353}
354
355
[441]356ViewCell *ViewCellsManager::MergeViewCells(ViewCell &front, ViewCell &back) const
[440]357{
[462]358        // generate merged view cell
[440]359        ViewCell *vc = GenerateViewCell();
[462]360
[440]361        // merge pvs
362        vc->GetPvs().Merge(front.GetPvs(), back.GetPvs());
363
[462]364        //-- merge ray sets
[564]365        if (0)
366        {
367                stable_sort(front.mPiercingRays.begin(), front.mPiercingRays.end());
368                stable_sort(back.mPiercingRays.begin(), back.mPiercingRays.end());
[440]369
[564]370                std::merge(front.mPiercingRays.begin(), front.mPiercingRays.end(),
371                                   back.mPiercingRays.begin(), back.mPiercingRays.end(),
372                                   vc->mPiercingRays.begin());
373        }
[440]374
375        return vc;
376}
377
[485]378
[480]379void ViewCellsManager::SetRenderer(Renderer *renderer)
380{
381        mRenderer = renderer;
382}
[441]383
[485]384
[440]385ViewCell *ViewCellsManager::GenerateViewCell(Mesh *mesh) const
386{
387        return new ViewCell(mesh);
388}
389
390
391void ViewCellsManager::SetVisualizationSamples(const int visSamples)
392{
[444]393        mVisualizationSamples = visSamples;
[440]394}
395
[485]396
[440]397void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
398{
399        mConstructionSamples = constructionSamples;
400}
401
[485]402
[440]403void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
404{
405        mPostProcessSamples = postProcessSamples;
406}
407
[485]408
[440]409int ViewCellsManager::GetVisualizationSamples() const
410{
411        return mVisualizationSamples;
412}
413
[485]414
[440]415int ViewCellsManager::GetConstructionSamples() const
416{
417        return mConstructionSamples;
418}
419
[485]420
[440]421int ViewCellsManager::GetPostProcessSamples() const
422{
423        return mPostProcessSamples;
424}
425
[485]426
427void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]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
[485]449
[480]450void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]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
[485]460
[532]461int ViewCellsManager::CastBeam(Beam &beam)
462{
463        return 0;
464}
465
[547]466
[468]467ViewCellContainer &ViewCellsManager::GetViewCells()
468{
469        return mViewCells;
470}
471
[485]472
[487]473void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
474{
[542]475        mViewSpaceBox = box;
[487]476}
477
478
[519]479AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
480{
[542]481        return mViewSpaceBox;
[519]482}
483
484
[480]485void ViewCellsManager::ResetViewCells()
486{
487        mViewCells.clear();
[564]488
[480]489        CollectViewCells();
[564]490
[480]491        mViewCellsStats.Reset();
492        EvaluateViewCellsStats();
[520]493        // has to be recomputed
[480]494        mTotalAreaValid = false;
495}
496
[485]497
[547]498int ViewCellsManager::GetMaxPvsSize() const
499{
500        return mMaxPvsSize;
501}
502
[563]503void
504ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
505{
506  if (!ViewCellsConstructed())
507        return;
[564]508
[563]509  VssRayContainer::const_iterator it, it_end = rays.end();
[564]510
[563]511  for (it = rays.begin(); it != it_end; ++ it) {
512        AddSampleContributions(*(*it));
513  }
514}
[547]515
[562]516int ViewCellsManager::GetMinPvsSize() const
517{
518        return mMinPvsSize;
519}
520
521
522
[561]523float ViewCellsManager::GetMaxPvsRatio() const
524{
525        return mMaxPvsRatio;
526}
527
528
[563]529void
530ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]531{
[563]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;
[569]537        if (viewcell->GetValid()) {
538          // if ray not outside of view space
539          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
540        }
[563]541  }
542}
[503]543
[563]544float
545ViewCellsManager::ComputeSampleContributions(VssRay &ray,
546                                                                                         const bool addRays
547                                                                                         )
548{
549  ViewCellContainer viewcells;
[564]550
[563]551  ray.mPvsContribution = 0;
552  ray.mRelativePvsContribution = 0.0f;
[485]553
[564]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))
[565]562                return 0;
[564]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;
[565]569        CastLineSegment(origin, termination, viewcells);
[564]570
[563]571  //Debug << "constribution: " << (int)viewcells.size() << endl;
[564]572
[563]573  // copy viewcells memory efficiently
574  const bool storeViewcells = !addRays;
[564]575
[563]576  if (storeViewcells)
[564]577  {
[569]578        ray.mViewCells.reserve(viewcells.size());
579        ray.mViewCells = viewcells;
580  }
[564]581
[563]582  ViewCellContainer::const_iterator it = viewcells.begin();
[564]583
584
[563]585  for (; it != viewcells.end(); ++it) {
586        ViewCell *viewcell = *it;
[569]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        }
[563]597  }
[564]598
[563]599  if (addRays)
600        for (it = viewcells.begin(); it != viewcells.end(); ++it) {
601          ViewCell *viewcell = *it;
[569]602          if (viewcell->GetValid()) {
603                // if ray not outside of view space
604                viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
605          }
[563]606        }
[569]607 
[563]608  return ray.mRelativePvsContribution;
[468]609}
610
611
[469]612void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]613                                                                  const int maxSize,
[503]614                                                                  VssRayContainer &usedRays,
[485]615                                                                  VssRayContainer *savedRays) const
[469]616{
[485]617        const int limit = min(maxSize, (int)sourceRays.size());
[473]618        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]619
[485]620        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]621        for (it = sourceRays.begin(); it != it_end; ++ it)
622        {
[473]623                if (Random(1.0f) < prop)
[485]624                        usedRays.push_back(*it);
625                else if (savedRays)
626                        savedRays->push_back(*it);
[469]627        }
628}
629
[477]630
631float ViewCellsManager::GetAccVcArea()
[470]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)
[480]641        {
642                //Debug << "area: " << GetArea(*it);
[470]643        mTotalArea += GetArea(*it);
[480]644        }
645
[470]646        mTotalAreaValid = true;
647
648        return mTotalArea;
649}
650
[482]651
[475]652void ViewCellsManager::PrintStatistics(ostream &s) const
653{
654        s << mViewCellsStats << endl;
655}
656
[477]657
[508]658void ViewCellsManager::CreateUniqueViewCellIds()
[482]659{
[508]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{
[482]667        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
668
669        for (it = mViewCells.begin(); it != it_end; ++ it)
670        {
671                ExportColor(exporter, *it);
[485]672                ExportVcGeometry(exporter, *it);
[482]673        }
674}
675
676
[517]677void ViewCellsManager::CreateViewCellMeshes()
[503]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        {
[517]684                if (!(*it)->GetMesh())
685                        CreateMesh(*it);
[503]686        }
687}
688
[508]689
[564]690bool ViewCellsManager::ExportViewCells(const string filename)
691{
[508]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
[440]712/**********************************************************************/
713/*                   BspViewCellsManager implementation               */
714/**********************************************************************/
715
[482]716
[503]717BspViewCellsManager::BspViewCellsManager(BspTree *bspTree,
[469]718                                                                                 int constructionSamples):
[503]719ViewCellsManager(constructionSamples),
[440]720mBspTree(bspTree)
721{
722}
723
[462]724
[440]725bool BspViewCellsManager::ViewCellsConstructed() const
726{
727        return mBspTree->GetRoot() != NULL;
728}
729
[480]730
[440]731ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
732{
733        return new BspViewCell(mesh);
734}
735
[480]736
[503]737int BspViewCellsManager::Construct(const ObjectContainer &objects,
[487]738                                                                   const VssRayContainer &rays)
[440]739{
[441]740        // if view cells were already constructed
[440]741        if (ViewCellsConstructed())
742                return 0;
743
744        int sampleContributions = 0;
[503]745
[469]746        // construct view cells using the collected samples
747        RayContainer constructionRays;
748        VssRayContainer savedRays;
[440]749
[469]750        const int limit = min(mConstructionSamples, (int)rays.size());
[440]751
[469]752        VssRayContainer::const_iterator it, it_end = rays.end();
[448]753
[473]754        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
755
[469]756        for (it = rays.begin(); it != it_end; ++ it)
757        {
[473]758                if (Random(1.0f) < prop)
[469]759                        constructionRays.push_back(new Ray(*(*it)));
760                else
761                        savedRays.push_back(*it);
762        }
[440]763
[503]764    if (mViewCells.empty())
765        {
766                // no view cells loaded
[469]767                mBspTree->Construct(objects, constructionRays);
768                // collect final view cells
769                mBspTree->CollectViewCells(mViewCells);
[503]770        }
[469]771        else
772        {
773                mBspTree->Construct(mViewCells);
774        }
775
776        // destroy rays created only for construction
777        CLEAR_CONTAINER(constructionRays);
778
[440]779        Debug << mBspTree->GetStatistics() << endl;
[503]780
781        //EvaluateViewCellsStats();
[480]782        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
783
[469]784        // recast rest of the rays
785        ComputeSampleContributions(savedRays);
786
[503]787
[440]788        return sampleContributions;
789}
790
[503]791
[480]792void BspViewCellsManager::CollectViewCells()
793{
794        mBspTree->CollectViewCells(mViewCells);
795}
[468]796
[503]797
[471]798float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]799{
[471]800        // compute view cell area as subsititute for probability
[557]801#if 1
802        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[477]803#else
804        return GetArea(viewCell) / GetAccVcArea();
805#endif
[466]806}
[440]807
[503]808
[469]809float BspViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[466]810{
[468]811        return viewCell->GetPvs().GetSize() * objRendercost;
[440]812}
813
[468]814
815int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
816                                                                                 const Vector3 &termination,
817                                                                                 ViewCellContainer &viewcells)
[440]818{
[468]819        return mBspTree->CastLineSegment(origin, termination, viewcells);
820}
821
822
[503]823int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]824                                                                         const VssRayContainer &rays)
825{
[469]826        if (!ViewCellsConstructed())
[441]827        {
828                Debug << "view cells not constructed" << endl;
829                return 0;
830        }
831
[440]832        //-- post processing of bsp view cells
833    int vcSize = 0;
834        int pvsSize = 0;
835
[480]836        EvaluateViewCellsStats();
[485]837        Debug << "\noriginal view cell partition:\n" << mViewCellsStats << endl;
[480]838
839        mRenderer->RenderScene();
840        SimulationStatistics ss;
841        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
842
843    Debug << ss << endl;
844
[477]845        if (1) // export view cells
[440]846        {
847                cout << "exporting initial view cells (=leaves) ... ";
848                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]849
[440]850                if (exporter)
851                {
[477]852                        //exporter->SetWireframe();
853                        exporter->SetFilled();
[508]854                        ExportViewCellsForViz(exporter);
[503]855
[485]856                        if (mExportGeometry)
[440]857                        {
[477]858                                Material m;
[440]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 ... ";
[503]872
[440]873        long startTime = GetTime();
874
[477]875
[466]876        // $$JB we do not have connectivity information from the ray in the moment
[485]877        // perhaps we could recast the rays or remember the cells traversed inside the
[466]878        // vssray (which would on other hand create some overhead)
[440]879        //-- merge or subdivide view cells
880        int merged = 0;
881
[475]882        vector<BspIntersection>::const_iterator iit;
[485]883        CLEAR_CONTAINER(mBspRays);
884        ConstructBspRays(rays, mPostProcessSamples);
[503]885
[477]886        for (int i = 0; i < (int)mBspRays.size(); ++ i)
[503]887        {
[477]888                BspRay *ray = mBspRays[i];
[503]889
[440]890                // traverse leaves stored in the rays and compare and merge consecutive
891                // leaves (i.e., the neighbors in the tree)
[477]892                if (ray->intersections.size() < 2)
[440]893                        continue;
[561]894#if 0
[477]895                iit = ray->intersections.begin();
[440]896
897                BspLeaf *previousLeaf = (*iit).mLeaf;
898                ++ iit;
[503]899
[477]900                for (; iit != ray->intersections.end(); ++ iit)
[440]901                {
902                        BspLeaf *leaf = (*iit).mLeaf;
903
[441]904                        if (ShouldMerge(leaf, previousLeaf))
[503]905                        {
[441]906                                MergeBspLeafViewCells(leaf, previousLeaf);
[440]907
908                                ++ merged;
909                        }
[503]910
[440]911                        previousLeaf = leaf;
912                }
[561]913#endif
[440]914        }
[477]915
[440]916        //-- stats and visualizations
917        cout << "finished" << endl;
918        cout << "merged " << merged << " view cells in "
919                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
920
[475]921        Debug << "Postprocessing: Merged " << merged << " view cells in "
[503]922                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs"
[485]923                  << "using " << (int)mBspRays.size() << " samples" << endl << endl;
[503]924
[485]925        CLEAR_CONTAINER(mBspRays);
926
[477]927        // reset view cells and stats
[480]928        ResetViewCells();
[475]929
[440]930        return merged;
931}
932
[477]933
934BspViewCellsManager::~BspViewCellsManager()
935{
936        CLEAR_CONTAINER(mBspRays);
937}
938
939
[440]940int BspViewCellsManager::GetType() const
941{
942        return BSP;
943}
944
945
946void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]947                                                                        const VssRayContainer &sampleRays)
[440]948{
[469]949        if (!ViewCellsConstructed())
950                return;
[485]951        CLEAR_CONTAINER(mBspRays);
952        ConstructBspRays(sampleRays, mVisualizationSamples);
[503]953
[469]954        if (1) // export view cells
[440]955        {
[469]956                cout << "exporting view cells after merge ... ";
957                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[477]958
[557]959
[469]960                if (exporter)
[440]961                {
[508]962                        ExportViewCellsForViz(exporter);
[469]963                        delete exporter;
[440]964                }
[503]965
[469]966                cout << "finished" << endl;
[503]967        }
[477]968
[469]969        //-- visualization of the BSP splits
970        bool exportSplits = false;
971        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]972
[469]973        if (exportSplits)
[440]974        {
[469]975                cout << "exporting splits ... ";
[477]976                ExportSplits(objects);
[469]977                cout << "finished" << endl;
[440]978        }
[477]979
980        ExportBspPvs(objects);
[440]981}
982
983
[503]984inline bool vc_gt(ViewCell *a, ViewCell *b)
985{
[440]986        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
987}
988
[477]989
990void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]991{
992        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
993
[503]994        if (exporter)
995        {
996                Material m;
[440]997                m.mDiffuseColor = RgbColor(1, 0, 0);
998                exporter->SetForcedMaterial(m);
999                exporter->SetWireframe();
[503]1000
[440]1001                exporter->ExportBspSplits(*mBspTree, true);
1002
[482]1003                //NOTE: take forced material, else big scenes cannot be viewed
[440]1004                m.mDiffuseColor = RgbColor(0, 1, 0);
1005                exporter->SetForcedMaterial(m);
[482]1006                //exporter->ResetForcedMaterial();
1007
[440]1008                exporter->SetFilled();
[503]1009
[440]1010                // export rays
[477]1011                if (0)
[440]1012                {
[469]1013                        VssRayContainer outRays;
[503]1014
[477]1015                        int raysSize = min((int)mBspRays.size(), mVisualizationSamples);
1016
[469]1017                        for (int i = 0; i < raysSize; ++ i)
1018                                // only rays piercing geometry
[477]1019                                outRays.push_back(mBspRays[i]->vssRay);
[503]1020
1021                        // export rays
[469]1022                        exporter->ExportRays(outRays, RgbColor(1, 1, 0));
[440]1023                }
[477]1024
[485]1025                if (mExportGeometry)
[469]1026                        exporter->ExportGeometry(objects);
[477]1027
[440]1028                delete exporter;
1029        }
1030}
1031
[477]1032
1033void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]1034{
[477]1035        const int leafOut = 10;
[503]1036
[477]1037        ViewCell::NewMail();
[440]1038
[477]1039        //-- some rays for output
1040        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]1041
[477]1042        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1043        Debug << "\nOutput view cells: " << endl;
[503]1044
[478]1045        // sort view cells to get largest view cells
1046#if 0
1047        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1048#endif
[503]1049        int limit = min(leafOut, (int)mViewCells.size());
1050
[478]1051        for (int i = 0; i < limit; ++ i)
[477]1052        {
[478]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 << " ... ";
[469]1062
[478]1063#if 0
1064                // check whether we can add the current ray to the output rays
[503]1065                for (int k = 0; k < raysOut; ++ k)
[477]1066                {
[478]1067                        BspRay *ray = mBspRays[k];
1068                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[477]1069                        {
[478]1070                                BspLeaf *leaf = ray->intersections[j].mLeaf;
[503]1071                                if (vc == leaf->GetViewCell())
[478]1072                                        vcRays.push_back(ray->vssRay);
[477]1073                        }
1074                }
[478]1075#endif
1076                //bspLeaves[j]->Mail();
1077                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]1078
[478]1079                Exporter *exporter = Exporter::GetExporter(s);
[503]1080
[478]1081                exporter->SetWireframe();
[477]1082
[478]1083                Material m;//= RandomMaterial();
1084                m.mDiffuseColor = RgbColor(0, 1, 0);
1085                exporter->SetForcedMaterial(m);
[477]1086
[478]1087                if (vc->GetMesh())
1088                        exporter->ExportViewCell(vc);
1089                else
1090                {
[503]1091                        BspNodeGeometry vcGeom;
1092
[478]1093                        //-- export view cell
1094                        mBspTree->ConstructGeometry(vc, vcGeom);
[503]1095                        exporter->ExportPolygons(vcGeom.mPolys);
[478]1096                }
[503]1097
1098                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[485]1099                          << ", piercing rays=" << (int)vcRays.size()
1100                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
[477]1101
[503]1102
[478]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);
[440]1113
[478]1114                ObjectPvsMap::const_iterator it,
1115                        it_end = vc->GetPvs().mEntries.end();
[440]1116
[478]1117                exporter->SetFilled();
[469]1118
[478]1119                // output PVS of view cell
[503]1120                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]1121                {
1122                        Intersectable *intersect = (*it).first;
[469]1123
[478]1124                        if (!intersect->Mailed())
1125                        {
1126                                Material m = RandomMaterial();
1127                                exporter->SetForcedMaterial(m);
1128
1129                                exporter->ExportIntersectable(intersect);
1130                                intersect->Mail();
[503]1131                        }
[477]1132                }
[503]1133
[478]1134                DEL_PTR(exporter);
1135                cout << "finished" << endl;
[477]1136        }
1137
1138        Debug << endl;
[440]1139}
1140
[441]1141
[503]1142
[477]1143void BspViewCellsManager::ConstructBspRays(const VssRayContainer &rays,
1144                                                                                   const int numSamples)
1145{
1146        VssRayContainer::const_iterator it, it_end = rays.end();
[467]1147
[477]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
[483]1155                // cast line segment to get intersections with bsp leaves
[477]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
[503]1170void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]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                {
[503]1185                        importance = (float)vc->GetPvs().GetSize() /
[482]1186                                (float)mViewCellsStats.maxPvs;
1187                }
1188                break;
1189        case 2: // merges
1190                {
1191                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
1192
[503]1193                        importance = (float)bspVc->mLeaves.size() /
[482]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;
[503]1210
[482]1211        exporter->SetForcedMaterial(m);
1212}
1213
[503]1214void BspViewCellsManager::ExportVcGeometry(Exporter *exporter,
[482]1215                                                                                 ViewCell *vc) const
1216{
1217        if (vc->GetMesh())
1218                exporter->ExportViewCell(vc);
1219        else
1220        {
[503]1221                BspNodeGeometry geom;
[485]1222                mBspTree->ConstructGeometry(
[503]1223                        dynamic_cast<BspViewCell *>(vc), geom);
1224                exporter->ExportPolygons(geom.mPolys);
[482]1225        }
1226}
1227
[503]1228
1229void BspViewCellsManager::CreateMesh(ViewCell *vc)
1230{
[551]1231        // TODO
[503]1232}
1233
[551]1234
[569]1235ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
[502]1236{
1237  if (!mBspTree)
1238        return NULL;
1239  return mBspTree->GetViewCell(point);
1240}
1241
[440]1242/**********************************************************************/
1243/*                   KdViewCellsManager implementation               */
1244/**********************************************************************/
1245
[503]1246
1247
[440]1248KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]1249ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]1250{
1251}
1252
[471]1253float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1254{
[479]1255        // compute view cell area / volume as subsititute for probability
[477]1256#if 0
[519]1257        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[479]1258#endif
1259#if 1
[477]1260        return GetArea(viewCell) / GetAccVcArea();
1261#endif
[479]1262#if 0
[519]1263        return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[479]1264#endif
[468]1265}
1266
1267
[469]1268float KdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1269{
[469]1270        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1271}
1272
[479]1273
[480]1274void KdViewCellsManager::CollectViewCells()
1275{
1276        //mKdTree->CollectViewCells(mViewCells); TODO
1277}
[479]1278
[519]1279
[503]1280int KdViewCellsManager::Construct(const ObjectContainer &objects,
[487]1281                                                                  const VssRayContainer &rays)
[440]1282{
[441]1283        // if view cells already constructed
[440]1284        if (ViewCellsConstructed())
1285                return 0;
[441]1286
[440]1287        mKdTree->Construct();
1288
[480]1289        mTotalAreaValid = false;
[469]1290        // create the view cells
1291        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]1292
[480]1293        // cast rays
1294        ComputeSampleContributions(rays);
1295
[479]1296        EvaluateViewCellsStats();
[480]1297        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[469]1298
[440]1299        return 0;
1300}
1301
1302bool KdViewCellsManager::ViewCellsConstructed() const
1303{
1304        return mKdTree->GetRoot() != NULL;
1305}
1306
[503]1307int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1308                                                                        const VssRayContainer &rays)
[440]1309{
1310        return 0;
1311}
1312
1313void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1314                                                                   const VssRayContainer &sampleRays)
[440]1315{
[441]1316        if (!ViewCellsConstructed())
1317                return;
1318
[469]1319        // using view cells instead of the kd PVS of objects
1320        const bool useViewCells = true;
1321        bool exportRays = false;
[440]1322
1323        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]1324        const int pvsOut = min((int)objects.size(), 10);
[466]1325        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]1326
[469]1327        if (useViewCells)
[440]1328        {
[469]1329                const int leafOut = 10;
[503]1330
[469]1331                ViewCell::NewMail();
[503]1332
[469]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;
[503]1339
[469]1340                for (int i = 0; i < leafOut; ++ i)
1341                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]1342
[469]1343                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]1344                {
[469]1345                        KdLeaf *leaf = kdLeaves[i];
1346                        RayContainer vcRays;
[503]1347
[469]1348                        cout << "creating output for view cell " << i << " ... ";
[503]1349#if 0
[469]1350                        // check whether we can add the current ray to the output rays
[503]1351                        for (int k = 0; k < raysOut; ++ k)
[440]1352                        {
[469]1353                                Ray *ray = sampleRays[k];
[503]1354
[469]1355                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
1356                                {
1357                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]1358
1359                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]1360                                        {
1361                                                vcRays.push_back(ray);
1362                                        }
1363                                }
[479]1364                        }
[503]1365#endif
[469]1366                        Intersectable::NewMail();
[503]1367
[469]1368                        ViewCell *vc = leaf->mViewCell;
[503]1369
[469]1370                        //bspLeaves[j]->Mail();
1371                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]1372
[469]1373                        Exporter *exporter = Exporter::GetExporter(s);
1374                        exporter->SetFilled();
1375
1376                        exporter->SetWireframe();
1377                        //exporter->SetFilled();
[503]1378
[469]1379                        Material m;//= RandomMaterial();
1380                        m.mDiffuseColor = RgbColor(1, 1, 0);
1381                        exporter->SetForcedMaterial(m);
[503]1382
[469]1383                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
1384                        exporter->ExportBox(box);
1385
[503]1386                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[469]1387                                << ", piercing rays=" << (int)vcRays.size() << endl;
[503]1388
[469]1389                        // export rays piercing this view cell
[503]1390                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
1391
[469]1392                        m.mDiffuseColor = RgbColor(1, 0, 0);
1393                        exporter->SetForcedMaterial(m);
[503]1394
[469]1395                        // exporter->SetWireframe();
1396                        exporter->SetFilled();
[503]1397
[469]1398                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
1399                        // output PVS of view cell
[503]1400                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]1401                        {
1402                                Intersectable *intersect = (*it).first;
1403                                if (!intersect->Mailed())
1404                                {
1405                                        exporter->ExportIntersectable(intersect);
1406                                        intersect->Mail();
[503]1407                                }
[440]1408                        }
[503]1409
[469]1410                        DEL_PTR(exporter);
1411                        cout << "finished" << endl;
[440]1412                }
[469]1413
1414                DEL_PTR(rays);
[440]1415        }
[469]1416        else // using kd PVS of objects
1417        {
1418                for (int i = 0; i < limit; ++ i)
1419                {
1420                        VssRay *ray = sampleRays[i];
[503]1421
[469]1422                        // check whether we can add this to the rays
[503]1423                        for (int j = 0; j < pvsOut; j++)
[469]1424                        {
1425                                if (objects[j] == ray->mTerminationObject)
1426                                {
1427                                        rays[j].push_back(ray);
1428                                }
1429                        }
1430                }
[440]1431
[503]1432                if (exportRays)
[469]1433                {
1434                        Exporter *exporter = NULL;
1435                        exporter = Exporter::GetExporter("sample-rays.x3d");
1436                        exporter->SetWireframe();
1437                        exporter->ExportKdTree(*mKdTree);
[503]1438
1439                        for (i=0; i < pvsOut; i++)
[469]1440                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
1441
1442                        exporter->SetFilled();
[503]1443
[469]1444                        delete exporter;
1445                }
[440]1446
[503]1447                for (int k=0; k < pvsOut; k++)
[469]1448                {
1449                        Intersectable *object = objects[k];
[503]1450                        char s[64];
[469]1451                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]1452
[469]1453                        Exporter *exporter = Exporter::GetExporter(s);
1454                        exporter->SetWireframe();
[503]1455
[469]1456                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
1457                        Intersectable::NewMail();
[503]1458
[469]1459                        // avoid adding the object to the list
1460                        object->Mail();
1461                        ObjectContainer visibleObjects;
[503]1462
1463                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]1464                        {
1465                                KdNode *node = (*i).first;
1466                                exporter->ExportBox(mKdTree->GetBox(node));
[503]1467
[469]1468                                mKdTree->CollectObjects(node, visibleObjects);
1469                        }
[503]1470
[469]1471                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
1472                        exporter->SetFilled();
[503]1473
[469]1474                        for (int j = 0; j < visibleObjects.size(); j++)
1475                                exporter->ExportIntersectable(visibleObjects[j]);
[503]1476
[469]1477                        Material m;
1478                        m.mDiffuseColor = RgbColor(1, 0, 0);
1479                        exporter->SetForcedMaterial(m);
1480                        exporter->ExportIntersectable(object);
[503]1481
[469]1482                        delete exporter;
[440]1483                }
[503]1484        }
[440]1485}
1486
[469]1487
[482]1488void KdViewCellsManager::ExportColor(Exporter *exporter,
1489                                                                         ViewCell *vc) const
1490{
1491        // TODO
1492}
1493
1494
[503]1495void KdViewCellsManager::ExportVcGeometry(Exporter *exporter,
[485]1496                                                                                  ViewCell *vc) const
[482]1497{
[485]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));
[482]1503}
1504
1505
[440]1506int KdViewCellsManager::GetType() const
1507{
1508        return ViewCellsManager::KD;
1509}
1510
1511
[441]1512
[440]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
[469]1522int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
1523                                                                                const Vector3 &termination,
1524                                                                                ViewCellContainer &viewcells)
[466]1525{
[469]1526        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]1527}
1528
[469]1529
[503]1530void KdViewCellsManager::CreateMesh(ViewCell *vc)
1531{
[551]1532        // TODO
[503]1533}
1534
[440]1535/**********************************************************************/
1536/*                   VspKdViewCellsManager implementation             */
1537/**********************************************************************/
1538
[482]1539
[503]1540VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree,
[462]1541                                                                                         int constructionSamples):
[503]1542ViewCellsManager(constructionSamples),
[440]1543mVspKdTree(vspKdTree)
1544{
[468]1545        mVspKdTree->SetViewCellsManager(this);
1546}
[462]1547
[471]1548float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1549{
1550        // volume or area substitutes for view point probability
[480]1551#if 0
[519]1552        return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
[480]1553#else
1554        return GetArea(viewCell) / GetAccVcArea();
1555#endif
[440]1556}
1557
[462]1558
[469]1559float VspKdViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
[468]1560{
[469]1561        return viewCell->GetPvs().GetSize() * objRendercost;
[468]1562}
1563
[503]1564
[480]1565void VspKdViewCellsManager::CollectViewCells()
1566{
1567        mVspKdTree->CollectViewCells(mViewCells);
1568}
[462]1569
[503]1570int VspKdViewCellsManager::Construct(const ObjectContainer &objects,
[487]1571                                                                         const VssRayContainer &rays)
[440]1572{
[441]1573        // if view cells already constructed
[440]1574        if (ViewCellsConstructed())
1575                return 0;
[503]1576
[469]1577        VssRayContainer constructionRays;
1578        VssRayContainer savedRays;
[440]1579
[503]1580        GetRaySets(rays,
1581                           mConstructionSamples,
1582                           constructionRays,
[485]1583                           &savedRays);
[503]1584
1585        Debug << "constructing vsp kd tree using "
[469]1586                  << (int)constructionRays.size() << " samples" << endl;
[452]1587
[542]1588        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]1589        Debug << mVspKdTree->GetStatistics() << endl;
1590
[482]1591        // export leaf building blocks
1592        ExportLeaves(objects, rays);
[480]1593
[469]1594        // finally merge kd leaf building blocks to view cells
[485]1595        const int merged = mVspKdTree->MergeViewCells(rays);
1596
1597        // collapse siblings belonging to the same view cell
[486]1598        mVspKdTree->RefineViewCells(rays);
[485]1599
[542]1600        // collapse siblings belonging to the same view cell
[503]1601        mVspKdTree->CollapseTree();
1602
[482]1603        // evaluale view cell stats
1604        ResetViewCells();
[469]1605
[482]1606        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
1607
[485]1608        long startTime = GetTime();
[469]1609        // recast rest of rays
1610        ComputeSampleContributions(savedRays);
[503]1611
1612        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]1613                  << " secs" << endl;
[469]1614
1615        return merged;
[440]1616}
1617
1618bool VspKdViewCellsManager::ViewCellsConstructed() const
1619{
1620        return mVspKdTree->GetRoot() != NULL;
1621}
1622
[441]1623
[462]1624ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
1625{
1626        return new VspKdViewCell(mesh);
1627}
1628
[503]1629int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]1630                                                                           const VssRayContainer &rays)
[440]1631{
[441]1632        if (!ViewCellsConstructed())
1633                return 0;
1634
[482]1635        // recalculate stats
1636        EvaluateViewCellsStats();
1637
[469]1638        return 0;
[440]1639}
1640
[482]1641
1642void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
1643                                                                                 const VssRayContainer &sampleRays)
[440]1644{
[441]1645        if (!ViewCellsConstructed())
1646                return;
1647
[482]1648        //-- export leaf building blocks
[503]1649        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]1650        if (!exporter)
1651                return;
1652
1653        //exporter->SetWireframe();
1654        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
1655        exporter->ExportVspKdTree(*mVspKdTree);
1656
[503]1657        if (mExportGeometry)
[482]1658                exporter->ExportGeometry(objects);
1659
[503]1660        if (mExportRays)
[440]1661        {
[503]1662                const float prob = (float)mVisualizationSamples
[482]1663                        / ((float)sampleRays.size() + Limits::Small);
[440]1664
[482]1665                exporter->SetWireframe();
[440]1666
[482]1667                //-- collect uniformly distributed rays
1668                VssRayContainer rays;
[440]1669
[482]1670                for (int i = 0; i < sampleRays.size(); ++ i)
1671                {
1672                        if (RandomValue(0,1) < prob)
1673                                rays.push_back(sampleRays[i]);
[440]1674                }
[482]1675                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]1676        }
1677
[482]1678        delete exporter;
1679}
1680
1681void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
1682                                                                          const VssRayContainer &sampleRays)
1683{
1684        if (!ViewCellsConstructed())
1685                return;
[503]1686
[482]1687        //-- export single view cells
1688        for (int i = 0; i < 10; ++ i)
[440]1689        {
[482]1690                char s[64];
1691                sprintf(s, "vsp_viewcell%04d.x3d", i);
1692                Exporter *exporter = Exporter::GetExporter(s);
[503]1693                const int idx =
[482]1694                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]1695
[503]1696                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]1697
[483]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;
[482]1700                //-- export geometry
1701                Material m;
1702                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]1703
[482]1704                exporter->SetForcedMaterial(m);
1705                exporter->SetWireframe();
1706
[485]1707                ExportVcGeometry(exporter, vc);
[482]1708
1709                //-- export stored rays
[485]1710                if (mExportRays)
[440]1711                {
[503]1712                        vector<VspKdLeaf *>::const_iterator it,
[482]1713                                it_end = vc->mLeaves.end();
[440]1714
[482]1715                        for (it = vc->mLeaves.begin(); it != it_end; ++ it)
1716                        {
1717                                VspKdLeaf *leaf = *it;
1718                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]1719
[482]1720                                VssRayContainer vssRays;
[483]1721
1722                                VssRayContainer castRays;
1723                                VssRayContainer initRays;
1724
[482]1725                                leaf->GetRays(vssRays);
[440]1726
[482]1727                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]1728                                const float prop = 200.0f / (float)vssRays.size();
[440]1729
[482]1730                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]1731                                {
[485]1732                                        if (Random(1) < prop)
[483]1733                                                if ((*it)->mTerminationObject == NULL)
1734                                                        castRays.push_back(*it);
[503]1735                                                else
[483]1736                                                        initRays.push_back(*it);
1737                                }
1738
1739                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
1740                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]1741                        }
1742                }
[440]1743
[482]1744                //-- output PVS of view cell
1745                m.mDiffuseColor = RgbColor(1, 0, 0);
1746                exporter->SetForcedMaterial(m);
[440]1747
[483]1748                Intersectable::NewMail();
1749
[482]1750                ObjectPvsMap::const_iterator it,
1751                        it_end = vc->GetPvs().mEntries.end();
1752
1753                exporter->SetFilled();
1754
[503]1755                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]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();
[503]1766                        }
[482]1767                }
1768
1769                delete exporter;
[440]1770        }
[462]1771
1772        //-- export final view cells
[503]1773        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
1774
[485]1775        //if (exportGeometry) exporter->SetWireframe();
1776        //else exporter->SetFilled();
[483]1777
[508]1778        ExportViewCellsForViz(exporter);
[462]1779
[503]1780        if (mExportGeometry)
[465]1781        {
1782                exporter->SetFilled();
[462]1783                exporter->ExportGeometry(objects);
[465]1784        }
[469]1785
[503]1786        if (mExportRays)
[462]1787        {
[503]1788                const float prob = (float)mVisualizationSamples
[482]1789                        / ((float)sampleRays.size() + Limits::Small);
[503]1790
[462]1791                exporter->SetWireframe();
[503]1792
[466]1793                VssRayContainer rays;
[503]1794
[462]1795                for (int i = 0; i < sampleRays.size(); ++ i)
1796                {
[466]1797                  if (RandomValue(0,1) < prob)
1798                        rays.push_back(sampleRays[i]);
[462]1799                }
[503]1800                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]1801        }
1802
1803        delete exporter;
[440]1804}
1805
1806int VspKdViewCellsManager::GetType() const
1807{
1808        return VSP_KD;
1809}
[442]1810
[462]1811
[469]1812int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
1813                                                                                   const Vector3 &termination,
1814                                                                                   ViewCellContainer &viewcells)
[466]1815{
[469]1816        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]1817}
1818
[477]1819
[482]1820void VspKdViewCellsManager::ExportColor(Exporter *exporter,
1821                                                                                ViewCell *vc) const
1822{
1823        if (mColorCode == 0) // Random color
1824                return;
[503]1825
[482]1826        float importance = 0;
[477]1827
[482]1828        switch (mColorCode)
1829        {
1830        case 1: // pvs
1831                {
[503]1832                        importance = (float)vc->GetPvs().GetSize() /
[482]1833                                (float)mViewCellsStats.maxPvs;
1834                }
1835                break;
1836        case 2: // merges
1837                {
1838            VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(vc);
1839
[503]1840                        importance = (float)vspKdVc->mLeaves.size() /
[482]1841                                (float)mViewCellsStats.maxLeaves;
1842                }
1843                break;
[485]1844        case 3: // merged tree depth difference
[482]1845                {
[503]1846                        //importance = (float)GetMaxTreeDiff(vc) /
[482]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
[503]1863void VspKdViewCellsManager::ExportVcGeometry(Exporter *exporter,
[482]1864                                                                                   ViewCell *vc) const
1865{
1866        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
1867        vector<VspKdLeaf *>::const_iterator it, it_end = kdVc->mLeaves.end();
1868
[486]1869        Mesh m;
[482]1870        for (it = kdVc->mLeaves.begin(); it != it_end; ++ it)
[486]1871        {
1872                mVspKdTree->GetBBox(*it).AddBoxToMesh(&m);
1873        }
1874
1875        exporter->ExportMesh(&m);
[482]1876}
1877
1878
[503]1879void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
1880{
[551]1881        //TODO
[503]1882}
[442]1883
[503]1884/**************************************************************************/
1885/*                   VspBspViewCellsManager implementation                */
1886/**************************************************************************/
[482]1887
[503]1888
1889VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree,
[442]1890                                                                                           int constructionSamples):
[503]1891ViewCellsManager(constructionSamples),
[442]1892mVspBspTree(vspBspTree)
1893{
[478]1894        mVspBspTree->SetViewCellsManager(this);
[442]1895}
1896
[477]1897
[475]1898VspBspViewCellsManager::~VspBspViewCellsManager()
1899{
1900}
1901
[477]1902
[471]1903float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]1904{
[551]1905        if (0 && mVspBspTree->mUseAreaForPvs)
[547]1906                return GetArea(viewCell) / GetAccVcArea();
1907        else
1908                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]1909}
1910
[477]1911
[480]1912void VspBspViewCellsManager::CollectViewCells()
1913{
[564]1914        mVspBspTree->CollectViewCells(mViewCells, mOnlyValidViewCells);
[480]1915}
1916
1917
[503]1918float VspBspViewCellsManager::GetRendercost(ViewCell *viewCell,
[477]1919                                                                                        float objRendercost) const
[468]1920{
1921        return viewCell->GetPvs().GetSize() * objRendercost;
1922}
1923
[462]1924
[442]1925bool VspBspViewCellsManager::ViewCellsConstructed() const
1926{
1927        return mVspBspTree->GetRoot() != NULL;
1928}
1929
[462]1930
[442]1931ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1932{
1933        return new BspViewCell(mesh);
1934}
1935
[569]1936
1937
[503]1938int VspBspViewCellsManager::Construct(const ObjectContainer &objects,
[487]1939                                                                          const VssRayContainer &rays)
[442]1940{
[503]1941        // if view cells were already constructed
1942        if (ViewCellsConstructed())
1943                return 0;
[442]1944
[503]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
[469]1953        VssRayContainer constructionRays;
1954        VssRayContainer savedRays;
[442]1955
[557]1956        Debug << "construction samples: " << mConstructionSamples << " rays: " << (int)rays.size() << endl;
[485]1957        GetRaySets(rays, mConstructionSamples, constructionRays, &savedRays);
[487]1958
[508]1959        Debug << "construction rays: " << (int)constructionRays.size() << endl;
1960        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]1961
[547]1962        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
[564]1963
[542]1964        mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[503]1965
[480]1966        Debug << mVspBspTree->GetStatistics() << endl;
[491]1967
[490]1968        // collapse invalid regions
[491]1969        cout << "collapsing invalid tree regions ... ";
[495]1970        long startTime = GetTime();
[503]1971        int collapsedLeaves = mVspBspTree->CollapseTree();
[501]1972        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3 << " seconds" << endl;
[495]1973    cout << "finished" << endl;
[503]1974
[491]1975        cout << "reseting view cell stats ... ";
[480]1976        ResetViewCells();
[491]1977        cout << "finished" << endl;
[503]1978
[480]1979        Debug << "\nView cells after construction:\n" << mViewCellsStats << endl;
[491]1980
1981        if (1) // export initial view cells
1982        {
1983                cout << "exporting initial view cells (=leaves) ... ";
1984                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
[503]1985
[491]1986                if (exporter)
1987                {
1988                        //exporter->SetWireframe();
1989                        exporter->SetFilled();
[508]1990                        ExportViewCellsForViz(exporter);
[491]1991
[495]1992                        if (0 && mExportRays)
1993                                exporter->ExportRays(rays, RgbColor(1, 1, 1));
[503]1994
[491]1995                        if (mExportGeometry)
1996                                exporter->ExportGeometry(objects);
[503]1997
[491]1998                        delete exporter;
1999                }
2000                cout << "finished" << endl;
2001        }
2002
[495]2003        startTime = GetTime();
[503]2004
2005        // reset view cells and stats
2006        ResetViewCells();
2007
[491]2008        cout << "Computing remaining ray contributions ... ";
[469]2009        // recast rest of rays
2010        ComputeSampleContributions(savedRays);
[491]2011        cout << "finished" << endl;
2012
[503]2013        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]2014                  << " secs" << endl;
[442]2015
[485]2016        cout << "construction finished" << endl;
[503]2017
[442]2018        return sampleContributions;
2019}
2020
[489]2021
[503]2022void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
2023                                                                                        const ObjectContainer &objects)
[475]2024{
[442]2025        //-- post processing of bsp view cells
2026    int vcSize = 0;
2027        int pvsSize = 0;
2028
[480]2029        mRenderer->RenderScene();
2030        SimulationStatistics ss;
2031        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2032    Debug << ss << endl;
2033
[442]2034        //-- merge or subdivide view cells
2035        int merged = 0;
[503]2036
[561]2037        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
[485]2038        long startTime = GetTime();
[442]2039
[503]2040        // TODO: should be done BEFORE the ray casting
[547]2041        merged = mVspBspTree->MergeViewCells(rays, objects);
[442]2042
[485]2043        //-- stats and visualizations
[561]2044        cout << "finished merging" << endl;
[485]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;
[503]2050
[491]2051        cout << "reseting view cell stats ... ";
[485]2052        ResetViewCells();
[491]2053        cout << "finished" << endl;
2054
[485]2055        //BspLeaf::NewMail();
2056        if (1) // export merged view cells
[483]2057        {
[485]2058                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
2059                Debug << "\nView cells after merge:\n" << mViewCellsStats << endl;
[483]2060
[485]2061                cout << "exporting view cells after merge ... ";
2062
2063                if (exporter)
[483]2064                {
[564]2065                        if (0)
[551]2066                                exporter->SetWireframe();
2067                        else
2068                                exporter->SetFilled();
[508]2069                        ExportViewCellsForViz(exporter);
[442]2070
[485]2071                        if (mExportGeometry)
[483]2072                        {
[485]2073                                Material m;
2074                                m.mDiffuseColor = RgbColor(0, 1, 0);
2075                                exporter->SetForcedMaterial(m);
2076                                exporter->SetFilled();
[442]2077
[485]2078                                exporter->ExportGeometry(objects);
[442]2079                        }
[485]2080
2081                        delete exporter;
[442]2082                }
[485]2083                cout << "finished" << endl;
[442]2084        }
[503]2085}
[475]2086
[503]2087
[564]2088void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
2089                                                                                         const ObjectContainer &objects)
[503]2090{
[485]2091        Debug << "render time before refine:" << endl;
2092        mRenderer->RenderScene();
[503]2093        SimulationStatistics ss;
[485]2094        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
2095    Debug << ss << endl;
2096
[489]2097        cout << "Refining the merged view cells ... ";
[503]2098        long startTime = GetTime();
[485]2099
2100        // refining the merged view cells
[564]2101        const int refined = mVspBspTree->RefineViewCells(rays, objects);
[485]2102
[442]2103        //-- stats and visualizations
2104        cout << "finished" << endl;
[485]2105        cout << "refined " << refined << " view cells in "
[442]2106                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
2107
[485]2108        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]2109                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]2110}
[495]2111
[517]2112
[503]2113int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
2114                                                                                const VssRayContainer &rays)
2115{
2116        if (!ViewCellsConstructed())
2117        {
[517]2118                Debug << "postprocess error: no view cells constructed" << endl;
[503]2119                return 0;
2120        }
[520]2121
[564]2122
[542]2123        // view cells already finished before post processing step (i.e. because they were loaded)
[520]2124        if (mViewCellsFinished)
[542]2125        {
[551]2126                FinalizeViewCells(true);
[542]2127                EvaluateViewCellsStats();
[517]2128                return 0;
[542]2129        }
[448]2130
[564]2131
[542]2132        // check if new view cells turned invalid
[544]2133        mVspBspTree->ValidateTree();
[542]2134        ResetViewCells();
2135
2136
[517]2137        VssRayContainer postProcessRays;
2138        GetRaySets(rays, mPostProcessSamples, postProcessRays);
2139
2140        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]2141
[517]2142        Debug << "\nview cell partition after sampling:\n" << mViewCellsStats << endl << endl;
2143
[552]2144        // should maybe be done here to allow merge working with area or volume
2145        // and to correct the rendering statistics
[554]2146        if (0)
[551]2147        {
2148                FinalizeViewCells(false);
2149        }
2150
2151        //-- merge the individual view cells
[517]2152        MergeViewCells(postProcessRays, objects);
2153        //-- refines the merged view cells
[564]2154        RefineViewCells(postProcessRays, objects);
[568]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
[517]2216        // collapse sibling leaves that share the same view cell
2217        mVspBspTree->CollapseTree();
2218
[520]2219        ResetViewCells();
2220
[508]2221        // real meshes are only contructed only at this stage
[551]2222        FinalizeViewCells(true);
[517]2223
[508]2224        // write view cells to disc
2225        if (mExportViewCells)
2226        {
[517]2227                char buff[100];
2228                environment->GetStringValue("ViewCells.filename", buff);
2229                string vcFilename(buff);
2230
2231                ExportViewCells(buff);
[508]2232        }
[503]2233
2234        return 0;
[442]2235}
2236
[490]2237
[442]2238int VspBspViewCellsManager::GetType() const
2239{
2240        return VSP_BSP;
2241}
2242
2243
[490]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        {
[542]2254                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]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{
[569]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);
[490]2273}
2274
2275
[442]2276void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2277                                                                           const VssRayContainer &sampleRays)
[442]2278{
2279        if (!ViewCellsConstructed())
2280                return;
2281
[485]2282        VssRayContainer visRays;
2283        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]2284
[442]2285        if (1) // export view cells
2286        {
[478]2287                cout << "exporting view cells after post process ... ";
[485]2288                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[442]2289
2290                if (exporter)
2291                {
[542]2292                        if (1)
2293                        {
2294                                exporter->SetWireframe();
2295                                exporter->ExportBox(mViewSpaceBox);
2296                                exporter->SetFilled();
2297                        }
2298
[485]2299                        if (mExportGeometry)
[542]2300                        {
[485]2301                                exporter->ExportGeometry(objects);
[542]2302                        }
[489]2303
2304                        // export rays
[490]2305                        if (mExportRays)
[489]2306                        {
[490]2307                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
2308                        }
[564]2309
[508]2310                        ExportViewCellsForViz(exporter);
[442]2311                        delete exporter;
2312                }
[557]2313        }
[503]2314
[442]2315        //-- visualization of the BSP splits
2316        bool exportSplits = false;
[489]2317        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]2318
[442]2319        if (exportSplits)
2320        {
2321                cout << "exporting splits ... ";
[485]2322                ExportSplits(objects, visRays);
[442]2323                cout << "finished" << endl;
2324        }
2325
[542]2326        //-- export single view cells
[485]2327        ExportBspPvs(objects, visRays);
[442]2328}
2329
[503]2330
[485]2331void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
2332                                                                                  const VssRayContainer &rays)
[442]2333{
2334        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
2335
[503]2336        if (exporter)
2337        {
2338                Material m;
[442]2339                m.mDiffuseColor = RgbColor(1, 0, 0);
2340                exporter->SetForcedMaterial(m);
2341                exporter->SetWireframe();
[503]2342
[448]2343                exporter->ExportBspSplits(*mVspBspTree, true);
[442]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();
[503]2351
[442]2352                // export rays
[485]2353                if (mExportRays)
2354                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]2355
[485]2356                if (mExportGeometry)
[442]2357                        exporter->ExportGeometry(objects);
2358
2359                delete exporter;
2360        }
2361}
2362
[503]2363
[485]2364void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
2365                                                                                  const VssRayContainer &rays)
[442]2366{
2367        const int leafOut = 10;
[503]2368
[442]2369        ViewCell::NewMail();
[503]2370
[442]2371        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
[475]2372        Debug << "\nOutput view cells: " << endl;
[503]2373
[485]2374        // sort view cells to visualize the largest view cells
[478]2375#if 0
2376        stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
2377#endif
[503]2378        int limit = min(leafOut, (int)mViewCells.size());
[483]2379
[485]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
[478]2388        for (int i = 0; i < limit; ++ i)
[442]2389        {
[478]2390                cout << "creating output for view cell " << i << " ... ";
[503]2391
[478]2392                VssRayContainer vcRays;
[485]2393                Intersectable::NewMail();
[542]2394#if 0 // largest view cell pvs first
[478]2395                BspViewCell *vc = dynamic_cast<BspViewCell *>(mViewCells[i]);
2396#else
[485]2397                BspViewCell *vc = dynamic_cast<BspViewCell *>
2398                        (mViewCells[Random((int)mViewCells.size())]);
[478]2399#endif
[442]2400
[483]2401#if 1
[478]2402                // check whether we can add the current ray to the output rays
[503]2403                for (int k = 0; k < raysOut; ++ k)
[442]2404                {
[485]2405                        BspRay *ray = bspRays[k];
[478]2406                        for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
[442]2407                        {
[478]2408                                BspLeaf *leaf = ray->intersections[j].mLeaf;
[503]2409                                if (vc == leaf->GetViewCell())
[478]2410                                        vcRays.push_back(ray->vssRay);
[442]2411                        }
2412                }
[478]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();
[442]2418
[478]2419                Material m;//= RandomMaterial();
2420                m.mDiffuseColor = RgbColor(0, 1, 0);
2421                exporter->SetForcedMaterial(m);
[442]2422
[503]2423                ExportVcGeometry(exporter, vc);
2424
2425
2426                Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
[485]2427                          << ", piercing rays=" << (int)vcRays.size()
2428                          << ", leaves=" << (int)vc->mLeaves.size() << endl;
[503]2429
[485]2430                //-- export rays piercing this view cell
[483]2431#if 1
[495]2432                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[483]2433#endif
[478]2434#if 0
2435                vector<BspLeaf *>::const_iterator lit, lit_end = vc->mLeaves.end();
[483]2436
[478]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);
[442]2442
[478]2443                ObjectPvsMap::const_iterator it,
2444                        it_end = vc->GetPvs().mEntries.end();
[442]2445
[478]2446                exporter->SetFilled();
[442]2447
[478]2448                // output PVS of view cell
[503]2449                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]2450                {
2451                        Intersectable *intersect = (*it).first;
[442]2452
[478]2453                        if (!intersect->Mailed())
2454                        {
2455                                Material m = RandomMaterial();
2456                                exporter->SetForcedMaterial(m);
2457
2458                                exporter->ExportIntersectable(intersect);
2459                                intersect->Mail();
[503]2460                        }
[442]2461                }
[503]2462
[478]2463                DEL_PTR(exporter);
2464                cout << "finished" << endl;
[442]2465        }
[475]2466
[485]2467#if 1
2468        CLEAR_CONTAINER(bspRays);
2469#endif
[475]2470        Debug << endl;
[442]2471}
2472
2473
[469]2474int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
2475                                                                                        const Vector3 &termination,
2476                                                                                        ViewCellContainer &viewcells)
[466]2477{
[469]2478        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]2479}
[482]2480
2481
[503]2482void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]2483                                                                                 ViewCell *vc) const
2484{
[564]2485        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[503]2486
[482]2487        float importance = 0;
[564]2488        static Material m;
2489
[482]2490        switch (mColorCode)
2491        {
[564]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;
[482]2506        case 1: // pvs
2507                {
[503]2508                        importance = (float)vc->GetPvs().GetSize() /
[482]2509                                (float)mViewCellsStats.maxPvs;
2510                }
2511                break;
2512        case 2: // merges
2513                {
2514            BspViewCell *bspVc = dynamic_cast<BspViewCell *>(vc);
2515
[503]2516                        importance = (float)bspVc->mLeaves.size() /
[482]2517                                (float)mViewCellsStats.maxLeaves;
2518                }
2519                break;
2520        case 3: // merge tree differene
2521                {
[503]2522                        importance = (float)GetMaxTreeDiff(vc) /
[482]2523                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]2524
[482]2525                }
2526                break;
2527        default:
2528                break;
2529        }
2530
[564]2531        // special color code for invalid view cells
[482]2532        m.mDiffuseColor.r = importance;
2533        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[564]2534        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[547]2535
[482]2536        //Debug << "importance: " << importance << endl;
2537        exporter->SetForcedMaterial(m);
2538}
2539
2540
[503]2541void VspBspViewCellsManager::ExportVcGeometry(Exporter *exporter,
[485]2542                                                                                          ViewCell *vc) const
[482]2543{
[542]2544        if (vc->GetMesh())
[503]2545        {
2546                exporter->ExportMesh(vc->GetMesh());
2547                return;
2548        }
2549
[485]2550        BspNodeGeometry geom;
2551        mVspBspTree->
[503]2552                ConstructGeometry(dynamic_cast<BspViewCell *>(vc), geom);
[485]2553        exporter->ExportPolygons(geom.mPolys);
[482]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        }
[492]2576        return maxDist;
2577}
[482]2578
[492]2579
[569]2580ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
[492]2581{
[508]2582        if (!mVspBspTree)
2583                return NULL;
2584        return mVspBspTree->GetViewCell(point);
[492]2585}
[503]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}
[508]2599
2600
2601bool VspBspViewCellsManager::LoadViewCells(const string filename, ObjectContainer *objects)
2602{
2603        ViewCellsParser parser;
[564]2604
[508]2605        DEL_PTR(mVspBspTree);
2606        mVspBspTree = new VspBspTree();
[564]2607
[508]2608        bool success = parser.ParseFile(filename, mVspBspTree, this, objects);
[520]2609        mVspBspTree->RepairViewCellsLeafLists();
2610        mVspBspTree->mBox = GetViewSpaceBox();
[508]2611        ResetViewCells();
[564]2612
[555]2613        mViewCellsFinished = true;
[562]2614        mMaxPvsSize = (int)objects->size();
[517]2615
[555]2616        FinalizeViewCells(true);
[564]2617
[508]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{
[564]2632        cout << "exporting view cells to xml ... ";
[508]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;
[564]2641
[508]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);
[564]2647
[508]2648        stream << "</ViewCells>" << endl;
[564]2649
[508]2650        //-- load the hierarchy
2651        stream << "<BspTree>" << endl;
2652        mVspBspTree->Export(stream);
2653        stream << endl << "</BspTree>" << endl;
[564]2654
[508]2655        stream << "</Visibility_Solution>" << endl;
2656        stream.close();
2657
2658        cout << "finished" << endl;
2659
2660        return true;
[532]2661}
2662
2663
2664int VspBspViewCellsManager::CastBeam(Beam &beam)
2665{
[535]2666        return mVspBspTree->CastBeam(beam);
[532]2667}
[551]2668
2669
[555]2670void VspBspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
[551]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);
[563]2692}
Note: See TracBrowser for help on using the repository browser.