summaryrefslogtreecommitdiff
path: root/pineapple.c
diff options
context:
space:
mode:
Diffstat (limited to 'pineapple.c')
-rw-r--r--pineapple.c27
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;
}