matrices: implement Matrix4x4:rotation_[xyz]
This commit is contained in:
parent
f792d1a626
commit
245b02b443
@ -283,6 +283,117 @@ impl Matrix4x4 {
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix representing a rotation around the x-axis.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::f32::consts::PI;
|
||||
///
|
||||
/// use float_cmp::approx_eq;
|
||||
///
|
||||
/// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple};
|
||||
///
|
||||
/// // A scaling matrix applied to a point.
|
||||
/// let p = Tuple::point(0., 1., 0.);
|
||||
/// let half_quarter = Matrix4x4::rotation_x(PI / 4.);
|
||||
/// let full_quarter = Matrix4x4::rotation_x(PI / 2.);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// half_quarter * p,
|
||||
/// Tuple::point(0., 2_f32.sqrt() / 2., 2_f32.sqrt() / 2.)
|
||||
/// );
|
||||
/// assert!(approx_eq!(
|
||||
/// Tuple,
|
||||
/// full_quarter * p,
|
||||
/// Tuple::point(0., 0., 1.),
|
||||
/// epsilon = 0.0001
|
||||
/// ));
|
||||
/// ```
|
||||
pub fn rotation_x(radians: f32) -> Matrix4x4 {
|
||||
let r = radians;
|
||||
Matrix4x4::new(
|
||||
[1., 0., 0., 0.],
|
||||
[0., r.cos(), -r.sin(), 0.],
|
||||
[0., r.sin(), r.cos(), 0.],
|
||||
[0., 0., 0., 1.],
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix representing a rotation around the y-axis.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::f32::consts::PI;
|
||||
///
|
||||
/// use float_cmp::approx_eq;
|
||||
///
|
||||
/// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple};
|
||||
///
|
||||
/// // A scaling matrix applied to a point.
|
||||
/// let p = Tuple::point(0., 0., 1.);
|
||||
/// let half_quarter = Matrix4x4::rotation_y(PI / 4.);
|
||||
/// let full_quarter = Matrix4x4::rotation_y(PI / 2.);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// half_quarter * p,
|
||||
/// Tuple::point(2_f32.sqrt() / 2., 0., 2_f32.sqrt() / 2.)
|
||||
/// );
|
||||
/// assert!(approx_eq!(
|
||||
/// Tuple,
|
||||
/// full_quarter * p,
|
||||
/// Tuple::point(1., 0., 0.,),
|
||||
/// epsilon = 0.0001
|
||||
/// ));
|
||||
/// ```
|
||||
pub fn rotation_y(radians: f32) -> Matrix4x4 {
|
||||
let r = radians;
|
||||
Matrix4x4::new(
|
||||
[r.cos(), 0., r.sin(), 0.],
|
||||
[0., 1., 0., 0.],
|
||||
[-r.sin(), 0., r.cos(), 0.],
|
||||
[0., 0., 0., 1.],
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a 4x4 matrix representing a rotation around the z-axis.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::f32::consts::PI;
|
||||
///
|
||||
/// use float_cmp::approx_eq;
|
||||
///
|
||||
/// use rtchallenge::{matrices::Matrix4x4, tuples::Tuple};
|
||||
///
|
||||
/// // A scaling matrix applied to a point.
|
||||
/// let p = Tuple::point(0., 1., 0.);
|
||||
/// let half_quarter = Matrix4x4::rotation_z(PI / 4.);
|
||||
/// let full_quarter = Matrix4x4::rotation_z(PI / 2.);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// half_quarter * p,
|
||||
/// Tuple::point(-2_f32.sqrt() / 2., 2_f32.sqrt() / 2., 0.)
|
||||
/// );
|
||||
/// assert!(approx_eq!(
|
||||
/// Tuple,
|
||||
/// full_quarter * p,
|
||||
/// Tuple::point(-1., 0., 0.,),
|
||||
/// epsilon = 0.0001
|
||||
/// ));
|
||||
/// ```
|
||||
pub fn rotation_z(radians: f32) -> Matrix4x4 {
|
||||
let r = radians;
|
||||
Matrix4x4::new(
|
||||
[r.cos(), -r.sin(), 0., 0.],
|
||||
[r.sin(), r.cos(), 0., 0.],
|
||||
[0., 0., 1., 0.],
|
||||
[0., 0., 0., 1.],
|
||||
)
|
||||
}
|
||||
|
||||
/// Transpose self, returning a new matrix that has been reflected across the diagonal.
|
||||
/// # Examples
|
||||
///
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use std::ops::{Add, Div, Mul, Neg, Sub};
|
||||
|
||||
use float_cmp::{ApproxEq, F32Margin};
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub struct Tuple {
|
||||
pub x: f32,
|
||||
@ -43,6 +45,40 @@ impl Tuple {
|
||||
}
|
||||
}
|
||||
|
||||
impl ApproxEq for Tuple {
|
||||
type Margin = F32Margin;
|
||||
|
||||
/// Implement float_cmp::ApproxEq for Tuple
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use float_cmp::approx_eq;
|
||||
/// use rtchallenge::tuples::Tuple;
|
||||
///
|
||||
/// assert!(approx_eq!(
|
||||
/// Tuple,
|
||||
/// Tuple::point(1., 1., 0.),
|
||||
/// Tuple::point(1., 1., 0.),
|
||||
/// ulps = 1
|
||||
/// ));
|
||||
///
|
||||
/// assert!(approx_eq!(
|
||||
/// Tuple,
|
||||
/// Tuple::vector(1., 1., 0.),
|
||||
/// Tuple::vector(1., 1., 0.),
|
||||
/// ulps = 1
|
||||
/// ));
|
||||
/// ```
|
||||
fn approx_eq<T: Into<Self::Margin>>(self, t2: Self, margin: T) -> bool {
|
||||
let t = self;
|
||||
let margin = margin.into();
|
||||
t.x.approx_eq(t2.x, margin)
|
||||
&& t.y.approx_eq(t2.y, margin)
|
||||
&& t.z.approx_eq(t2.z, margin)
|
||||
&& t.w.approx_eq(t2.w, margin)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Tuple {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user