From d3eead53cf69abcfb8f45e135314823c25f0e6d2 Mon Sep 17 00:00:00 2001 From: tolelom <98kimsungmin@naver.com> Date: Wed, 25 Mar 2026 10:45:06 +0900 Subject: [PATCH] feat(math): add Ray type with direction normalization --- crates/voltex_math/src/lib.rs | 2 ++ crates/voltex_math/src/ray.rs | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 crates/voltex_math/src/ray.rs diff --git a/crates/voltex_math/src/lib.rs b/crates/voltex_math/src/lib.rs index a45c9ff..afda285 100644 --- a/crates/voltex_math/src/lib.rs +++ b/crates/voltex_math/src/lib.rs @@ -3,9 +3,11 @@ pub mod vec3; pub mod vec4; pub mod mat4; pub mod aabb; +pub mod ray; pub use vec2::Vec2; pub use vec3::Vec3; pub use vec4::Vec4; pub use mat4::Mat4; pub use aabb::AABB; +pub use ray::Ray; diff --git a/crates/voltex_math/src/ray.rs b/crates/voltex_math/src/ray.rs new file mode 100644 index 0000000..a6b1ee8 --- /dev/null +++ b/crates/voltex_math/src/ray.rs @@ -0,0 +1,46 @@ +use crate::Vec3; + +#[derive(Debug, Clone, Copy)] +pub struct Ray { + pub origin: Vec3, + pub direction: Vec3, +} + +impl Ray { + pub fn new(origin: Vec3, direction: Vec3) -> Self { + Self { + origin, + direction: direction.normalize(), + } + } + + pub fn at(&self, t: f32) -> Vec3 { + self.origin + self.direction * t + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn approx(a: f32, b: f32) -> bool { + (a - b).abs() < 1e-5 + } + + fn approx_vec(a: Vec3, b: Vec3) -> bool { + approx(a.x, b.x) && approx(a.y, b.y) && approx(a.z, b.z) + } + + #[test] + fn test_new_normalizes_direction() { + let r = Ray::new(Vec3::ZERO, Vec3::new(3.0, 0.0, 0.0)); + assert!(approx_vec(r.direction, Vec3::X)); + } + + #[test] + fn test_at() { + let r = Ray::new(Vec3::new(1.0, 2.0, 3.0), Vec3::X); + let p = r.at(5.0); + assert!(approx_vec(p, Vec3::new(6.0, 2.0, 3.0))); + } +}