transformations: implement view_transform.

This commit is contained in:
Bill Thiede 2021-07-17 17:40:35 -07:00
parent 249a2915d9
commit 125c96c25f
2 changed files with 60 additions and 0 deletions

View File

@ -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;

View File

@ -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)
}