diff --git a/rtchallenge/src/transformations.rs b/rtchallenge/src/transformations.rs index b0963da..e91b5e1 100644 --- a/rtchallenge/src/transformations.rs +++ b/rtchallenge/src/transformations.rs @@ -5,47 +5,6 @@ use crate::{ /// Create a matrix representing a eye at `from` looking at `to`, with an `up` /// as the up vector. -/// -/// # Examples -/// ``` -/// use rtchallenge::{matrices::Matrix4x4, transformations::view_transform, tuples::Tuple}; -/// -/// // The transofrmation matrix for the default orientation. -/// let from = Tuple::point(0., 0., 0.); -/// let to = Tuple::point(0., 0., -1.); -/// let up = Tuple::vector(0., 1., 0.); -/// let t = view_transform(from, to, up); -/// assert_eq!(t, Matrix4x4::identity()); -/// -/// // A view transformation matrix looking in positive z direction. -/// let from = Tuple::point(0., 0., 0.); -/// let to = Tuple::point(0., 0., 1.); -/// let up = Tuple::vector(0., 1., 0.); -/// let t = view_transform(from, to, up); -/// assert_eq!(t, Matrix4x4::scaling(-1., 1., -1.)); -/// -/// // The view tranformation moves the world. -/// let from = Tuple::point(0., 0., 8.); -/// let to = Tuple::point(0., 0., 0.); -/// let up = Tuple::vector(0., 1., 0.); -/// let t = view_transform(from, to, up); -/// assert_eq!(t, Matrix4x4::translation(0., 0., -8.)); -/// -/// // An arbitrary view transformation. -/// let from = Tuple::point(1., 3., 2.); -/// let to = Tuple::point(4., -2., 8.); -/// let up = Tuple::vector(1., 1., 0.); -/// let t = view_transform(from, to, up); -/// assert_eq!( -/// t, -/// Matrix4x4::new( -/// [-0.50709, 0.50709, 0.67612, -2.36643], -/// [0.76772, 0.60609, 0.12122, -2.82843], -/// [-0.35857, 0.59761, -0.71714, 0.], -/// [0., 0., 0., 1.], -/// ) -/// ); -/// ``` pub fn view_transform(from: Tuple, to: Tuple, up: Tuple) -> Matrix4x4 { let forward = (to - from).normalize(); let left = cross(forward, up.normalize()); @@ -57,3 +16,56 @@ pub fn view_transform(from: Tuple, to: Tuple, up: Tuple) -> Matrix4x4 { [0., 0., 0., 1.], ) * Matrix4x4::translation(-from.x, -from.y, -from.z) } + +#[cfg(test)] +mod tests { + use crate::{ + matrices::{identity, scaling, translation, Matrix4x4}, + transformations::view_transform, + tuples::{point, vector}, + }; + #[test] + fn default_orientation() { + // The transformation matrix for the default orientation. + let from = point(0., 0., 0.); + let to = point(0., 0., -1.); + let up = vector(0., 1., 0.); + let t = view_transform(from, to, up); + assert_eq!(t, identity()); + } + #[test] + fn looking_positive_z() { + // A view transformation matrix looking in positive z direction. + let from = point(0., 0., 0.); + let to = point(0., 0., 1.); + let up = vector(0., 1., 0.); + let t = view_transform(from, to, up); + assert_eq!(t, scaling(-1., 1., -1.)); + } + #[test] + fn transformation_moves_world() { + // The view transformation moves the world. + let from = point(0., 0., 8.); + let to = point(0., 0., 0.); + let up = vector(0., 1., 0.); + let t = view_transform(from, to, up); + assert_eq!(t, translation(0., 0., -8.)); + } + #[test] + fn arbitrary_view() { + // An arbitrary view transformation. + let from = point(1., 3., 2.); + let to = point(4., -2., 8.); + let up = vector(1., 1., 0.); + let t = view_transform(from, to, up); + assert_eq!( + t, + Matrix4x4::new( + [-0.50709, 0.50709, 0.67612, -2.36643], + [0.76772, 0.60609, 0.12122, -2.82843], + [-0.35857, 0.59761, -0.71714, 0.], + [0., 0., 0., 1.], + ) + ); + } +}