source: trunk/VUT/GtpVisibilityPreprocessor/src/VssPreprocessor.cpp @ 508

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

implemented view cells exporting / loading
improved vsp bsp tree (only axis aligbed until a level), reuse results from Plane
testing, collectmergeneighbors
implemented view cell meshes

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