From 9cf37cdc39fffbd13c73052ac3728c68bab5e402 Mon Sep 17 00:00:00 2001 From: btipling Date: Sat, 30 Dec 2023 14:48:39 -0800 Subject: [PATCH] Early return with null for a ray with no direction (#1132) --- src/math/ray.zig | 103 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/src/math/ray.zig b/src/math/ray.zig index 94564cb9..ae55533d 100644 --- a/src/math/ray.zig +++ b/src/math/ray.zig @@ -49,9 +49,10 @@ pub fn Ray(comptime Vec3P: type) type { } } else if (v[1] > v[2]) { return 1; - } else { - return 0; + } else if (v[2] > v[0]) { + return 2; } + return 0; } // Algorithm based on: @@ -76,6 +77,9 @@ pub fn Ray(comptime Vec3P: type) type { @abs(ray.direction.v[1]), @abs(ray.direction.v[2]), }); + if (ray.direction.v[kz] == 0.0) { + return null; + } var kx: u8 = kz + 1; if (kx == 3) kx = 0; @@ -353,3 +357,98 @@ test "triangleIntersect_precise_frontface_bc_hit_f64" { try testing.expect(f64, expected_w).eqlApprox(result.v[2], 1e-4); try testing.expect(f64, expected_t).eqlApprox(result.v[3], 1e-2); } + +test "triangleIntersect_ray_no_direction" { + const a: math.Vec3 = math.vec3(0, 0, 0); + const b: math.Vec3 = math.vec3(1, 0, 0); + const c: math.Vec3 = math.vec3(0, 1, 0); + const ray: math.Ray = math.Ray{ + .origin = math.vec3(0.1, 0.1, 1), + .direction = math.vec3(0.0, 0.0, 0.0), + }; + + const result = ray.triangleIntersect( + &a, + &b, + &c, + true, + ); + + try testing.expect(?math.Ray.Hit, null).eql(result); +} + +test "triangleIntersect_ray_no_x_y_direction" { + const a: math.Vec3 = math.vec3(-1, 1, 0); + const b: math.Vec3 = math.vec3(-1, -1, 0); + const c: math.Vec3 = math.vec3(1, -1, 0); + const ray: math.Ray = math.Ray{ + .origin = math.vec3(0.0, 0.0, 1), + .direction = math.vec3(0.0, 0.0, -1), + }; + + const result = ray.triangleIntersect( + &a, + &b, + &c, + true, + ).?; + + const expected_t: f64 = 1; + const expected_u: f64 = 0.3333; + const expected_v: f64 = 0.3333; + const expected_w: f64 = 0.3333; + try testing.expect(f64, expected_u).eqlApprox(result.v[0], 1e-4); + try testing.expect(f64, expected_v).eqlApprox(result.v[1], 1e-4); + try testing.expect(f64, expected_w).eqlApprox(result.v[2], 1e-4); + try testing.expect(f64, expected_t).eqlApprox(result.v[3], 1e-2); +} + +test "triangleIntersect_ray_no_y_z_direction" { + const a: math.Vec3 = math.vec3(0, -1, 1); + const b: math.Vec3 = math.vec3(0, -1, -1); + const c: math.Vec3 = math.vec3(0, 1, -1); + const ray: math.Ray = math.Ray{ + .origin = math.vec3(1, 0.0, 0.0), + .direction = math.vec3(-1, 0.0, 0.0), + }; + + const result = ray.triangleIntersect( + &a, + &b, + &c, + true, + ).?; + const expected_t: f64 = 1; + const expected_u: f64 = 0.3333; + const expected_v: f64 = 0.3333; + const expected_w: f64 = 0.3333; + try testing.expect(f64, expected_u).eqlApprox(result.v[0], 1e-4); + try testing.expect(f64, expected_v).eqlApprox(result.v[1], 1e-4); + try testing.expect(f64, expected_w).eqlApprox(result.v[2], 1e-4); + try testing.expect(f64, expected_t).eqlApprox(result.v[3], 1e-2); +} + +test "triangleIntersect_ray_no_x_z_direction" { + const a: math.Vec3 = math.vec3(-1, 0, 1); + const b: math.Vec3 = math.vec3(-1, 0, -1); + const c: math.Vec3 = math.vec3(1, 0, -1); + const ray: math.Ray = math.Ray{ + .origin = math.vec3(0.0, -1.0, 0.0), + .direction = math.vec3(0.0, 1.0, 0.0), + }; + + const result = ray.triangleIntersect( + &a, + &b, + &c, + true, + ).?; + const expected_t: f64 = 1; + const expected_u: f64 = 0.3333; + const expected_v: f64 = 0.3333; + const expected_w: f64 = 0.3333; + try testing.expect(f64, expected_u).eqlApprox(result.v[0], 1e-4); + try testing.expect(f64, expected_v).eqlApprox(result.v[1], 1e-4); + try testing.expect(f64, expected_w).eqlApprox(result.v[2], 1e-4); + try testing.expect(f64, expected_t).eqlApprox(result.v[3], 1e-2); +}