diff --git a/features/src/transformations.rs b/features/src/transformations.rs index 01f9e57..ce43d6e 100644 --- a/features/src/transformations.rs +++ b/features/src/transformations.rs @@ -1,3 +1,4 @@ +use std::f32::consts::PI; use crate::matrix::Matrix; use crate::structs::Tuple; @@ -20,6 +21,15 @@ impl Matrix { [0.0, 0.0, 0.0, 1.0], ]) } + + pub fn rotation_x(r: f32) -> Self { + Matrix::from_array([ + [1.0 , 0.0, 0.0, 0.0], + [0.0, r.cos(), -1.0 * r.sin(), 0.0], + [0.0, r.sin(), r.cos() , 0.0], + [0.0, 0.0, 0.0, 1.0], + ]) + } } #[cfg(test)] @@ -86,4 +96,27 @@ mod tests { let p = Tuple::point(2.0, 3.0, 4.0); assert_eq!(&transform * &p, Tuple::point(-2.0, 3.0, 4.0)); } + + fn sqrt_of_2() -> f32 { + (2.0 as f32).sqrt() + } + + #[test] + fn rotating_a_point_around_the_x_axis() { + let p = Tuple::point(0.0, 1.0, 0.0); + let half_quarter = Matrix::rotation_x(PI / 4.0); + let full_quarter = Matrix::rotation_x(PI / 2.0); + + assert_eq!(&half_quarter * &p, Tuple::point(0.0, sqrt_of_2() / 2.0, sqrt_of_2() / 2.0)); + assert_eq!(&full_quarter * &p, Tuple::point(0.0, 0.0, 1.0)); + } + + #[test] + fn inverse_of_an_x_rotation_rotates_opposite_direction() { + let p = Tuple::point(0.0, 1.0, 0.0); + let half_quarter = Matrix::rotation_x(PI / 4.0); + let inv = half_quarter.inverse(); + + assert_eq!(&inv * &p, Tuple::point(0.0, sqrt_of_2() / 2.0, -1.0 * sqrt_of_2() / 2.0)); + } }