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

Revision 473, 16.3 KB checked in by mattausch, 19 years ago (diff)

worked on new features,
removed Random Bug (took only 32000 values),
removed bug when choosing new candidates (totally wrong)
introduced new candidate plane method
implemented priority queue for vsp bsp

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 = false;
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        "#RSS_AVG_PVS_SIZE\n"<<avgPvsSize<<endl<<
222        "#RSS_AVG_RAYS\n"<<avgRays<<endl<<
223        "#RSS_AVG_RAY_CONTRIB\n"<<avgRayContribution<<endl<<
224        "#RSS_AVG_PVS_ENTROPY\n"<<avgPvsEntropy<<endl<<
225        "#RSS_AVG_RAY_LENGTH_ENTROPY\n"<<avgRayLengthEntropy<<endl<<
226        "#RSS_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  AxisAlignedBox3 *box = new AxisAlignedBox3(mKdTree->GetBox());
401
402  if (fromBoxVisibility) {
403        float m = box->Min(1);
404        float bsize = box->Size(1);
405
406        float size = 0.02f;
407        float s = 0.5f - size;
408        float olds = Magnitude(box->Size());
409        box->Enlarge(box->Size()*Vector3(-s));
410        //      Vector3 translation = Vector3(-olds*0.2f, 0, 0);
411        Vector3 translation = Vector3(-0.05f*olds, 0, 0);
412        box->SetMin(box->Min() + translation);
413        box->SetMax(box->Max() + translation);
414
415        box->SetMin(1,  m + bsize*0.1f);
416        box->SetMax(1,  m + bsize*0.6f);
417
418       
419  } else {
420               
421        // sample city like heights
422        float m = box->Min(1);
423        float bsize = box->Size(1);
424        box->SetMin(1,  m + bsize*0.2f);
425        box->SetMax(1,  m + bsize*0.3f);
426  }
427
428  if (use2dSampling)
429        box->SetMax(1, box->Min(1));
430       
431  if (useViewSpaceBox)
432        mViewSpaceBox = box;
433  else
434        mViewSpaceBox = NULL;
435               
436
437  RssTree *rssTree = NULL;
438
439  while (totalSamples < mInitialSamples) {
440        int passContributingSamples = 0;
441        int passSampleContributions = 0;
442        int passSamples = 0;
443        int index = 0;
444               
445        int sampleContributions;
446               
447        int s = Min(mSamplesPerPass, mInitialSamples);
448        for (int k=0; k < s; k++) {
449                       
450          Vector3 viewpoint = GetViewpoint(mViewSpaceBox);
451          Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
452                       
453          sampleContributions = CastRay(viewpoint, direction, mVssRays);
454                       
455                       
456          //-- CORR matt: put block inside loop
457          if (sampleContributions) {
458                passContributingSamples ++;
459                passSampleContributions += sampleContributions;
460          }
461          passSamples++;
462          totalSamples++;
463        }
464   
465               
466        float avgRayContrib = (passContributingSamples > 0) ?
467          passSampleContributions/(float)passContributingSamples : 0;
468               
469        cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
470        cout << "#TotalSamples=" << totalSamples/1000
471                 << "k   #SampleContributions=" << passSampleContributions << " ("
472                 << 100*passContributingSamples/(float)passSamples<<"%)"
473                 << "avgcontrib=" << avgRayContrib << endl;
474               
475        mStats <<
476          "#Pass\n" <<mPass<<endl<<
477          "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
478          "#TotalSamples\n" << totalSamples<< endl<<
479          "#SampleContributions\n" << passSampleContributions << endl <<
480          "#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
481          "#AvgRayContrib\n" << avgRayContrib << endl;
482       
483        mPass++;
484
485  }
486 
487  cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
488  cout << "#totalRayStackSize=" << (int)mVssRays.size() << endl <<flush;
489 
490
491  if (mExportRays) {
492        char filename[64];
493        sprintf(filename, "rss-rays-initial.x3d");
494        ExportRays(filename, mVssRays, mExportNumRays);
495  }
496 
497  if (mUseViewcells) {
498        // construct view cells
499        mViewCellsManager->Construct(mObjects, mVssRays, mViewSpaceBox);
500       
501        VssRayContainer selectedRays;
502        int desired = Max(
503                                          mViewCellsManager->GetPostProcessSamples(),
504                                          mViewCellsManager->GetVisualizationSamples());
505        float p = desired/(float)mVssRays.size();
506       
507        for (int i=0; i < mVssRays.size(); i++) {
508          if (Random(1.0f) < p)
509                selectedRays.push_back(mVssRays[i]);
510        }
511        //-- post process view cells
512        mViewCellsManager->PostProcess(mObjects, selectedRays);
513       
514        //-- several visualizations and statistics
515        mViewCellsManager->PrintStatistics(Debug);
516       
517        if (1)
518          mViewCellsManager->Visualize(mObjects, selectedRays);
519  }
520
521
522  rssTree = new RssTree;
523       
524  if (mUseImportanceSampling) {
525       
526        if (fromBoxVisibility)
527          rssTree->Construct(mVssRays, mViewSpaceBox);
528        else
529          rssTree->Construct(mVssRays, NULL);
530        cout<<"RssTree root PVS size = "<<rssTree->GetRootPvsSize()<<endl;
531       
532        if (mExportRssTree) {
533          ExportRssTree("rss-tree-100.x3d", rssTree, Vector3(1,0,0));
534          ExportRssTree("rss-tree-001.x3d", rssTree, Vector3(0,0,1));
535          ExportRssTree("rss-tree-101.x3d", rssTree, Vector3(1,0,1));
536          ExportRssTree("rss-tree-101m.x3d", rssTree, Vector3(-1,0,-1));
537          ExportRssTreeLeaves(rssTree, 10);
538        }
539       
540        if (mExportPvs) {
541          ExportPvs("rss-pvs-initial.x3d", rssTree);
542        }
543  }
544 
545  // viewcells->UpdatePVS(newVssRays);
546 
547  int rssPass = 0;
548  int rssSamples = 0;
549  while (1) {
550        int num = mRssSamplesPerPass;
551        SimpleRayContainer rays;
552        VssRayContainer vssRays;
553               
554        if (!mUseImportanceSampling) {
555          for (int j=0; j < num; j++) {
556                Vector3 viewpoint = GetViewpoint(mViewSpaceBox);
557                Vector3 direction = GetDirection(viewpoint, mViewSpaceBox);
558                rays.push_back(SimpleRay(viewpoint, direction));
559          }
560        } else {
561          num = GenerateImportanceRays(rssTree, num, rays);
562        }
563               
564               
565        for (int i=0; i < rays.size(); i++)
566          CastRay(rays[i].mOrigin, rays[i].mDirection, vssRays);
567
568       
569        totalSamples+=num;
570        rssSamples+=num;
571
572        mStats <<
573          "#Pass\n" <<mPass<<endl<<
574          "#RssPass\n" <<rssPass<<endl<<
575          "#Time\n" << TimeDiff(startTime, GetTime())*1e-3<<endl<<
576          "#TotalSamples\n" <<totalSamples<<endl<<
577          "#RssSamples\n" <<rssSamples<<endl;
578
579        if (mUseViewcells) {
580         
581          /// compute view cell contribution of rays
582          mViewCellsManager->ComputeSampleContributions(vssRays);
583         
584          vssRays.PrintStatistics(mStats);
585          mViewCellsManager->PrintPvsStatistics(mStats);
586        }
587
588        // add rays to the tree after the viewcells have been cast to have their contributions
589        // already when adding into the tree
590        // do not add those rays which have too low or no contribution....
591       
592        if (mUseImportanceSampling) {
593          rssTree->AddRays(vssRays);
594         
595          if (0) {
596                cout<<"############# Rss PVS STAT ##################\n";
597                cout<<"#AVG_RSS_PVS\n"<<rssTree->GetAvgPvsSize()<<endl;
598                cout<<"#RSS_ROOT_PVS\n"<<rssTree->GetRootPvsSize()<<endl;
599          }
600         
601          if (mUpdateSubdivision) {
602                int subdivided = rssTree->UpdateSubdivision();
603                cout<<"subdivided leafs = "<<subdivided<<endl;
604                cout<<"#total leaves = "<<rssTree->stat.Leaves()<<endl;
605          }
606        }
607       
608        if (mExportRays) {
609          char filename[64];
610          if (mUseImportanceSampling)
611                sprintf(filename, "rss-rays-i%04d.x3d", rssPass);
612          else
613                sprintf(filename, "rss-rays-%04d.x3d", rssPass);
614         
615          ExportRays(filename, vssRays, mExportNumRays);
616        }
617
618       
619        if (mExportPvs) {
620          char filename[64];
621          sprintf(filename, "rss-pvs-%04d.x3d", rssPass);
622          ExportPvs(filename, rssTree);
623        }
624
625        if (totalSamples >= mRssSamples + mInitialSamples)
626          break;
627
628       
629        rssPass++;
630        mPass++;
631  }
632 
633  if (mUseViewcells) {
634
635
636  //-- render simulation after merge
637  cout << "\nevaluating bsp view cells render time after merge ... ";
638 
639  mRenderSimulator->RenderScene();
640  SimulationStatistics ss;
641  mRenderSimulator->GetStatistics(ss);
642
643  cout << " finished" << endl;
644  cout << ss << endl;
645  Debug << ss << endl;
646
647  }
648
649  delete rssTree;
650 
651  return true;
652}
653
Note: See TracBrowser for help on using the repository browser.