From 125c96c25fb9d84d7cd07648d105e0efbaa661e6 Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sat, 17 Jul 2021 17:40:35 -0700 Subject: [PATCH] transformations: implement view_transform. --- rtchallenge/src/lib.rs | 1 + rtchallenge/src/transformations.rs | 59 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 rtchallenge/src/transformations.rs diff --git a/rtchallenge/src/lib.rs b/rtchallenge/src/lib.rs index d69dec1..f4ff091 100644 --- a/rtchallenge/src/lib.rs +++ b/rtchallenge/src/lib.rs @@ -5,6 +5,7 @@ pub mod materials; pub mod matrices; pub mod rays; pub mod spheres; +pub mod transformations; pub mod tuples; pub mod world; diff --git a/rtchallenge/src/transformations.rs b/rtchallenge/src/transformations.rs new file mode 100644 index 0000000..b0963da --- /dev/null +++ b/rtchallenge/src/transformations.rs @@ -0,0 +1,59 @@ +use crate::{ + matrices::Matrix4x4, + tuples::{cross, Tuple}, +}; + +/// 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()); + let true_up = cross(left, forward); + Matrix4x4::new( + [left.x, left.y, left.z, 0.], + [true_up.x, true_up.y, true_up.z, 0.], + [-forward.x, -forward.y, -forward.z, 0.], + [0., 0., 0., 1.], + ) * Matrix4x4::translation(-from.x, -from.y, -from.z) +}