diff --git a/features/src/transformations.rs b/features/src/transformations.rs index 9fb1bef..e07446e 100644 --- a/features/src/transformations.rs +++ b/features/src/transformations.rs @@ -48,6 +48,15 @@ impl Matrix { [0.0, 0.0, 0.0, 1.0], ]) } + + pub fn shearing(xy: f32, xz: f32, yx: f32, yz: f32, zx: f32, zy: f32) -> Self { + Matrix::from_array([ + [1.0, xy, xz, 0.0], + [ yx, 1.0, yz, 0.0], + [ zx, zy, 1.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + ]) + } } #[cfg(test)] @@ -157,4 +166,44 @@ mod tests { assert_eq!(&half_quarter * &p, Tuple::point(-1.0 * sqrt_of_2() / 2.0, sqrt_of_2() / 2.0, 0.0)); assert_eq!(&full_quarter * &p, Tuple::point(-1.0, 0.0, 0.0)); } + + #[test] + fn shearing_transform_moves_x_in_proportion_to_y() { + let transform = Matrix::shearing(1.0, 0.0, 0.0, 0.0, 0.0, 0.0); + let p = Tuple::point(2.0, 3.0, 4.0); + + assert_eq!(&transform * &p, Tuple::point(5.0, 3.0, 4.0)); + } + + #[test] + fn shearing_transform_moves_x_in_proportion_to_z() { + let transform = Matrix::shearing(0.0, 1.0, 0.0, 0.0, 0.0, 0.0); + let p = Tuple::point(2.0, 3.0, 4.0); + + assert_eq!(&transform * &p, Tuple::point(6.0, 3.0, 4.0)); + } + + #[test] + fn shearing_transform_moves_y_in_proportion_to_z() { + let transform = Matrix::shearing(0.0, 0.0, 0.0, 1.0, 0.0, 0.0); + let p = Tuple::point(2.0, 3.0, 4.0); + + assert_eq!(&transform * &p, Tuple::point(2.0, 7.0, 4.0)); + } + + #[test] + fn shearing_transform_moves_z_in_proportion_to_x() { + let transform = Matrix::shearing(0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + let p = Tuple::point(2.0, 3.0, 4.0); + + assert_eq!(&transform * &p, Tuple::point(2.0, 3.0, 6.0)); + } + + #[test] + fn shearing_transform_moves_z_in_proportion_to_y() { + let transform = Matrix::shearing(0.0, 0.0, 0.0, 0.0, 0.0, 1.0); + let p = Tuple::point(2.0, 3.0, 4.0); + + assert_eq!(&transform * &p, Tuple::point(2.0, 3.0, 7.0)); + } }