use crate::matrix::Matrix; use crate::structs::Tuple; impl Matrix { pub fn translation(x: f32, y: f32, z: f32) -> Self { Matrix::from_array([ [1.0, 0.0, 0.0, x ], [0.0, 1.0, 0.0, y ], [0.0, 0.0, 1.0, z ], [0.0, 0.0, 0.0, 1.0], ]) } pub fn scaling(x: f32, y: f32, z: f32) -> Self { Matrix::from_array([ [ x, 0.0, 0.0, 0.0], [0.0, y, 0.0, 0.0], [0.0, 0.0, z, 0.0], [0.0, 0.0, 0.0, 1.0], ]) } } #[cfg(test)] mod tests { use super::*; #[test] fn multiply_by_a_translations_matrix() { let transform = Matrix::translation(5.0, -3.0, 2.0); let p = Tuple::point(-3.0, 4.0, 5.0); let expected_point = Tuple::point(2.0, 1.0, 7.0); let translated_point = &p * &transform; assert_eq!(expected_point, translated_point); } #[test] fn multiply_by_the_inverse_of_a_translation_matrix() { let transform = Matrix::translation(5.0, -3.0, 2.0); let inv = transform.inverse(); let p = Tuple::point(-3.0, 4.0, 5.0); let expected_point = Tuple::point(-8.0, 7.0, 3.0); assert_eq!(&inv * &p, expected_point); } #[test] fn translation_does_not_affect_vectors() { let transform = Matrix::translation(5.0, -3.0, 2.0); let v = Tuple::vector(-3.0, 4.0, 5.0); assert_eq!(&transform * &v, v); } #[test] fn scaling_matrix_applied_to_point() { let transform = Matrix::scaling(2.0, 3.0, 4.0); let p = Tuple::point(-4.0, 6.0, 8.0); let expected = Tuple::point(-8.0, 18.0, 32.0); assert_eq!(&transform * &p, expected); } #[test] fn scaling_matrix_apled_to_vector() { let transform = Matrix::scaling(2.0, 3.0, 4.0); let v = Tuple::vector(-4.0, 6.0, 8.0); assert_eq!(&transform * &v, Tuple::vector(-8.0, 18.0, 32.0)); } #[test] fn multiplying_inverse_of_scaling_matrix() { let transform = Matrix::scaling(2.0, 3.0, 4.0); let inv = transform.inverse(); let v = Tuple::vector(-4.0, 6.0, 8.0); assert_eq!(&inv * &v, Tuple::vector(-2.0, 2.0, 2.0)); } #[test] fn reflection_is_scaling_by_a_negative_value() { let transform = Matrix::scaling(-1.0, 1.0, 1.0); let p = Tuple::point(2.0, 3.0, 4.0); assert_eq!(&transform * &p, Tuple::point(-2.0, 3.0, 4.0)); } }