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

Revision 490, 17.0 KB checked in by mattausch, 19 years ago (diff)

added loading and storing rays capability

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