( ray: Ray, v0: Vec3, v1: Vec3, v2: Vec3, )
| 398 | // Ray-triangle intersection (Moller-Trumbore algorithm) |
| 399 | |
| 400 | export function rayIntersectsTriangle( |
| 401 | ray: Ray, v0: Vec3, v1: Vec3, v2: Vec3, |
| 402 | ): RayHit { |
| 403 | const EPSILON = 1e-8; |
| 404 | const edge1: Vec3 = { x: v1.x - v0.x, y: v1.y - v0.y, z: v1.z - v0.z }; |
| 405 | const edge2: Vec3 = { x: v2.x - v0.x, y: v2.y - v0.y, z: v2.z - v0.z }; |
| 406 | const h = vec3Cross(ray.direction, edge2); |
| 407 | const a = vec3Dot(edge1, h); |
| 408 | const noHit: RayHit = { hit: false, distance: 0, point: { x: 0, y: 0, z: 0 }, normal: { x: 0, y: 0, z: 0 } }; |
| 409 | if (a > -EPSILON && a < EPSILON) return noHit; |
| 410 | const f = 1.0 / a; |
| 411 | const s: Vec3 = { x: ray.position.x - v0.x, y: ray.position.y - v0.y, z: ray.position.z - v0.z }; |
| 412 | const u = f * vec3Dot(s, h); |
| 413 | if (u < 0.0 || u > 1.0) return noHit; |
| 414 | const q = vec3Cross(s, edge1); |
| 415 | const v = f * vec3Dot(ray.direction, q); |
| 416 | if (v < 0.0 || u + v > 1.0) return noHit; |
| 417 | const t = f * vec3Dot(edge2, q); |
| 418 | if (t <= EPSILON) return noHit; |
| 419 | const point: Vec3 = { |
| 420 | x: ray.position.x + ray.direction.x * t, |
| 421 | y: ray.position.y + ray.direction.y * t, |
| 422 | z: ray.position.z + ray.direction.z * t, |
| 423 | }; |
| 424 | const normal = vec3Normalize(vec3Cross(edge1, edge2)); |
| 425 | return { hit: true, distance: t, point, normal }; |
| 426 | } |
| 427 | |
| 428 | export function getRayCollisionBox(ray: Ray, box_: BoundingBox): RayHit { |
| 429 | const noHit: RayHit = { hit: false, distance: 0, point: { x: 0, y: 0, z: 0 }, normal: { x: 0, y: 0, z: 0 } }; |
no test coverage detected