diff options
Diffstat (limited to 'pineapple.c')
| -rw-r--r-- | pineapple.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/pineapple.c b/pineapple.c index eeb112b..043904f 100644 --- a/pineapple.c +++ b/pineapple.c @@ -2,6 +2,7 @@ #include <endian.h> #include <errno.h> +#include <float.h> #include <getopt.h> #include <math.h> #include <stdint.h> @@ -75,19 +76,23 @@ vnorm(vec3 v) return (vec3){ v.x / mag, v.y / mag, v.z / mag }; } -float +static float ray_triangle_intersect(vec3 P, vec3 d, struct triangle tri) { - d = vnorm(d); - vec3 n = vnorm(tri.n); - vec3 A = tri.a, B = tri.b, C = tri.c; - if (dot(n, d) == 0.0) return NAN; - float t = (dot(n, A) - dot(n, P)) / dot(n, d); - vec3 Q = vadd(P, smul(d, t)); - if (dot(cross(vsub(B, A), vsub(Q, A)), n) >= 0.0 && - dot(cross(vsub(C, B), vsub(Q, B)), n) >= 0.0 && - dot(cross(vsub(A, C), vsub(Q, C)), n) >= 0.0) - return t; + vec3 edge1 = vsub(tri.b, tri.a); + vec3 edge2 = vsub(tri.c, tri.a); + vec3 ray_cross_e2 = cross(d, edge2); + float det = dot(edge1, ray_cross_e2); + if (det > -FLT_EPSILON && det < FLT_EPSILON) return NAN; + float inv_det = 1.0 / det; + vec3 s = vsub(P, tri.a); + float u = inv_det * dot(s, ray_cross_e2); + if (u < 0.0 || u > 1.0) return NAN; + vec3 s_cross_e1 = cross(s, edge1); + float v = inv_det * dot(d, s_cross_e1); + if (v < 0.0 || u + v > 1.0) return NAN; + float t = -inv_det * dot(edge2, s_cross_e1); + if (t > FLT_EPSILON) return t; return NAN; } |
