00001 #if !defined(raytrace_h__INCLUDED_)
00002 #define raytrace_h__INCLUDED_
00003
00004 #include <math.h>
00005
00007
00008
00010
00011
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
00024
00025 inline int intersect_triangle(double orig[3], double dir[3],
00026
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;
00033
00034
00035 CROSS(pvec, dir, edge2);
00036
00037
00038 det = DOT(edge1, pvec);
00039
00040 if (det > EPSILON)
00041 {
00042
00043 SUB(tvec, orig, vert0);
00044
00045
00046 *u = DOT(tvec, pvec);
00047 if (*u < 0.0 || *u > det)
00048 return 0;
00049
00050
00051 CROSS(qvec, tvec, edge1);
00052
00053
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
00062 SUB(tvec, orig, vert0);
00063
00064
00065 *u = DOT(tvec, pvec);
00066 if (*u > 0.0 || *u < det)
00067 return 0;
00068
00069
00070 CROSS(qvec, tvec, edge1);
00071
00072
00073 *v = DOT(dir, qvec) ;
00074 if (*v > 0.0 || *u + *v < det)
00075 return 0;
00076 }
00077 else return 0;
00078
00079
00080 *t = DOT(edge2, qvec) / det;
00081
00082 return 1;
00083 }
00084
00085
00086
00087 inline int intersect_triangle_backup(double orig[3], double dir[3],
00088
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;
00094
00095
00096 SUB(edge1, vert1, vert0);
00097 SUB(edge2, vert2, vert0);
00098
00099
00100 CROSS(pvec, dir, edge2);
00101
00102
00103 det = DOT(edge1, pvec);
00104
00105 if (det > EPSILON)
00106 {
00107
00108 SUB(tvec, orig, vert0);
00109
00110
00111 *u = DOT(tvec, pvec);
00112 if (*u < 0.0 || *u > det)
00113 return 0;
00114
00115
00116 CROSS(qvec, tvec, edge1);
00117
00118
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
00127 SUB(tvec, orig, vert0);
00128
00129
00130 *u = DOT(tvec, pvec);
00131 if (*u > 0.0 || *u < det)
00132 return 0;
00133
00134
00135 CROSS(qvec, tvec, edge1);
00136
00137
00138 *v = DOT(dir, qvec) ;
00139 if (*v > 0.0 || *u + *v < det)
00140 return 0;
00141 }
00142 else return 0;
00143
00144
00145
00146
00147
00148 *t = DOT(edge2, qvec) / det;
00149
00150
00151
00152 return 1;
00153 }
00154
00155
00156
00157
00158
00159
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
00169 SUB(edge1, vert1, vert0);
00170 SUB(edge2, vert2, vert0);
00171
00172
00173 SUB(tvec, orig, vert0);
00174
00175
00176 CROSS(pvec, dir, edge2);
00177
00178
00179 det = DOT(edge1, pvec);
00180
00181
00182 if (det > -EPSILON && det < EPSILON)
00183
00184 goto trysecond;
00185 inv_det = 1 / det;
00186
00187
00188 utemp = DOT(tvec, pvec);
00189 *u = utemp * inv_det;
00190 if (*u < 0.0 || *u > 1.0)
00191 goto trysecond;
00192
00193
00194 CROSS(qvec, tvec, edge1);
00195
00196
00197 *v = DOT(dir, qvec) * inv_det;
00198 if (*v < 0.0 || *u + *v > 1.0)
00199 goto trysecond;
00200
00201
00202 *t = DOT(edge2, qvec) * inv_det;
00203
00204 return 1;
00205
00206 trysecond:
00207
00208
00209 SUB(edge3, vert3, vert0);
00210 det = DOT (edge3,pvec);
00211
00212
00213
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
00223 CROSS(qvec, tvec, edge3);
00224
00225
00226 *v = DOT(dir, qvec) * inv_det;
00227 if (*v < 0.0 || *u + *v > 1.0)
00228 return 0;
00229
00230
00231 *t = DOT(edge2, qvec) * inv_det;
00232 return 1;
00233
00234 }
00235
00236
00237
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
00247 SUB(edge1, vert1, vert0);
00248 SUB(edge2, vert2, vert0);
00249
00250
00251 CROSS(pvec, dir, edge2);
00252
00253
00254 det = DOT(edge1, pvec);
00255
00256
00257 if (det > -EPSILON && det < EPSILON)
00258
00259 return 0;
00260 inv_det = 1 / det;
00261
00262
00263 SUB(tvec, orig, vert0);
00264
00265
00266 utemp = DOT(tvec, pvec);
00267 *u = utemp * inv_det;
00268 if (*u < 0.0 || *u > 1.0)
00269 goto trysecond;
00270
00271
00272 CROSS(qvec, tvec, edge1);
00273
00274
00275 *v = DOT(dir, qvec) * inv_det;
00276 if (*v < 0.0 || *u + *v > 1.0)
00277 goto trysecond;
00278
00279
00280 *t = DOT(edge2, qvec) * inv_det;
00281
00282 return 1;
00283
00284 trysecond:
00285
00286
00287 SUB(edge3, vert3, vert0);
00288 det = DOT (edge3,pvec);
00289
00290
00291
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
00301 CROSS(qvec, tvec, edge3);
00302
00303
00304 *v = DOT(dir, qvec) * inv_det;
00305 if (*v < 0.0 || *u + *v > 1.0)
00306 return 0;
00307
00308
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
00358
00359
00360
00361
00362
00363
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