source: GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp @ 2743

Revision 2743, 11.4 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "RayCaster.h"
2#include "VssRay.h"
3#include "Ray.h"
4#include "Preprocessor.h"
5#include "ViewCellsManager.h"
6
7#include <cassert>
8
9namespace GtpVisibilityPreprocessor {
10
11
12#define DEBUG_PROCESS_RAY 0
13
14#define DEBUG_RAYCAST 0
15
16#define EXACT_BOX_CLIPPING 0
17
18RayCaster::RayCaster(const Preprocessor &preprocessor):
19  mVssRayPool(), mPreprocessor(preprocessor)
20{
21}
22
23
24RayCaster::~RayCaster()
25{
26}
27
28
29VssRay *RayCaster::CastRay(const SimpleRay &simpleRay,
30                                                   const AxisAlignedBox3 &box,
31                                                   const bool castDoubleRay)
32{
33        VssRayContainer rays;
34        //CastRay(simpleRay, rays, box, castDoubleRay, true);
35        CastRay(simpleRay, rays, box, castDoubleRay, false);
36   
37        if (!rays.empty())
38                return rays.back();
39        else
40                return NULL;
41}
42
43
44bool
45RayCaster::ClipToViewSpaceBox(const Vector3 &origin,
46                                                          const Vector3 &termination,
47                                                          Vector3 &clippedOrigin,
48                                                          Vector3 &clippedTermination)
49{
50 
51  Ray ray(origin, termination - origin, Ray::LINE_SEGMENT);     
52  ray.Precompute();
53 
54  float tmin, tmax;
55  if ((!mPreprocessor.mViewCellsManager->
56           GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax)) ||
57          tmin>=tmax
58          )
59        return false;
60
61  if (tmin >= 1.0f || tmax <= 0.0f)
62        return false;
63 
64  if (tmin > 0.0f)
65        clippedOrigin = ray.Extrap(tmin);
66  else
67        clippedOrigin = origin;
68 
69  if (tmax < 1.0f)
70        clippedTermination = ray.Extrap(tmax);
71  else
72        clippedTermination = termination;
73 
74  return true;
75}
76
77/** Checks if ray is valid
78        (e.g., not in empty view space or outside the view space)
79*/
80bool
81RayCaster::ValidateRay(const Vector3 &origin,
82                                           const Vector3 &direction,
83                                           const AxisAlignedBox3 &box,
84                                           Intersection &hit)
85{
86        if (!hit.mObject) 
87        {
88                // compute intersection with the scene bounding box
89#if EXACT_BOX_CLIPPING
90                static Ray ray;
91                mPreprocessor.SetupRay(ray, origin, direction);
92
93                float tmin, tmax;
94                if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax))
95                {
96                        hit.mPoint = ray.Extrap(tmax);
97                }
98                else
99                {
100                        // cout<<" invalid hp "<<tmin<<" "<<tmax<<endl;
101                        // cout<<" box "<<box<<endl;
102                        // cout<<" origin "<<origin<<endl;
103                        // cout<<" direction "<<direction<<endl;
104                        // cout<< "inv dir"<<ray.GetInvDir()<<endl;
105                        return false;
106                }
107#else
108                hit.mPoint = origin + direction * Magnitude(box.Diagonal());
109#endif
110        }
111        else
112        {
113          if (mPreprocessor.mDetectEmptyViewSpace)  {
114                if (DotProd(hit.mNormal, direction) >= -Limits::Small)  {       
115                  hit.mObject = NULL;
116                  return false;
117                }
118          }
119        }
120       
121        return true;
122}
123
124void
125RayCaster::SortRays(SimpleRayContainer &rays)
126{
127  AxisAlignedBox3 box =
128        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
129 
130  float b[12]={
131        box.Min().x,
132        box.Min().y,
133        box.Min().z,
134        -1,
135        -1,
136        -1,
137        box.Max().x,
138        box.Max().y,
139        box.Max().z,
140        1,
141        1,
142        1
143  };
144
145#if 0
146  static vector<SimpleRay *> pointerArray;
147
148  if (pointerArray.size()!=rays.size()) {
149        // realloc the pointerarray
150        pointerArray.resize(rays.size());
151  }
152
153  // init pointer array
154  SimpleRay *p = &pointerArray[0];
155  for (i=0; i < rays.size(); i++, p++)
156        pointerArray[i] = p;
157#endif
158 
159#if 1
160  _SortRays(rays,
161                        0,
162                        (int)rays.size()-1,
163                        0,
164                        b
165                        );
166#endif
167}
168                                       
169void
170RayCaster::_SortRays(SimpleRayContainer &rays,
171                                         const int l,
172                                         const int r,
173                                         const int depth,
174                                         float *box)
175{
176  // pick-up a pivot
177  int axis = 0;
178 
179  float maxDiff = -1.0f;
180  // get the largest axis
181  int offset = 0;
182  int i;
183
184  //const int batchsize = 16384;
185  const int batchsize = 8192;
186  //const int batchsize = 128;
187
188  //if (r - l < 16*batchsize)
189  //    offset = 3;
190       
191  //  if (depth%2==0)
192  //    offset = 3;
193 
194  for (i=offset; i < offset + 3; i++) {
195        float diff = box[i + 6] - box[i];
196        if (diff > maxDiff) {
197          maxDiff = diff;
198          axis = i;
199        }
200  }
201
202  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
203 
204  i=l;
205  int j=r;
206
207  float x = (box[axis] + box[axis+6])*0.5f;
208  //  float x = rays[(l+r)/2].GetParam(axis);
209  do {
210        while(i<j && rays[i].GetParam(axis) < x)
211          i++;
212        while(i<j && x < rays[j].GetParam(axis))
213          j--;
214       
215        if (i <= j) {
216          swap(rays[i], rays[j]);
217          i++;
218          j--;
219        }
220  } while (i<=j);
221
222 
223  if (l + batchsize < j ) {
224        // set new max
225        float save = box[axis+6];
226        box[axis+6] = x;
227        _SortRays(rays, l, j, depth+1, box);
228        box[axis+6] = save;
229  } else {
230        //      for (int k=0; k < 6; k++)
231        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
232  }
233 
234  if (i + batchsize < r) {
235        // set new min
236        box[axis] = x;
237    _SortRays(rays, i, r, depth+1, box);
238  } else {
239        //      for (int k=0; k < 6; k++)
240        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
241  }
242       
243}
244 
245
246void
247RayCaster::SortRays2(SimpleRayContainer &rays)
248{
249  AxisAlignedBox3 box =
250        mPreprocessor.mViewCellsManager->GetViewSpaceBox();
251
252  const float sizeBox = Magnitude(box.Diagonal());
253  // This is some size of the
254  const float sizeDir = 0.2f * sizeBox;
255 
256  float b[12]={
257    box.Min().x,
258    box.Min().y,
259    box.Min().z,
260    -sizeDir,
261    -sizeDir,
262    -sizeDir,
263    box.Max().x,
264    box.Max().y,
265    box.Max().z,
266    sizeDir,
267    sizeDir,
268    sizeDir
269  };
270
271#if 0
272  static vector<SimpleRay *> pointerArray;
273
274  if (pointerArray.size()!=rays.size()) {
275        // realloc the pointerarray
276        pointerArray.resize(rays.size());
277  }
278
279  // init pointer array
280  SimpleRay *p = &pointerArray[0];
281  for (i=0; i < rays.size(); i++, p++)
282        pointerArray[i] = p;
283#endif
284 
285  _SortRays2(rays, 0, (int)rays.size()-1, 0, b);
286
287  return;
288}
289                                       
290void
291RayCaster::_SortRays2(SimpleRayContainer &rays,
292                      const int l,
293                      const int r,
294                      const int depth,
295                      float box[12])
296{
297  // pick-up a pivot
298  int axis;
299 
300  float maxDiff = -1.0f;
301  // get the largest axis
302  int offset = 0;
303  int i;
304
305  //const int batchsize = 16384;
306  //const int batchsize = 8192;
307  const int batchsize = 128;
308
309  //if (r - l < 16*batchsize)
310  //    offset = 3;
311       
312  //  if (depth%2==0)
313  //    offset = 3;
314 
315  for (i=offset; i < offset + 6; i++) {
316    float diff = box[i + 6] - box[i];
317    assert(diff >= 0.f);
318    if (diff > maxDiff) {
319      // Find the maximum
320      maxDiff = diff;
321      axis = i;
322    }
323  }
324
325  //  cout<<depth<<" "<<axis<<" "<<l<<" "<<r<<endl;
326 
327  i=l;
328  int j=r;
329
330  float x = (box[axis] + box[axis+6])*0.5f;
331  //  float x = rays[(l+r)/2].GetParam(axis);
332  do {
333        while(i<j && rays[i].GetParam(axis) < x)
334          i++;
335        while(i<j && x < rays[j].GetParam(axis))
336          j--;
337       
338        if (i <= j) {
339          swap(rays[i], rays[j]);
340          i++;
341          j--;
342        }
343  } while (i<=j);
344
345 
346  if (l + batchsize < j ) {
347        // set new max
348        float save = box[axis+6];
349        box[axis+6] = x;
350        _SortRays2(rays, l, j, depth+1, box);
351        box[axis+6] = save;
352  } else {
353        //      for (int k=0; k < 6; k++)
354        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
355  }
356 
357  if (i + batchsize < r) {
358    // set new min
359    box[axis] = x;
360    _SortRays2(rays, i, r, depth+1, box);
361  } else {
362        //      for (int k=0; k < 6; k++)
363        //        cout<<k<<" "<<box[k]<<" - "<<box[k+6]<<endl;
364  }
365       
366}
367 
368 
369VssRay *RayCaster::RequestRay(const Vector3 &origin,
370                                                          const Vector3 &termination,
371                                                          Intersectable *originObject,
372                                                          Intersectable *terminationObject,
373                                                          const int pass,
374                                                          const float pdf)
375{
376#ifdef USE_RAY_POOL
377
378 #if DEBUG_RAYCAST
379        Debug<<"PR2a"<<flush;
380#endif
381       
382        // old method: always allocate
383        if (0) return new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
384
385        VssRay *vssRay = mVssRayPool.Alloc();
386
387#if DEBUG_RAYCAST
388        Debug<<"PR2b"<<flush;
389#endif
390       
391        *vssRay = VssRay(origin, termination, originObject, terminationObject, pass, pdf);
392
393#if DEBUG_RAYCAST
394        Debug<<"PR2c"<<flush;
395#endif
396
397#else
398        VssRay *vssRay = new VssRay(origin, termination, originObject, terminationObject, pass, pdf);
399#endif
400        return vssRay;
401}
402
403
404void RayCaster::SheduleRayForDeletion(VssRay *ray)
405{
406#ifndef USE_RAY_POOL
407        delete ray;
408#endif
409}
410
411
412int
413RayCaster::ProcessRay(const SimpleRay &simpleRay,
414                                          Intersection &hitA,
415                                          Intersection &hitB,
416                                          VssRayContainer &vssRays,
417                                          const AxisAlignedBox3 &box,
418                                          const bool castDoubleRay,
419                                          const bool pruneInvalidRays)
420{
421  int hits = 0;
422
423
424#if DEBUG_RAYCAST
425  static int id=0;
426  Debug<<"PRA "<<id++<<endl<<flush;
427#endif
428       
429        if (pruneInvalidRays)
430        {
431          if (!hitA.mObject && !hitB.mObject) {
432#if DEBUG_PROCESS_RAY
433                cout<<"I1 ";
434#endif
435                return 0;
436          }
437        }
438       
439        // regardless of the pruneInvalidRays setting reject
440        // rays which degenerate to a point
441        if (EpsilonEqualV3(hitA.mPoint, hitB.mPoint, Limits::Small)) {
442#if DEBUG_PROCESS_RAY
443                cout<<"I2 ";
444#endif
445          return 0;
446        }
447       
448        const bool validA = ValidateRay(simpleRay.mOrigin, simpleRay.mDirection, box, hitA);
449        const bool validB = //castDoubleRay &&
450          ValidateRay(simpleRay.mOrigin, -simpleRay.mDirection, box, hitB);
451       
452       
453#if DEBUG_RAYCAST
454        Debug<<"PR1"<<flush;
455#endif
456       
457        // reset both contributions
458        if (!validA || !validB) {
459          if (pruneInvalidRays)
460                return 0;
461
462#if DEBUG_PROCESS_RAY
463                cout<<"I2 ";
464#endif
465
466          // reset both contributions of this ray
467          hitA.mObject = NULL;
468          hitB.mObject = NULL;
469        }
470       
471        // 8.11. 2007 JB
472        // degenerate rays checked by geometrical constraint...
473        //      !pruneInvalidRays || (hitA.mObject != hitB.mObject);
474
475       
476#if DEBUG_RAYCAST
477        Debug<<"PR2"<<flush;
478#endif
479
480        // VH - I do not know what this is for, commented out temporarily
481        // !!!!!!!!!!!!!! !!!!!!!!!!!! !!!!!!!!!!
482#if 1
483        const bool validSample = true;
484        if (validSample) {
485          Vector3 clipA, clipB;
486          if (!ClipToViewSpaceBox(hitA.mPoint,
487                                                          hitB.mPoint,
488                                                          clipA,
489                                                          clipB)) {
490#if DEBUG_PROCESS_RAY
491                cout<<"I3 ";
492#endif
493
494                return 0;
495          }
496
497          if (!pruneInvalidRays || hitA.mObject) {
498
499                  VssRay *vssRay =
500                          RequestRay(!castDoubleRay ? simpleRay.mOrigin : clipB,
501                                                 hitA.mPoint,
502                                                 hitB.mObject,
503                                                 hitA.mObject,
504                                                 mPreprocessor.mPass,
505                                                 1.0f //simpleRay.mPdf
506                                                 );
507
508                if (validA)
509                  vssRay->mFlags |= VssRay::Valid;
510               
511                vssRay->mDistribution = simpleRay.mDistribution;
512                vssRay->mGeneratorId = simpleRay.mGeneratorId;
513
514                vssRays.push_back(vssRay);
515                ++ hits;
516                //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl;
517        }
518
519#if DEBUG_RAYCAST
520        Debug<<"PR3"<<flush;
521#endif
522
523        if (castDoubleRay && (!pruneInvalidRays || hitB.mObject))
524        {
525                VssRay *vssRay = RequestRay(
526                                            clipA,
527                                            hitB.mPoint,
528                                            hitA.mObject,
529                                            hitB.mObject,
530                                            mPreprocessor.mPass,
531                                            1.0f //simpleRay.mPdf
532                                            );
533
534                if (validB)
535                        vssRay->mFlags |= VssRay::Valid;
536
537                vssRay->mDistribution = simpleRay.mDistribution;
538                vssRay->mGeneratorId = simpleRay.mGeneratorId;
539                vssRays.push_back(vssRay);
540                ++ hits;
541                //cout << "vssray 2: " << *vssRay << endl;
542        }
543#if DEBUG_RAYCAST
544          Debug<<"PR4"<<flush;
545#endif
546        } // validSample
547#else
548        // Just pass if intersected or not
549        hits = (hitA.mObject != 0) ? 1 : 0;
550        intersect = hitA;
551#endif 
552       
553        return hits;
554}
555
556
557void
558RayCaster::CastRays(
559                    SimpleRayContainer &rays,
560                    VssRayContainer &vssRays,
561                    const AxisAlignedBox3 &sbox,
562                    const bool castDoubleRay,
563                    const bool pruneInvalidRays )
564{
565  SimpleRayContainer::const_iterator rit, rit_end = rays.end();
566 
567  for (rit = rays.begin(); rit != rit_end; ++ rit) {
568   
569    CastRay(
570            *rit,                               
571            vssRays,
572            sbox,
573            castDoubleRay,
574            pruneInvalidRays);
575        }
576}
577 
578
579}
Note: See TracBrowser for help on using the repository browser.