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

Revision 563, 18.3 KB checked in by bittner, 18 years ago (diff)

rss sampling changes, preprocessor::GenerateRays?

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