source: trunk/VUT/GtpVisibilityPreprocessor/src/RssPreprocessor.cpp @ 464

Revision 464, 17.1 KB checked in by bittner, 19 years ago (diff)
Line 
1#include "SceneGraph.h"
2#include "KdTree.h"
3#include "RssPreprocessor.h"
4#include "X3dExporter.h"
5#include "Environment.h"
6#include "MutualVisibility.h"
7#include "Polygon3.h"
8#include "ViewCell.h"
9#include "VssRay.h"
10#include "RssTree.h"
11#include "ViewCellsManager.h"
12#include "RenderSimulator.h"
13
14static bool useViewSpaceBox = true;
15static bool use2dSampling = false;
16static bool fromBoxVisibility = false;
17
18
19RssPreprocessor::RssPreprocessor():
20  mPass(0),
21  mVssRays()
22{
23  // this should increase coherence of the samples
24  environment->GetIntValue("RssPreprocessor.samplesPerPass", mSamplesPerPass);
25  environment->GetIntValue("RssPreprocessor.initialSamples", mInitialSamples);
26  environment->GetIntValue("RssPreprocessor.vssSamples", mRssSamples);
27  environment->GetIntValue("RssPreprocessor.vssSamplesPerPass", mRssSamplesPerPass);
28  environment->GetBoolValue("RssPreprocessor.useImportanceSampling", mUseImportanceSampling);
29  environment->GetIntValue("BspTree.Construction.samples", mBspConstructionSamples);
30
31  environment->GetBoolValue("RssPreprocessor.Export.pvs", mExportPvs);
32  environment->GetBoolValue("RssPreprocessor.Export.rssTree", mExportRssTree);
33  environment->GetBoolValue("RssPreprocessor.Export.rays", mExportRays);
34  environment->GetIntValue("RssPreprocessor.Export.numRays", mExportNumRays);
35  environment->GetBoolValue("RssPreprocessor.useViewcells", mUseViewcells);
36
37  environment->GetBoolValue("RssPreprocessor.updateSubdivision", mUpdateSubdivision);
38 
39  mStats.open("stats.log");
40}
41
42RssPreprocessor::~RssPreprocessor()
43{
44  CLEAR_CONTAINER(mVssRays);
45}
46
47void
48RssPreprocessor::SetupRay(Ray &ray,
49                                                  const Vector3 &point,
50                                                  const Vector3 &direction
51                                                  )
52{
53  ray.intersections.clear();
54  // do not store anything else then intersections at the ray
55  ray.Init(point, direction, Ray::LOCAL_RAY);
56}
57
58int
59RssPreprocessor::CastRay(
60                                                 Vector3 &viewPoint,
61                                                 Vector3 &direction,
62                                                 VssRayContainer &vssRays
63                                                 )
64{
65  int hits = 0;
66  static Ray ray;
67  AxisAlignedBox3 box = mKdTree->GetBox();
68
69  AxisAlignedBox3 sbox = box;
70  sbox.Enlarge(Vector3(-Limits::Small));
71  if (!sbox.IsInside(viewPoint))
72        return 0;
73       
74  SetupRay(ray, viewPoint, direction);
75  // cast ray to KD tree to find intersection with other objects
76  Intersectable *objectA, *objectB;
77  Vector3 pointA, pointB;
78  float bsize = Magnitude(box.Size());
79 
80  if (mKdTree->CastRay(ray)) {
81        objectA = ray.intersections[0].mObject;
82        pointA = ray.Extrap(ray.intersections[0].mT);
83  } else {
84        objectA = NULL;
85        // compute intersection with the scene bounding box
86        float tmin, tmax;
87        box.ComputeMinMaxT(ray, &tmin, &tmax);
88        if (tmax > bsize) {
89          //cerr<<"Warning: tmax > box size tmax="<<tmax<<" tmin="<<tmin<<" size="<<bsize<<endl;
90          //cerr<<"ray"<<ray<<endl;
91        }
92        pointA = ray.Extrap(tmax);
93  }
94
95  bool detectEmptyViewSpace = true;
96       
97  if (detectEmptyViewSpace) {
98        SetupRay(ray, pointA, -direction);
99  } else
100        SetupRay(ray, viewPoint, -direction);
101       
102       
103  if (mKdTree->CastRay(ray)) {
104        objectB = ray.intersections[0].mObject;
105        pointB = ray.Extrap(ray.intersections[0].mT);
106  } else {
107        objectB = NULL;
108        float tmin, tmax;
109        box.ComputeMinMaxT(ray, &tmin, &tmax);
110        if (tmax > bsize) {
111          //cerr<<"Warning: tmax > box size tmax="<<tmax<<" tmin="<<tmin<<" size="<<bsize<<endl;
112          //cerr<<"ray"<<ray<<endl;
113        }
114        pointB = ray.Extrap(tmax);
115  }
116
117  VssRay *vssRay  = NULL;
118
119  bool validSample = true;
120  if (detectEmptyViewSpace) {
121        // check if the viewpoint lies on the line segment AB
122        if (Distance(pointA, pointB) <
123                Distance(viewPoint, pointA) + Distance(viewPoint, pointB) - Limits::Small) {
124          validSample = false;
125        }
126  }
127       
128  if (validSample) {
129        if (objectA) {
130          vssRay = new VssRay(pointB,
131                                                  pointA,
132                                                  objectB,
133                                                  objectA,
134                                                  mPass
135                                                  );
136          vssRays.push_back(vssRay);
137          hits ++;
138        }
139       
140        if (objectB) {
141          vssRay = new VssRay(pointA,
142                                                  pointB,
143                                                  objectA,
144                                                  objectB,
145                                                  mPass
146                                                  );
147          vssRays.push_back(vssRay);
148          hits ++;
149        }
150  }
151       
152  return hits;
153}
154
155
156Vector3
157RssPreprocessor::GetViewpoint(AxisAlignedBox3 *viewSpaceBox)
158{
159  AxisAlignedBox3 box;
160       
161  if (viewSpaceBox)
162        box =*viewSpaceBox;
163  else
164        box = mKdTree->GetBox();
165       
166  // shrink the box in the y direction
167  return box.GetRandomPoint();
168}
169
170Vector3
171RssPreprocessor::GetDirection(const Vector3 &viewpoint,
172                                                          AxisAlignedBox3 *viewSpaceBox
173                                                          )
174{
175  Vector3 point;
176  if (!use2dSampling) {
177        Vector3 normal;
178        int i = RandomValue(0, mObjects.size()-1);
179        Intersectable *object = mObjects[i];
180        object->GetRandomSurfacePoint(point, normal);
181  } else {
182        AxisAlignedBox3 box;
183               
184        if (viewSpaceBox)
185          box =*viewSpaceBox;
186        else
187          box = mKdTree->GetBox();
188               
189        point = box.GetRandomPoint();
190        point.y = viewpoint.y;
191  }
192       
193  return point - viewpoint;
194}
195
196int
197RssPreprocessor::GenerateImportanceRays(RssTree *rssTree,
198                                                                                const int desiredSamples,
199                                                                                SimpleRayContainer &rays
200                                                                                )
201{
202  int num;
203
204
205 
206  float avgPvsSize;
207  float avgRayContribution;
208  float avgPvsEntropy;
209  float avgRayLengthEntropy;
210  float avgImportance;
211  float avgRays;
212  rssTree->GetTreeStatistics(
213                                                         avgPvsSize,
214                                                         avgRays,
215                                                         avgRayContribution,
216                                                         avgPvsEntropy,
217                                                         avgRayLengthEntropy,
218                                                         avgImportance);
219 
220  cout<<
221        "#AVG_PVS_SIZE\n"<<avgPvsSize<<endl<<
222        "#AVG_RAYS\n"<<avgRays<<endl<<
223        "#AVG_RAY_CONTRIB\n"<<avgRayContribution<<endl<<
224        "#AVG_PVS_ENTROPY\n"<<avgPvsEntropy<<endl<<
225        "#AVG_RAY_LENGTH_ENTROPY\n"<<avgRayLengthEntropy<<endl<<
226        "#AVG_IMPORTANCE\n"<<avgImportance<<endl;
227 
228  if (0) {
229        float p = desiredSamples/(float)(avgRayContribution*rssTree->stat.Leaves());
230        num = rssTree->GenerateRays(p, rays);
231  } else {
232        int leaves = rssTree->stat.Leaves()/1;
233        num = rssTree->GenerateRays(desiredSamples, leaves, rays);
234  }
235       
236  cout<<"Generated "<<num<<" rays."<<endl;
237       
238  return num;
239}
240
241
242bool
243RssPreprocessor::ExportRays(const char *filename,
244                                                        const VssRayContainer &vssRays,
245                                                        const int number
246                                                        )
247{
248  cout<<"Exporting vss rays..."<<endl<<flush;
249       
250  float prob = number/(float)vssRays.size();
251
252
253  Exporter *exporter = NULL;
254  exporter = Exporter::GetExporter(filename);
255  //    exporter->SetWireframe();
256  //    exporter->ExportKdTree(*mKdTree);
257  exporter->SetFilled();
258  exporter->ExportScene(mSceneGraph->mRoot);
259  exporter->SetWireframe();
260
261  if (mViewSpaceBox) {
262        exporter->SetForcedMaterial(RgbColor(1,0,1));
263        exporter->ExportBox(*mViewSpaceBox);
264        exporter->ResetForcedMaterial();
265  }
266       
267  VssRayContainer rays; for (int i=0; i < vssRays.size(); i++)
268        if (RandomValue(0,1) < prob)
269          rays.push_back(vssRays[i]);
270
271  exporter->ExportRays(rays, RgbColor(1, 0, 0));
272       
273  delete exporter;
274
275  cout<<"done."<<endl<<flush;
276
277  return true;
278}
279
280
281bool
282RssPreprocessor::ExportRssTree(char *filename,
283                                                           RssTree *tree,
284                                                           const Vector3 &dir
285                                                           )
286{
287  Exporter *exporter = Exporter::GetExporter(filename);
288  exporter->SetFilled();
289  exporter->ExportScene(mSceneGraph->mRoot);
290  //  exporter->SetWireframe();
291  bool result = exporter->ExportRssTree2( *tree, dir );
292  delete exporter;
293  return result;
294}
295
296bool
297RssPreprocessor::ExportRssTreeLeaf(char *filename,
298                                                                   RssTree *tree,
299                                                                   RssTreeLeaf *leaf)
300{
301  Exporter *exporter = NULL;
302  exporter = Exporter::GetExporter(filename);
303  exporter->SetWireframe();
304  exporter->ExportKdTree(*mKdTree);
305       
306  if (mViewSpaceBox) {
307        exporter->SetForcedMaterial(RgbColor(1,0,0));
308        exporter->ExportBox(*mViewSpaceBox);
309        exporter->ResetForcedMaterial();
310  }
311       
312  exporter->SetForcedMaterial(RgbColor(0,0,1));
313  exporter->ExportBox(tree->GetBBox(leaf));
314  exporter->ResetForcedMaterial();
315       
316  VssRayContainer rays[4];
317  for (int i=0; i < leaf->rays.size(); i++) {
318        int k = leaf->rays[i].GetRayClass();
319        rays[k].push_back(leaf->rays[i].mRay);
320  }
321       
322  // SOURCE RAY
323  exporter->ExportRays(rays[0], RgbColor(1, 0, 0));
324  // TERMINATION RAY
325  exporter->ExportRays(rays[1], RgbColor(1, 1, 1));
326  // PASSING_RAY
327  exporter->ExportRays(rays[2], RgbColor(1, 1, 0));
328  // CONTAINED_RAY
329  exporter->ExportRays(rays[3], RgbColor(0, 0, 1));
330
331  delete exporter;
332  return true;
333}
334
335void
336RssPreprocessor::ExportRssTreeLeaves(RssTree *tree, const int number)
337{
338  vector<RssTreeLeaf *> leaves;
339  tree->CollectLeaves(leaves);
340
341  int num = 0;
342  int i;
343  float p = number / (float)leaves.size();
344  for (i=0; i < leaves.size(); i++) {
345        if (RandomValue(0,1) < p) {
346          char filename[64];
347          sprintf(filename, "rss-leaf-%04d.x3d", num);
348          ExportRssTreeLeaf(filename, tree, leaves[i]);
349          num++;
350        }
351        if (num >= number)
352          break;
353  }
354}
355
356
357float
358RssPreprocessor::GetAvgPvsSize(RssTree *tree,
359                                                           const vector<AxisAlignedBox3> &viewcells
360                                                           )
361{
362  vector<AxisAlignedBox3>::const_iterator it, it_end = viewcells.end();
363
364  int sum = 0;
365  for (it = viewcells.begin(); it != it_end; ++ it)
366        sum += tree->GetPvsSize(*it);
367       
368  return sum/(float)viewcells.size();
369}
370
371
372void
373RssPreprocessor::ExportPvs(char *filename,
374                                                   RssTree *rssTree
375                                                   )
376{
377  ObjectContainer pvs;
378  if (rssTree->CollectRootPvs(pvs)) {
379        Exporter *exporter = Exporter::GetExporter(filename);
380        exporter->SetFilled();
381        exporter->ExportGeometry(pvs);
382        exporter->SetWireframe();
383        exporter->ExportBox(rssTree->bbox);
384        exporter->ExportViewpoint(rssTree->bbox.Center(), Vector3(1,0,0));
385        delete exporter;
386  }
387}
388
389bool
390RssPreprocessor::ComputeVisibility()
391{
392  cout<<"Rss Preprocessor started\n"<<flush;
393  cout<<"Memory/ray "<<sizeof(VssRay)+sizeof(RssTreeNode::RayInfo)<<endl;
394  mSceneGraph->CollectObjects(&mObjects);
395       
396  long startTime = GetTime();
397 
398  int totalSamples = 0;
399
400  /// Rays used for post processing and visualizations.
401  RayContainer storedRays;
402
403  AxisAlignedBox3 *box = new AxisAlignedBox3(mKdTree->GetBox());
404
405  if (fromBoxVisibility) {
406        float m = box->Min(1);
407        float bsize = box->Size(1);
408
409        float size = 0.02f;
410        float s = 0.5f - size;
411        float olds = Magnitude(box->Size());
412        box->Enlarge(box->Size()*Vector3(-s));
413        //      Vector3 translation = Vector3(-olds*0.2f, 0, 0);
414        Vector3 translation = Vector3(-0.05*olds, 0, 0);
415        box->SetMin(box->Min() + translation);
416        box->SetMax(box->Max() + translation);
417
418        box->SetMin(1,  m + bsize*0.1);
419        box->SetMax(1,  m + bsize*0.6);
420
421       
422  } else {
423               
424        // sample city like heights
425        float m = box->Min(1);
426        float bsize = box->Size(1);
427        box->SetMin(1,  m + bsize*0.2);
428        box->SetMax(1,  m + bsize*0.3);
429  }
430
431  if (use2dSampling)
432        box->SetMax(1, box->Min(1));
433       
434  if (useViewSpaceBox)
435        mViewSpaceBox = box;
436  else
437        mViewSpaceBox = NULL;
438               
439
440  RssTree *rssTree = NULL;
441
442  while (totalSamples < mInitialSamples) {
443        int passContributingSamples = 0;
444        int passSampleContributions = 0;
445        int passSamples = 0;
446        int index = 0;
447               
448        int sampleContributions;
449               
450        int s = Min(mSamplesPerPass, mInitialSamples);
451        for (int k=0; k < s; k++) {
452                       
453          Vector3 viewpoint = GetViewpoint(mViewSpaceBox);
454          Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
455                       
456          sampleContributions = CastRay(viewpoint, direction, mVssRays);
457                       
458                       
459          //-- CORR matt: put block inside loop
460          if (sampleContributions) {
461                passContributingSamples ++;
462                passSampleContributions += sampleContributions;
463          }
464          passSamples++;
465          totalSamples++;
466        }
467   
468        mPass++;
469               
470        int pvsSize = 0;
471        float avgRayContrib = (passContributingSamples > 0) ?
472          passSampleContributions/(float)passContributingSamples : 0;
473               
474        cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
475        cout << "#TotalSamples=" << totalSamples/1000
476                 << "k   #SampleContributions=" << passSampleContributions << " ("
477                 << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
478                 << pvsSize/(float)mObjects.size() << endl
479                 << "avg ray contrib=" << avgRayContrib << endl;
480               
481        mStats <<
482          "#Pass\n" <<mPass<<endl<<
483          "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
484          "#TotalSamples\n" << totalSamples<< endl<<
485          "#SampleContributions\n" << passSampleContributions << endl <<
486          "#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
487          "#AvgPVS\n"<< pvsSize/(float)mObjects.size() << endl <<
488          "#AvgRayContrib\n" << avgRayContrib << endl;
489  }
490 
491  cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
492  cout << "#totalRayStackSize=" << mVssRays.size() << endl <<flush;
493 
494
495  if (mExportRays) {
496        char filename[64];
497        sprintf(filename, "rss-rays-initial.x3d");
498        ExportRays(filename, mVssRays, mExportNumRays);
499  }
500 
501  if (mUseViewcells)
502        // construct view cells
503        mViewCellsManager->Construct(mObjects, mVssRays, mViewSpaceBox);
504
505  rssTree = new RssTree;
506       
507  if (fromBoxVisibility)
508        rssTree->Construct(mVssRays, mViewSpaceBox);
509  else
510        rssTree->Construct(mVssRays, NULL);
511
512  cout<<"RssTree root PVS size = "<<rssTree->GetRootPvsSize()<<endl;
513
514  if (mExportRssTree) {
515        ExportRssTree("rss-tree-100.x3d", rssTree, Vector3(1,0,0));
516        ExportRssTree("rss-tree-001.x3d", rssTree, Vector3(0,0,1));
517        ExportRssTree("rss-tree-101.x3d", rssTree, Vector3(1,0,1));
518        ExportRssTree("rss-tree-101m.x3d", rssTree, Vector3(-1,0,-1));
519        ExportRssTreeLeaves(rssTree, 10);
520  }
521
522  if (mExportPvs) {
523        ExportPvs("rss-pvs-initial.x3d", rssTree);
524  }
525
526  // viewcells->UpdatePVS(newVssRays);
527  // get viewcells as kd tree boxes
528  vector<AxisAlignedBox3> kdViewcells;
529
530  if (0) {
531        vector<KdLeaf *> leaves;
532        mKdTree->CollectLeaves(leaves);
533        vector<KdLeaf *>::const_iterator it;
534        int targetLeaves = 50;
535        float prob = targetLeaves/(float)leaves.size();
536        for (it = leaves.begin(); it != leaves.end(); ++it)
537          if (RandomValue(0.0f,1.0f) < prob)
538                kdViewcells.push_back(mKdTree->GetBox(*it));
539               
540        float avgPvs = GetAvgPvsSize(rssTree, kdViewcells);
541        cout<<"Initial average PVS size = "<<avgPvs<<endl;
542  }
543
544       
545  int samples = 0;
546  int pass = 0;
547  while (1) {
548        int num = mRssSamplesPerPass;
549        SimpleRayContainer rays;
550        VssRayContainer vssRays;
551               
552        if (!mUseImportanceSampling) {
553          for (int j=0; j < num; j++) {
554                Vector3 viewpoint = GetViewpoint(mViewSpaceBox);
555                Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
556                rays.push_back(SimpleRay(viewpoint, direction));
557          }
558        } else {
559          num = GenerateImportanceRays(rssTree, num, rays);
560        }
561               
562               
563        for (int i=0; i < rays.size(); i++)
564          CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays);
565               
566        rssTree->AddRays(vssRays);
567               
568        if (mUpdateSubdivision) {
569          int subdivided = rssTree->UpdateSubdivision();
570          cout<<"subdivided leafs = "<<subdivided<<endl;
571          cout<<"#total leaves = "<<rssTree->stat.Leaves()<<endl;
572
573        }
574
575        if (mUseViewcells) {
576          float avgPvs = GetAvgPvsSize(rssTree, kdViewcells);
577          cout<<"Average PVS size = "<<avgPvs<<endl;
578        }
579
580        if (mExportRays) {
581          char filename[64];
582          if (mUseImportanceSampling)
583                sprintf(filename, "rss-rays-i%04d.x3d", pass);
584          else
585                sprintf(filename, "rss-rays-%04d.x3d", pass);
586         
587          ExportRays(filename, vssRays, mExportNumRays);
588        }
589
590        samples+=num;
591
592        if (mUseViewcells) {
593         
594          //-- prepare traversal rays for view cell intersections
595          RayContainer passRays;
596         
597          VssRayContainer::const_iterator it, it_end = vssRays.end();
598         
599          for (it = vssRays.begin(); it != it_end; ++ it)
600                passRays.push_back(new Ray(*(*it)));
601         
602          int sampleContributions = 0;
603          int contributingSamples = 0;
604         
605          /// compute view cell contribution of rays
606          mViewCellsManager->ComputeSampleContributions(passRays,
607                                                                                                        sampleContributions,
608                                                                                                        contributingSamples);
609         
610          //-- save rays for post processing
611          if (((int)storedRays.size() < mViewCellsManager->GetPostProcessSamples()) ||
612                  ((int)storedRays.size() < mViewCellsManager->GetVisualizationSamples()))
613                {
614                  RayContainer::const_iterator it, it_end = passRays.end();
615                 
616                  for (it = passRays.begin(); it != it_end; ++ it)
617                        storedRays.push_back(new Ray(*(*it)));
618                }
619          else
620                {
621                  CLEAR_CONTAINER(passRays);
622                }
623         
624          float pvs = rssTree->GetAvgPvsSize();
625          cout<<"*****************************\n";
626          cout<<samples<<" avgPVS ="<<pvs<<endl;
627          cout<<"sample contributions ="<<sampleContributions<<endl;
628          cout<<"contributing sample ="<<contributingSamples<<endl;
629          cout<<"RssTree root PVS size = "<<rssTree->GetRootPvsSize()<<endl;
630          cout<<"*****************************\n";
631        }
632       
633        if (mExportPvs) {
634          char filename[64];
635          sprintf(filename, "rss-pvs-%04d.x3d", pass);
636          ExportPvs(filename, rssTree);
637        }
638
639        if (samples >= mRssSamples)
640          break;
641
642       
643        pass++;
644  }
645 
646  if (mUseViewcells) {
647       
648        //-- post process view cells
649        mViewCellsManager->PostProcess(mObjects, storedRays);
650       
651        //-- several visualizations and statistics
652        mViewCellsManager->PrintStatistics(Debug);
653       
654        //-- render simulation after merge
655        cout << "\nevaluating render time of final view cells ... ";
656       
657        const SimulationStatistics ss = mViewCellsManager->SimulateRendering();
658       
659        cout << " finished" << endl;
660       
661        cout << ss << endl;
662        Debug << ss << endl;
663       
664        mViewCellsManager->Visualize(mObjects, storedRays);
665  }
666 
667  delete rssTree;
668 
669  return true;
670}
671
Note: See TracBrowser for help on using the repository browser.