source: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp @ 333

Revision 333, 18.1 KB checked in by bittner, 19 years ago (diff)

code merge

Line 
1#include "SceneGraph.h"
2#include "KdTree.h"
3#include "SamplingPreprocessor.h"
4#include "X3dExporter.h"
5#include "Environment.h"
6#include "MutualVisibility.h"
7#include "Polygon3.h"
8#include "ViewCell.h"
9
10SamplingPreprocessor::SamplingPreprocessor(): mPass(0), mSampleRays(NULL)
11{
12  // this should increase coherence of the samples
13  environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
14  environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
15  environment->GetIntValue("BspTree.Construction.samples", mBspConstructionSamples);
16
17  mKdPvsDepth = 100;
18  mStats.open("stats.log");
19
20}
21
22SamplingPreprocessor::~SamplingPreprocessor()
23{
24        CLEAR_CONTAINER(mSampleRays);
25}
26
27void
28SamplingPreprocessor::SetupRay(Ray &ray, const Vector3 &point, const Vector3 &direction)
29{
30  ray.intersections.clear();
31  ray.leaves.clear();
32  ray.meshes.clear();
33  ray.viewCells.clear();
34
35  //  cout<<point<<" "<<direction<<endl;
36  ray.Init(point, direction, Ray::LOCAL_RAY);
37}
38
39KdNode *
40SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
41{
42  KdNode *node = leaf;
43  while (node->mParent && node->mDepth > mKdPvsDepth)
44    node = node->mParent;
45  return node;
46}
47
48bool
49SamplingPreprocessor::BuildBspTree()
50{
51        // delete old tree
52        DEL_PTR(mBspTree);
53        mBspTree = new BspTree(&mUnbounded);
54
55        ObjectContainer objects;
56       
57        switch (BspTree::sConstructionMethod)
58        {
59        case BspTree::FROM_INPUT_VIEW_CELLS:
60                mBspTree->SetGenerateViewCells(false);
61                mBspTree->Construct(mViewCells);
62                break;
63        case BspTree::FROM_SCENE_GEOMETRY:
64                DeleteViewCells(); // we generate new view cells
65                mBspTree->SetGenerateViewCells(true);
66                mSceneGraph->CollectObjects(&objects);
67                mBspTree->Construct(objects);
68                Debug << "collecting view cells" << endl;
69                mBspTree->CollectViewCells(mViewCells);
70                break;
71        case BspTree::FROM_RAYS:
72                DeleteViewCells(); // we generate new view cells
73                mBspTree->SetGenerateViewCells(true);
74                mBspTree->Construct(mSampleRays);
75                Debug << "collecting view cells" << endl;
76                mBspTree->CollectViewCells(mViewCells);
77                break;
78        default:
79                Debug << "Error: Method not available\n";
80                break;
81        }
82       
83       
84        return true;
85}
86
87int
88SamplingPreprocessor::AddNodeSamples(Intersectable *object,
89                                                                                                                                                 const Ray &ray
90                                                                                                                                                 )
91{
92  int contributingSamples = 0;
93  int j;
94  for (j=0; j < ray.leaves.size(); j++) {
95    KdNode *node = GetNodeForPvs( ray.leaves[j] );
96    contributingSamples += object->mKdPvs.AddSample(node);
97  }
98   
99  if (mPass > 10)
100    for (j=1; j < ((int)ray.leaves.size() - 1); j++) {
101      ray.leaves[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
102  }
103 
104  return contributingSamples;
105}
106
107
108int SamplingPreprocessor::AddObjectSamples(Intersectable *obj, const Ray &ray)
109{
110        int contributingSamples = 0;
111        int j;
112 
113        // object can be seen from the view cell => add to view cell pvs
114        for (j=0; j < ray.viewCells.size(); ++ j)
115        {       // if ray not in unbounded space
116                if (ray.viewCells[j] != &mUnbounded)
117                        contributingSamples += ray.viewCells[j]->GetPvs().AddSample(obj);
118        }
119 
120        // rays passing through this viewcell
121        if (mPass > 1)
122                for (j=1; j < ((int)ray.viewCells.size() - 1); ++ j)
123                {
124                        if (ray.viewCells[j] != &mUnbounded)
125                                ray.viewCells[j]->AddPassingRay(ray, contributingSamples ? 1 : 0);
126                }
127 
128        return contributingSamples;
129}
130
131
132void
133SamplingPreprocessor::HoleSamplingPass()
134{
135  vector<KdLeaf *> leaves;
136  mKdTree->CollectLeaves(leaves);
137 
138  // go through all the leaves and evaluate their passing contribution
139  for (int i=0 ; i < leaves.size(); i++) {
140    KdLeaf *leaf = leaves[i];
141    cout<<leaf->mPassingRays<<endl;
142  }
143}
144
145
146int
147SamplingPreprocessor::CastRay(Intersectable *object, Ray &ray)
148{
149        int sampleContributions = 0;
150
151        // cast ray to KD tree to find intersection with other objects
152        mKdTree->CastRay(ray);
153       
154        if (mViewCellsType == BSP_VIEW_CELLS)
155        {
156                // cast ray to BSP tree to get intersection with view cells
157                if (mBspTree)
158                {
159                        mBspTree->CastRay(ray);
160               
161                        sampleContributions += AddObjectSamples(object, ray);
162                               
163                        if (!ray.intersections.empty()) // second intersection found
164                        {
165                                sampleContributions +=
166                                        AddObjectSamples(ray.intersections[0].mObject, ray);
167                        }
168                }
169        }
170        else
171        {
172                if (ray.leaves.size()) {
173                        sampleContributions += AddNodeSamples(object, ray);
174               
175                        if (ray.intersections.size()) {
176                                sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray);
177                        }
178                }
179        }       
180       
181        return sampleContributions;
182}
183
184//  void
185//  SamplingPreprocessor::AvsGenerateRandomRay(Ray &ray)
186//  {
187//    int objId = RandomValue(0, mObjects.size());
188//    Intersectable *object = objects[objId];
189//    object->GetRandomSurfacePoint(point, normal);
190//    direction = UniformRandomVector(normal);
191//    SetupRay(ray, point, direction);
192//  }
193
194//  void
195//  SamplingPreprocessor::AvsHandleRay(Ray &ray)
196//  {
197//    int sampleContributions = 0;
198
199//    mKdTree->CastRay(ray);
200 
201//    if (ray.leaves.size()) {
202//      sampleContributions += AddNodeSamples(object, ray, pass);
203   
204//      if (ray.intersections.size()) {
205//        sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray, pass);
206//      }
207//    }
208//  }
209
210//  void
211//  SamplingPreprocessor::AvsBorderSampling(Ray &ray)
212//  {
213 
214
215//  }
216
217//  void
218//  SamplingPreprocessor::AvsPass()
219//  {
220//    Ray ray;
221//    while (1) {
222//      AvsGenerateRay(ray);
223//      HandleRay(ray);
224//      while ( !mRayQueue.empty() ) {
225//        Ray ray = mRayQueue.pop();
226//        mRayQueue.pop();
227//        AdaptiveBorderSampling(ray);
228//      }
229//    }
230 
231 
232
233//  }
234
235
236int
237SamplingPreprocessor::CastEdgeSamples(
238                                                                                                                                                        Intersectable *object,
239                                                                                                                                                        const Vector3 &point,
240                                                                                                                                                        MeshInstance *mi,
241                                                                                                                                                        const int samples
242                                                                                                                                                        )
243{
244        Ray ray;
245        int maxTries = samples*10;
246        int i;
247        int rays = 0;
248        int edgeSamplesContributions = 0;
249        for (i=0; i < maxTries && rays < samples; i++) {
250                // pickup a random face of each mesh
251                Mesh *mesh = mi->GetMesh();
252                int face = RandomValue(0, mesh->mFaces.size()-1);
253               
254                Polygon3 poly(mesh->mFaces[face], mesh);
255                poly.Scale(1.001);
256                // now extend a random edge of the face
257                int edge = RandomValue(0, poly.mVertices.size()-1);
258                float t = RandomValue(0.0f,1.0f);
259                Vector3 target = t*poly.mVertices[edge] + (1.0f-t)*poly.mVertices[(edge + 1)%
260                                                                                                                                                                                                                                                                                 poly.mVertices.size()];
261                SetupRay(ray, point, target - point);
262                if (!mesh->CastRay(ray, mi)) {
263                        // the rays which intersect the mesh have been discarded since they are not tangent
264                        // to the mesh
265                        rays++;
266                        edgeSamplesContributions += CastRay(object, ray);
267                }
268        }
269        return edgeSamplesContributions;
270}
271
272bool
273SamplingPreprocessor::ComputeVisibility()
274{
275 
276  // pickup an object
277  ObjectContainer objects;
278 
279  mSceneGraph->CollectObjects(&objects);
280
281  Vector3 point, normal, direction;
282  Ray ray;
283
284  long startTime = GetTime();
285 
286  int i;
287  int totalSamples = 0;
288
289  int pvsOut = Min((int)objects.size(), 10);
290
291  vector<Ray> rays[10];
292
293  vector<Ray> vcRays[5];
294  ViewCellContainer pvsViewCells;
295  vector<Ray> viewCellRays; // used for BSP tree construction
296
297  while (totalSamples < mTotalSamples) {
298                int passContributingSamples = 0;
299                int passSampleContributions = 0;
300                int passSamples = 0;
301                int index = 0;
302                Real maxTime = 0;
303                int maxTimeIdx = 0;
304
305                cout << "totalSamples: "  << totalSamples << endl;
306
307                for (i = 0; i < objects.size(); i++) {
308                                               
309                        KdNode *nodeToSample = NULL;
310                        Intersectable *object = objects[i];
311               
312                        int pvsSize = 0;
313                        if (mViewCellsType == KD_VIEW_CELLS)
314                                pvsSize = object->mKdPvs.GetSize();
315                                               
316                        if (0 && pvsSize) {
317                                // mail all nodes from the pvs
318                                Intersectable::NewMail();
319                                KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
320                         
321                                for (; i != object->mKdPvs.mEntries.end(); i++) {
322                                        KdNode *node = (*i).first;
323                                        node->Mail();
324                                }
325                               
326                                int maxTries = 2*pvsSize;
327                                Debug << "Finding random neighbour" << endl;   
328                                for (int tries = 0; tries < 10; tries++) {
329                                        index = RandomValue(0, pvsSize - 1);
330                                        KdPvsData data;
331                                        KdNode *node;
332                                        object->mKdPvs.GetData(index, node, data);
333                                        nodeToSample = mKdTree->FindRandomNeighbor(node, true);
334                                        if (nodeToSample)
335                                                break;
336                                }
337                        }
338                       
339                        if (0 && pvsSize && mPass == 1000 ) {
340                                // mail all nodes from the pvs
341                                Intersectable::NewMail();
342                                KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
343                                for (; i != object->mKdPvs.mEntries.end(); i++) {
344                                        KdNode *node = (*i).first;
345                                        node->Mail();
346                                }
347                                Debug << "Get all neighbours from PVS" << endl;
348                                vector<KdNode *> invisibleNeighbors;
349                                // get all neighbors of all PVS nodes
350                                i = object->mKdPvs.mEntries.begin();
351                                for (; i != object->mKdPvs.mEntries.end(); i++) {
352                                        KdNode *node = (*i).first;
353                                        mKdTree->FindNeighbors(node, invisibleNeighbors, true);
354                                        AxisAlignedBox3 box = object->GetBox();
355                                        for (int j=0; j < invisibleNeighbors.size(); j++) {
356                                                int visibility = ComputeBoxVisibility(mSceneGraph,
357                                                                                                                                                                                                        mKdTree,
358                                                                                                                                                                                                        box,
359                                                                                                                                                                                                        mKdTree->GetBox(invisibleNeighbors[j]),
360                                                                                                                                                                                                        1e-6f);
361                                                //            exit(0);
362                                        }
363                                        // now rank all the neighbors according to probability that a new
364                                        // sample creates some contribution
365                                }
366                        }
367                       
368                        object->GetRandomSurfacePoint(point, normal);
369                       
370                        long samplesPerObjStart = GetTime();
371
372                        bool viewcellSample = true;
373                        int sampleContributions;
374
375                        if (viewcellSample) {
376                                nodeToSample = mKdTree->GetRandomLeaf(Plane3(normal, point));
377                                       
378                                for (int k=0; k < mSamplesPerPass; k++) {
379                                        if (nodeToSample) {
380                                                int maxTries = 5;
381                                               
382                                                for (int tries = 0; tries < maxTries; tries++) {
383                                                        direction = mKdTree->GetBox(nodeToSample).GetRandomPoint() - point;
384                                                       
385                                                        if (DotProd(direction, normal) > Limits::Small)
386                                                                break;                                                 
387                                                }
388                                               
389                                                if (tries == maxTries)
390                                                        direction = UniformRandomVector(normal);
391                                        }
392                                        else {
393                                                direction = UniformRandomVector(normal);
394                                        }
395                                       
396                                        // construct a ray
397                                        SetupRay(ray, point, direction);
398                                       
399                                        sampleContributions = CastRay(object, ray);
400
401                                        //-- CORR matt: put block inside loop
402                                        if (sampleContributions) {
403                                                passContributingSamples++;
404                                                passSampleContributions += sampleContributions;
405                                        }
406
407                                        if ( i < pvsOut )
408                                                rays[i].push_back(ray);
409               
410                                        if (!ray.intersections.empty()) {
411                                                // check whether we can add this to the rays
412                                                for (int j = 0; j < pvsOut; j++) {
413                                                        if (objects[j] == ray.intersections[0].mObject) {
414                                                                rays[j].push_back(ray);
415                                                        }
416                                                }
417                                        }
418                                        //-------------------
419
420                                        if (mViewCellsType == BSP_VIEW_CELLS)
421                                        {
422                        // save rays for bsp tree construction
423                                                if ((BspTree::sConstructionMethod = BspTree::FROM_RAYS) &&
424                                                        (totalSamples < mBspConstructionSamples))
425                                                {
426                                                        mSampleRays.push_back(new Ray(ray));
427                                                }
428                                                else
429                                                {
430                            // construct BSP tree using the samples
431                                                        if (!mBspTree)
432                                                        {
433                                                                BuildBspTree();
434
435                                                                cout << "generated " << (int)mViewCells.size() << " view cells" << endl;
436                                                                passContributingSamples += mBspTree->GetStat().contributingSamples;
437                                                                passSampleContributions += mBspTree->GetStat().pvs;
438
439                                                                BspTreeStatistics(Debug);       
440                                                                Export("vc_bsptree.x3d", false, false, true);
441                                                        }
442                                                                                                       
443                                                        // some random view cells for output
444                                                        if (pvsViewCells.empty())
445                                                        {
446                                                                int vcPvsOut = Min((int)mViewCells.size(), 5);
447                                                       
448                                                                for (int j = 0; j < vcPvsOut; ++ j)
449                                                                {
450                                                                        int idx = Random((int)mViewCells.size());
451                                                                        Debug << "output view cell=" << idx << endl;
452                                                                        pvsViewCells.push_back(mViewCells[Random((int)mViewCells.size())]);
453                                                                }
454                                                        }
455                                                        else
456                                                        {
457                                                                // check whether we can add the current ray to the rays
458                                                                for (int k = 0; k < (int)ray.viewCells.size(); ++ k)
459                                                                        for (int j = 0; j < (int)pvsViewCells.size(); ++ j)
460                                                                                if (pvsViewCells[j] == ray.viewCells[k])
461                                                                                        vcRays[j].push_back(ray);                                                       
462                                                        }
463                                                }                               
464                                        }
465               
466                                }
467                        } else {
468                                // edge samples
469                                // get random visible mesh
470                                //                              object->GetRandomVisibleMesh(Plane3(normal, point));
471                        }
472                               
473                        // measure maximal time for samples per object
474                        Real t = TimeDiff(samplesPerObjStart, GetTime());
475
476                        if (t > maxTime)
477                        {
478                                maxTime = t;
479                                maxTimeIdx = i;
480                        }
481       
482                        // CORR matt: must add all samples
483                        passSamples += mSamplesPerPass;
484                }
485       
486                totalSamples += passSamples;
487               
488                //    if (pass>10)
489                //      HoleSamplingPass();
490   
491                mPass++;
492
493                int pvsSize = 0;
494       
495                if (mViewCellsType == BSP_VIEW_CELLS) {
496                        for (i=0; i < mViewCells.size(); i++) {
497                                ViewCell *vc = mViewCells[i];
498                                pvsSize += vc->GetPvs().GetSize();
499                        }
500                } else  {
501                        for (i=0; i < objects.size(); i++) {
502                                Intersectable *object = objects[i];
503                                pvsSize += object->mKdPvs.GetSize();
504                        }
505                }
506
507                Debug << "maximal time needed for pass: " << maxTime << " (object " << maxTimeIdx << ")" << endl;
508
509                float avgRayContrib = (passContributingSamples > 0) ?
510                        passSampleContributions/(float)passContributingSamples : 0;
511
512                cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
513                cout << "#TotalSamples=" << totalSamples/1000
514                                 << "k   #SampleContributions=" << passSampleContributions << " ("
515                                 << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
516                                 << pvsSize/(float)objects.size() << endl
517                                 << "avg ray contrib=" << avgRayContrib << endl;
518               
519                mStats <<
520                        "#Pass\n" <<mPass<<endl<<
521                        "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
522                        "#TotalSamples\n" << totalSamples<< endl<<
523                        "#SampleContributions\n" << passSampleContributions << endl <<
524                        "#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
525                        "#AvgPVS\n"<< pvsSize/(float)objects.size() << endl <<
526                        "#AvgRayContrib\n" << avgRayContrib << endl;
527        }
528
529        if (mViewCellsType == KD_VIEW_CELLS)   
530                cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
531 
532  //  HoleSamplingPass();
533  if (0) {
534    Exporter *exporter = Exporter::GetExporter("ray-density.x3d");
535    exporter->SetExportRayDensity(true);
536    exporter->ExportKdTree(*mKdTree);
537
538        if (mViewCellsType == BSP_VIEW_CELLS)   
539                exporter->ExportBspTree(*mBspTree);
540
541    delete exporter;
542  }
543 
544  bool exportRays = false;
545  if (exportRays) {
546    Exporter *exporter = NULL;
547    exporter = Exporter::GetExporter("sample-rays.x3d");
548    exporter->SetWireframe();
549    exporter->ExportKdTree(*mKdTree);
550        exporter->ExportBspTree(*mBspTree);
551
552    for (i=0; i < pvsOut; i++)
553      exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
554    exporter->SetFilled();
555         
556    delete exporter;
557  }
558 
559  if (1) {
560  if (mViewCellsType == BSP_VIEW_CELLS)
561  {
562          bool exportSplits = false;
563          environment->GetBoolValue("BspTree.exportSplits", exportSplits);
564
565          // export the bsp splits
566          if (exportSplits)
567          {
568                  Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
569
570                  if (exporter)
571                  {     
572                          Material m;
573                          m.mDiffuseColor = RgbColor(1, 0, 0);
574                          exporter->SetForcedMaterial(m);
575                          exporter->SetWireframe();
576                          exporter->ExportBspSplits(*mBspTree);
577
578                          // take forced material, else big scenes cannot be viewed
579                          m.mDiffuseColor = RgbColor(0, 1, 0);
580                          exporter->SetForcedMaterial(m);
581                          exporter->SetFilled();
582
583                          exporter->ResetForcedMaterial();
584
585                          if (1)
586                          {
587                                  Material m;//= RandomMaterial();
588                                  m.mDiffuseColor = RgbColor(0, 0, 1);
589                                  exporter->SetForcedMaterial(m);
590                 
591                                  for (int j = 0; j < objects.size(); ++ j)
592                                           exporter->ExportIntersectable(objects[j]);
593                       
594                                  delete exporter;
595                          }
596                  }
597          }
598
599          for (int j = 0; j < pvsViewCells.size(); ++ j)
600          {
601                  ViewCell *vc = pvsViewCells[j];
602
603                  Intersectable::NewMail();
604                  char s[64]; sprintf(s, "bsp-pvs%04d.x3d", j);
605
606                  Exporter *exporter = Exporter::GetExporter(s);
607                  exporter->SetFilled();
608
609                  ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
610
611                  Material m;//= RandomMaterial();
612                  m.mDiffuseColor = RgbColor(0, 1, 0);
613                  exporter->SetForcedMaterial(m);
614
615                  exporter->ExportViewCell(vc);
616
617                  Debug << j << ": pvs size=" << (int)vc->GetPvs().GetSize()
618                            << ", piercing rays=" << (int)vcRays[j].size() << endl;
619
620                  exporter->SetWireframe();
621
622                  // export view cells
623                  m.mDiffuseColor = RgbColor(1, 0, 1);
624                  exporter->SetForcedMaterial(m);
625                  exporter->ExportViewCells(mViewCells);
626                       
627                  // export rays piercing this view cell
628                  exporter->ExportRays(vcRays[j], 1000, RgbColor(0, 1, 0));
629
630                  m.mDiffuseColor = RgbColor(1, 0, 0);
631                  exporter->SetForcedMaterial(m);
632
633                  // output pvs of view cell
634                  for (; it != vc->GetPvs().mEntries.end(); ++ it)
635                  {
636                          Intersectable *intersect = (*it).first;
637                          if (!intersect->Mailed())
638                          {
639                                  exporter->ExportIntersectable(intersect);
640                                  intersect->Mail();
641                          }                     
642                  }
643               
644                  // output rest of the objects
645                  if (1)
646                  {
647                          Material m;//= RandomMaterial();
648                          m.mDiffuseColor = RgbColor(0, 0, 1);
649                          exporter->SetForcedMaterial(m);
650
651                          for (int j = 0; j < objects.size(); ++ j)
652                                  if (!objects[j]->Mailed())
653                                  {
654                                          //if (j == 2198)m.mDiffuseColor = RgbColor(1, 0, 1);
655                                          //else m.mDiffuseColor = RgbColor(1, 1, 0);
656                                          exporter->SetForcedMaterial(m);
657                                          exporter->ExportIntersectable(objects[j]);
658                                          objects[j]->Mail();
659                                  }
660                  }
661                  DEL_PTR(exporter);
662                }
663  } 
664
665   for (int k=0; k < pvsOut; k++) {
666      Intersectable *object = objects[k];
667      char s[64];
668      sprintf(s, "sample-pvs%04d.x3d", k);
669      Exporter *exporter = Exporter::GetExporter(s);
670      exporter->SetWireframe();
671
672       
673          KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
674          Intersectable::NewMail();
675                 
676          // avoid adding the object to the list
677          object->Mail();
678          ObjectContainer visibleObjects;
679
680          for (; i != object->mKdPvs.mEntries.end(); i++)
681          {
682                  KdNode *node = (*i).first;
683                  exporter->ExportBox(mKdTree->GetBox(node));
684                  mKdTree->CollectObjects(node, visibleObjects);
685          }
686
687          exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
688          exporter->SetFilled();
689
690          for (int j = 0; j < visibleObjects.size(); j++)
691                  exporter->ExportIntersectable(visibleObjects[j]);
692       
693
694          Material m;
695          m.mDiffuseColor = RgbColor(1, 0, 0);
696          exporter->SetForcedMaterial(m);
697          exporter->ExportIntersectable(object);
698
699          delete exporter;
700    }
701  }
702 
703  return true;
704}
Note: See TracBrowser for help on using the repository browser.