basic/geometry/geo_rangesensor/raytrace.h

Go to the documentation of this file.
00001 #if !defined(raytrace_h__INCLUDED_)
00002 #define raytrace_h__INCLUDED_
00003 
00004 #include <math.h>
00005 
00007 // Code has been placed in this .h file because it seems to be
00008 // necesscary in order to make the functions inline.
00010 
00011 //since we're using floats, we may need a larger factor than 0.000001
00012 #define EPSILON 0.000001
00013 #define CROSS(dest,v1,v2) \
00014   dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
00015   dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
00016 dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
00017 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
00018 #define SUB(dest,v1,v2) \
00019   dest[0]=v1[0]-v2[0]; \
00020   dest[1]=v1[1]-v2[1]; \
00021 dest[2]=v1[2]-v2[2]; 
00022 
00023 /* code rewritten to do tests on the sign of the determinant */
00024 /* the division is at the end in the code                    */
00025 inline int intersect_triangle(double orig[3], double dir[3],
00026 //                      Vector4 vert0, Vector4 vert1, Vector4  vert2,
00027                         double vert0[3], double vert1[3], double vert2[3],
00028                         double edge1[3], double edge2[3],
00029                         double *t, double *u, double *v)
00030 {
00031    double tvec[3], pvec[3], qvec[3];
00032    double det; //,inv_det;
00033 
00034    /* begin calculating determinant - also used to calculate U parameter */
00035    CROSS(pvec, dir, edge2);
00036 
00037    /* if determinant is near zero, ray lies in plane of triangle */
00038    det = DOT(edge1, pvec);
00039 
00040    if (det > EPSILON)
00041    {
00042       /* calculate distance from vert0 to ray origin */
00043       SUB(tvec, orig, vert0);
00044       
00045       /* calculate U parameter and test bounds */
00046       *u = DOT(tvec, pvec);
00047       if (*u < 0.0 || *u > det)
00048          return 0;
00049       
00050       /* prepare to test V parameter */
00051       CROSS(qvec, tvec, edge1);
00052       
00053       /* calculate V parameter and test bounds */
00054       *v = DOT(dir, qvec);
00055       if (*v < 0.0 || *u + *v > det)
00056          return 0;
00057       
00058    }
00059    else if(det < -EPSILON)
00060    {
00061       /* calculate distance from vert0 to ray origin */
00062       SUB(tvec, orig, vert0);
00063       
00064       /* calculate U parameter and test bounds */
00065       *u = DOT(tvec, pvec);
00066       if (*u > 0.0 || *u < det)
00067          return 0;
00068       
00069       /* prepare to test V parameter */
00070       CROSS(qvec, tvec, edge1);
00071       
00072       /* calculate V parameter and test bounds */
00073       *v = DOT(dir, qvec) ;
00074       if (*v > 0.0 || *u + *v < det)
00075          return 0;
00076    }
00077    else return 0;  /* ray is parallell to the plane of the triangle */
00078 
00079    /* calculate t, ray intersects triangle */
00080    *t = DOT(edge2, qvec) / det;
00081 
00082    return 1;
00083 }
00084 
00085 /* code rewritten to do tests on the sign of the determinant */
00086 /* the division is at the end in the code                    */
00087 inline int intersect_triangle_backup(double orig[3], double dir[3],
00088 //                      Vector4 vert0, Vector4 vert1, Vector4  vert2,
00089                         double vert0[3], double vert1[3], double vert2[3],
00090                         double *t, double *u, double *v)
00091 {
00092    double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
00093    double det; //,inv_det;
00094 
00095    /* find vectors for two edges sharing vert0 */
00096    SUB(edge1, vert1, vert0);
00097    SUB(edge2, vert2, vert0);
00098 
00099    /* begin calculating determinant - also used to calculate U parameter */
00100    CROSS(pvec, dir, edge2);
00101 
00102    /* if determinant is near zero, ray lies in plane of triangle */
00103    det = DOT(edge1, pvec);
00104 
00105    if (det > EPSILON)
00106    {
00107       /* calculate distance from vert0 to ray origin */
00108       SUB(tvec, orig, vert0);
00109       
00110       /* calculate U parameter and test bounds */
00111       *u = DOT(tvec, pvec);
00112       if (*u < 0.0 || *u > det)
00113          return 0;
00114       
00115       /* prepare to test V parameter */
00116       CROSS(qvec, tvec, edge1);
00117       
00118       /* calculate V parameter and test bounds */
00119       *v = DOT(dir, qvec);
00120       if (*v < 0.0 || *u + *v > det)
00121          return 0;
00122       
00123    }
00124    else if(det < -EPSILON)
00125    {
00126       /* calculate distance from vert0 to ray origin */
00127       SUB(tvec, orig, vert0);
00128       
00129       /* calculate U parameter and test bounds */
00130       *u = DOT(tvec, pvec);
00131       if (*u > 0.0 || *u < det)
00132          return 0;
00133       
00134       /* prepare to test V parameter */
00135       CROSS(qvec, tvec, edge1);
00136       
00137       /* calculate V parameter and test bounds */
00138       *v = DOT(dir, qvec) ;
00139       if (*v > 0.0 || *u + *v < det)
00140          return 0;
00141    }
00142    else return 0;  /* ray is parallell to the plane of the triangle */
00143 
00144 
00145    //inv_det = 1.0 / det;
00146 
00147    /* calculate t, ray intersects triangle */
00148    *t = DOT(edge2, qvec) / det; // * inv_det;
00149    //(*u) *= inv_det;
00150    //(*v) *= inv_det;
00151 
00152    return 1;
00153 }
00154 
00155 
00156 // two triangles sharing the 4 ccw points vert0, vert1, vert2, vert3.
00157 // where:
00158 //   vert0, vert2 are the "wing" points,
00159 //   vert1, vert3 form the axis connecting the wings
00160 inline int
00161 intersect_4pt(double orig[3], double dir[3],
00162                    double vert0[3], double vert1[3], double vert2[3], double vert3[3],
00163                    double *t, double *u, double *v)
00164 {
00165   double edge1[3], edge2[3], edge3[3], tvec[3], pvec[3], qvec[3];
00166   double det,inv_det,utemp;
00167   
00168   /* find vectors for two edges sharing vert0 */
00169   SUB(edge1, vert1, vert0);
00170   SUB(edge2, vert2, vert0);
00171   
00172   /* calculate distance from vert0 to ray origin */
00173   SUB(tvec, orig, vert0);
00174   
00175   /* begin calculating determinant - also used to calculate U parameter */
00176   CROSS(pvec, dir, edge2);
00177   
00178   /* if determinant is near zero, ray lies in plane of triangle */
00179   det = DOT(edge1, pvec);
00180   
00181   /* the non-culling branch */
00182   if (det > -EPSILON && det < EPSILON)
00183     /*in case triangles 1 and 2 aren't on same plane, but still share edge2*/
00184     goto trysecond;
00185   inv_det = 1 / det;
00186   
00187   /* calculate U parameter and test bounds */
00188   utemp = DOT(tvec, pvec);
00189   *u = utemp * inv_det;
00190   if (*u < 0.0 || *u > 1.0)
00191     goto trysecond;
00192   
00193   /* prepare to test V parameter */
00194   CROSS(qvec, tvec, edge1);
00195   
00196   /* calculate V parameter and test bounds */
00197   *v = DOT(dir, qvec) * inv_det;
00198   if (*v < 0.0 || *u + *v > 1.0)
00199     goto trysecond;
00200   
00201   /* calculate t, ray intersects triangle */
00202   *t = DOT(edge2, qvec) * inv_det;
00203 
00204   return 1;
00205 
00206   trysecond:
00207 
00208   /* begin testing for 4th point (vert3)*/
00209   SUB(edge3, vert3, vert0);
00210   det = DOT (edge3,pvec);
00211 
00212   /* the non-culling branch */
00213   /*in case triangles 1 and 2 aren't on same plane, but still share edge2*/
00214   if (det > -EPSILON && det < EPSILON) 
00215     return 0;
00216   inv_det = 1 / det;
00217 
00218   *u = utemp * inv_det;
00219   if (*u < 0.0 || *u > 1.0)
00220     return 0;
00221 
00222   /* prepare to test V parameter */
00223   CROSS(qvec, tvec, edge3);
00224   
00225   /* calculate V parameter and test bounds */
00226   *v = DOT(dir, qvec) * inv_det;
00227   if (*v < 0.0 || *u + *v > 1.0)
00228     return 0;
00229   
00230   /* calculate t, ray intersects 4pt object */
00231   *t = DOT(edge2, qvec) * inv_det;
00232   return 1;
00233   
00234 }
00235 
00236 
00237 // two triangles on the same plane sharing the 4 ccw points vert0, vert1, vert2, vert3.
00238 inline int
00239 intersect_quad(double orig[3], double dir[3],
00240                    double vert0[3], double vert1[3], double vert2[3], double vert3[3],
00241                    double *t, double *u, double *v)
00242 {
00243   double edge1[3], edge2[3], edge3[3], tvec[3], pvec[3], qvec[3];
00244   double det,inv_det,utemp;
00245   
00246   /* find vectors for two edges sharing vert0 */
00247   SUB(edge1, vert1, vert0);
00248   SUB(edge2, vert2, vert0);
00249   
00250   /* begin calculating determinant - also used to calculate U parameter */
00251   CROSS(pvec, dir, edge2);
00252   
00253   /* if determinant is near zero, ray lies in plane of triangle */
00254   det = DOT(edge1, pvec);
00255   
00256   /* the non-culling branch */
00257   if (det > -EPSILON && det < EPSILON)
00258     /*we know the other triangle on same plane is also parallel to the eye ray*/
00259     return 0;
00260   inv_det = 1 / det;
00261   
00262   /* calculate distance from vert0 to ray origin */
00263   SUB(tvec, orig, vert0);
00264   
00265   /* calculate U parameter and test bounds */
00266   utemp = DOT(tvec, pvec);
00267   *u = utemp * inv_det;
00268   if (*u < 0.0 || *u > 1.0)
00269     goto trysecond;
00270   
00271   /* prepare to test V parameter */
00272   CROSS(qvec, tvec, edge1);
00273   
00274   /* calculate V parameter and test bounds */
00275   *v = DOT(dir, qvec) * inv_det;
00276   if (*v < 0.0 || *u + *v > 1.0)
00277     goto trysecond;
00278   
00279   /* calculate t, ray intersects triangle */
00280   *t = DOT(edge2, qvec) * inv_det;
00281 
00282   return 1;
00283 
00284   trysecond:
00285 
00286   /* begin testing for 4th point (vert3)*/
00287   SUB(edge3, vert3, vert0);
00288   det = DOT (edge3,pvec);
00289 
00290   /* the non-culling branch */
00291   /*in case triangles 1 and 2 aren't on same plane, but still share edge2*/
00292   if (det > -EPSILON && det < EPSILON) 
00293     return 0;
00294   inv_det = 1 / det;
00295 
00296   *u = utemp * inv_det;
00297   if (*u < 0.0 || *u > 1.0)
00298     return 0;
00299 
00300   /* prepare to test V parameter */
00301   CROSS(qvec, tvec, edge3);
00302   
00303   /* calculate V parameter and test bounds */
00304   *v = DOT(dir, qvec) * inv_det;
00305   if (*v < 0.0 || *u + *v > 1.0)
00306     return 0;
00307   
00308   /* calculate t, ray intersects 4pt object */
00309   *t = DOT(edge2, qvec) * inv_det;
00310   return 1;
00311   
00312 }
00313 
00315 
00316 inline int
00317 intersect_sphere(double loc[3], double dir[3], double center[3], double radius, 
00318                                                                  double& t, double maxt)
00319 {
00320         double b, c, d;
00321         double t1, t2;
00322         double diff[3];
00323         
00324         diff[0] = center[0] - loc[0];
00325         diff[1] = center[1] - loc[1];
00326         diff[2] = center[2] - loc[2];
00327         
00328         c = DOT(diff, diff) - radius*radius;
00329         b = -2 * DOT(diff, dir);
00330         d = b*b - 4*c;
00331         
00332         if (d <= 0)
00333                 return 0;
00334 
00335         d = (double) sqrt(d);
00336         t1 = (-b+d)/2;
00337         t2 = (-b-d)/2;
00338         
00339         if (t1 < EPSILON || t1 >= maxt)
00340                 t1 = -1;
00341         if (t2 < EPSILON || t2 >= maxt)
00342                 t2 = -1;
00343         if (t1 < 0) {
00344                 if (t2 < 0)
00345       return 0;
00346                 t = t2;
00347         }
00348         else {
00349                 if (t2 < 0)
00350       t = t1;
00351                 else
00352       t = (t1 < t2) ? t1 : t2;
00353         }
00354         return (t > EPSILON);
00355 }
00356 
00357 /*inline void normalize (double & a, double & b, double & c)
00358 {
00359   double x;
00360   x = (double)sqrt(1/( (a)*(a)+(b)*(b)+(c)*(c) ));
00361   a = a * x;
00362   b = b * x;
00363   c = c * x;
00364 }*/
00365 
00366 inline void normalize (double & a, double & b, double & c)
00367 {
00368   double x;
00369   x = (double)sqrt(1/( (a)*(a)+(b)*(b)+(c)*(c) ));
00370   a = a * x;
00371   b = b * x;
00372   c = c * x;
00373 }
00374 
00375 #endif

Generated on Sat Apr 1 21:30:32 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO