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

Revision 452, 16.0 KB checked in by mattausch, 19 years ago (diff)

started to add view cell merging to vsp kd tree

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