Struct vek::quaternion::repr_simd::Quaternion [−][src]
#[repr(simd)]pub struct Quaternion<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
Expand description
Quaternions are a convenient representation for rotations in 3D spaces.
IMPORTANT: Quaternions are only valid as rotations as long as they are normalized (i.e their magnitude is 1). Most operations assume this, instead of normalizing inputs behind your back, so be careful.
They essentially consist of a vector part (x
, y
, z
), and scalar part (w
).
For unit quaternions, the vector part is the unit axis of rotation scaled by the sine of
the half-angle of the rotation, and the scalar part is the cosine of the half-angle.
Fields
x: T
y: T
z: T
w: T
Implementations
Creates a new quaternion with x
, y
, z
and w
elements in order.
You are responsible for ensuring that the resulting quaternion is normalized.
Creates a new quaternion from a scalar-and-vector pair.
You are responsible for ensuring that the resulting quaternion is normalized.
Converts this quaternion into a scalar-and-vector pair by destructuring.
Not to be confused with into_angle_axis()
.
Creates a new quaternion with all elements set to zero.
Be careful: since it has a magnitude equal to zero, it is not valid to use for most operations.
Creates the identity quaternion.
use std::f32::consts::PI;
let id = Quaternion::<f32>::identity();
assert_eq!(id, Default::default());
assert_relative_eq!(id, id.conjugate());
assert_relative_eq!(id, id.inverse());
let q = Quaternion::rotation_y(PI);
assert_relative_eq!(id * q, q);
assert_relative_eq!(q * id, q);
Gets this quaternion’s conjugate (copy with negated vector part).
On normalized quaternions, the conjugate also happens to be the inverse.
use std::f32::consts::PI;
let p = Quaternion::rotation_x(PI);
let q = Quaternion::rotation_z(PI);
assert_relative_eq!((p*q).conjugate(), q.conjugate() * p.conjugate());
// Rotation quaternions are normalized, so their conjugate is also their inverse.
assert_relative_eq!(q.conjugate(), q.inverse());
Gets this quaternion’s inverse, i.e the one that reverses its effect.
On normalized quaternions, the inverse happens to be the conjugate.
use std::f32::consts::PI;
let rot = Quaternion::rotation_y(PI);
let inv = rot.inverse();
assert_relative_eq!(rot*inv, Quaternion::identity());
assert_relative_eq!(inv*rot, Quaternion::identity());
let p = Quaternion::rotation_x(PI);
let q = Quaternion::rotation_z(PI);
assert_relative_eq!((p*q).inverse(), q.inverse() * p.inverse());
Gets the dot product between two quaternions.
Gets a normalized copy of this quaternion.
Gets this quaternion’s magnitude, squared.
Gets this quaternion’s magnitude.
Creates a quaternion that would rotate a from
direction to to
.
let (from, to) = (Vec4::<f32>::unit_x(), Vec4::<f32>::unit_y());
let q = Quaternion::<f32>::rotation_from_to_3d(from, to);
assert_relative_eq!(q * from, to);
assert_relative_eq!(q * Vec4::unit_y(), -Vec4::unit_x());
let (from, to) = (Vec4::<f32>::unit_x(), -Vec4::<f32>::unit_x());
let q = Quaternion::<f32>::rotation_from_to_3d(from, to);
assert_relative_eq!(q * from, to);
Creates a quaternion from an angle and axis. The axis is not required to be normalized.
Creates a quaternion from an angle for a rotation around the X axis.
Creates a quaternion from an angle for a rotation around the Y axis.
Creates a quaternion from an angle for a rotation around the Y axis.
Returns this quaternion rotated around the given axis with given angle. The axis is not required to be normalized.
Returns this quaternion rotated around the X axis with given angle.
Returns this quaternion rotated around the Y axis with given angle.
Returns this quaternion rotated around the Z axis with given angle.
Rotates this quaternion around the given axis with given angle. The axis is not required to be normalized.
Rotates this quaternion around the X axis with given angle.
Rotates this quaternion around the Y axis with given angle.
Rotates this quaternion around the Z axis with given angle.
Convert this quaternion to angle-axis representation, assuming the quaternion is normalized.
use std::f32::consts::PI;
let q = Quaternion::rotation_x(PI/2.);
let (angle, axis) = q.into_angle_axis();
assert_relative_eq!(angle, PI/2.);
assert_relative_eq!(axis, Vec3::unit_x());
let angle = PI*4./5.;
let axis = Vec3::new(1_f32, 2., 3.);
let q = Quaternion::rotation_3d(angle, axis);
let (a, v) = q.into_angle_axis();
assert_relative_eq!(a, angle);
assert_relative_eq!(v, axis.normalized());
Creates a quaternion from a Vec4
by destructuring.
You are responsible for ensuring that the resulting quaternion is normalized.
pub fn lerp_precise_unnormalized(from: Self, to: Self, factor: T) -> Self where
T: Clamp + Zero,
pub fn lerp_precise_unnormalized(from: Self, to: Self, factor: T) -> Self where
T: Clamp + Zero,
Performs linear interpolation without normalizing the result, using an implementation that supposedly yields a more precise result.
This is probably not what you’re looking for.
For an implementation that normalizes the result (which is more commonly wanted), see the Lerp
implementation.
Performs linear interpolation without normalizing the result and without
implicitly constraining factor
to be between 0 and 1,
using an implementation that supposedly yields a more precise result.
This is probably not what you’re looking for.
For an implementation that normalizes the result (which is more commonly wanted), see the Lerp
implementation.
Performs linear interpolation without normalizing the result.
This is probably not what you’re looking for.
For an implementation that normalizes the result (which is more commonly wanted), see the Lerp
implementation.
Performs linear interpolation without normalizing the result and without
implicitly constraining factor
to be between 0 and 1.
This is probably not what you’re looking for.
For an implementation that normalizes the result (which is more commonly wanted), see the Lerp
implementation.
Performs spherical linear interpolation without implictly constraining factor
to
be between 0 and 1.
use std::f32::consts::PI;
let from = Quaternion::rotation_z(0_f32);
let to = Quaternion::rotation_z(PI*9./10.);
let angles = 32;
for i in 0..angles {
let factor = (i as f32) / (angles as f32);
let expected = Quaternion::rotation_z(factor * PI*9./10.);
let slerp = Quaternion::slerp(from, to, factor);
assert_relative_eq!(slerp, expected);
}
Trait Implementations
The default tolerance to use when testing values that are close together. Read more
A test for equality that uses the absolute difference to compute the approximate equality of two numbers. Read more
The inverse of AbsDiffEq::abs_diff_eq
.
The default value for a quaternion is the identity.
assert_eq!(Quaternion::<f32>::identity(), Quaternion::default());
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error> where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error> where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
Rotation matrices can be obtained from quaternions. This implementation only works properly if the quaternion is normalized.
use std::f32::consts::PI;
let angles = 32;
for i in 0..angles {
let theta = PI * 2. * (i as f32) / (angles as f32);
assert_relative_eq!(Mat4::rotation_x(theta), Mat4::from(Quaternion::rotation_x(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_y(theta), Mat4::from(Quaternion::rotation_y(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_z(theta), Mat4::from(Quaternion::rotation_z(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_x(theta), Mat4::rotation_3d(theta, Vec4::unit_x()));
assert_relative_eq!(Mat4::rotation_y(theta), Mat4::rotation_3d(theta, Vec4::unit_y()));
assert_relative_eq!(Mat4::rotation_z(theta), Mat4::rotation_3d(theta, Vec4::unit_z()));
// See what rotating unit vectors do for most angles between 0 and 2*PI.
// It's helpful to picture this as a right-handed coordinate system.
let v = Vec4::unit_y();
let m = Mat4::rotation_x(theta);
assert_relative_eq!(m * v, Vec4::new(0., theta.cos(), theta.sin(), 0.));
let v = Vec4::unit_z();
let m = Mat4::rotation_y(theta);
assert_relative_eq!(m * v, Vec4::new(theta.sin(), 0., theta.cos(), 0.));
let v = Vec4::unit_x();
let m = Mat4::rotation_z(theta);
assert_relative_eq!(m * v, Vec4::new(theta.cos(), theta.sin(), 0., 0.));
}
Performs the conversion.
Performs the conversion.
Rotation matrices can be obtained from quaternions. This implementation only works properly if the quaternion is normalized.
use std::f32::consts::PI;
let angles = 32;
for i in 0..angles {
let theta = PI * 2. * (i as f32) / (angles as f32);
assert_relative_eq!(Mat4::rotation_x(theta), Mat4::from(Quaternion::rotation_x(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_y(theta), Mat4::from(Quaternion::rotation_y(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_z(theta), Mat4::from(Quaternion::rotation_z(theta)), epsilon = 0.000001);
assert_relative_eq!(Mat4::rotation_x(theta), Mat4::rotation_3d(theta, Vec4::unit_x()));
assert_relative_eq!(Mat4::rotation_y(theta), Mat4::rotation_3d(theta, Vec4::unit_y()));
assert_relative_eq!(Mat4::rotation_z(theta), Mat4::rotation_3d(theta, Vec4::unit_z()));
// See what rotating unit vectors do for most angles between 0 and 2*PI.
// It's helpful to picture this as a right-handed coordinate system.
let v = Vec4::unit_y();
let m = Mat4::rotation_x(theta);
assert_relative_eq!(m * v, Vec4::new(0., theta.cos(), theta.sin(), 0.));
let v = Vec4::unit_z();
let m = Mat4::rotation_y(theta);
assert_relative_eq!(m * v, Vec4::new(theta.sin(), 0., theta.cos(), 0.));
let v = Vec4::unit_x();
let m = Mat4::rotation_z(theta);
assert_relative_eq!(m * v, Vec4::new(theta.cos(), theta.sin(), 0., 0.));
}
Performs the conversion.
Performs the conversion.
A Vec4
can be created directly from a quaternion’s x
, y
, z
and w
elements.
Performs the conversion.
A Vec3
can be created directly from a quaternion’s x
, y
and z
elements.
Performs the conversion.
A Vec4
can be created directly from a quaternion’s x
, y
, z
and w
elements.
Performs the conversion.
A Vec3
can be created directly from a quaternion’s x
, y
and z
elements.
Performs the conversion.
A quaternion can be created directly from a Vec4
’s x
, y
, z
and w
elements.
You are responsible for ensuring that the resulting quaternion is normalized.
A quaternion can be created directly from a Vec4
’s x
, y
, z
and w
elements.
You are responsible for ensuring that the resulting quaternion is normalized.
The Lerp
implementation for quaternion is the “Normalized LERP”.
type Output = Self
type Output = Self
The resulting type after performing the LERP operation.
Returns the linear interpolation of from
to to
with factor
unconstrained,
using a possibly slower but more precise operation. Read more
Returns the linear interpolation of from
to to
with factor
unconstrained,
using the supposedly fastest but less precise implementation. Read more
fn lerp_unclamped_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
fn lerp_unclamped_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
Version of lerp_unclamped()
that used a single RangeInclusive
parameter instead of two values.
fn lerp_unclamped_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
fn lerp_unclamped_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
Version of lerp_unclamped_precise()
that used a single RangeInclusive
parameter instead of two values.
Alias to lerp_unclamped
which constrains factor
to be between 0 and 1
(inclusive). Read more
fn lerp_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
fn lerp_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
Version of lerp()
that used a single RangeInclusive
parameter instead of two values.
Alias to lerp_unclamped_precise
which constrains factor
to be between 0 and 1
(inclusive). Read more
fn lerp_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
fn lerp_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
Version of lerp_precise()
that used a single RangeInclusive
parameter instead of two values.
The Lerp
implementation for quaternion is the “Normalized LERP”.
type Output = Quaternion<T>
type Output = Quaternion<T>
The resulting type after performing the LERP operation.
Returns the linear interpolation of from
to to
with factor
unconstrained,
using a possibly slower but more precise operation. Read more
Returns the linear interpolation of from
to to
with factor
unconstrained,
using the supposedly fastest but less precise implementation. Read more
fn lerp_unclamped_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
fn lerp_unclamped_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
Version of lerp_unclamped()
that used a single RangeInclusive
parameter instead of two values.
fn lerp_unclamped_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
fn lerp_unclamped_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output
Version of lerp_unclamped_precise()
that used a single RangeInclusive
parameter instead of two values.
Alias to lerp_unclamped
which constrains factor
to be between 0 and 1
(inclusive). Read more
fn lerp_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
fn lerp_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
Version of lerp()
that used a single RangeInclusive
parameter instead of two values.
Alias to lerp_unclamped_precise
which constrains factor
to be between 0 and 1
(inclusive). Read more
fn lerp_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
fn lerp_precise_inclusive_range(
range: RangeInclusive<Self>,
factor: Factor
) -> Self::Output where
Factor: Clamp + Zero + One,
Version of lerp_precise()
that used a single RangeInclusive
parameter instead of two values.
impl<T> Mul<Quaternion<T>> for Quaternion<T> where
T: Copy + Mul<Output = T> + Sub<Output = T> + Zero + Add<T, Output = T>,
impl<T> Mul<Quaternion<T>> for Quaternion<T> where
T: Copy + Mul<Output = T> + Sub<Output = T> + Zero + Add<T, Output = T>,
The Mul
implementation for quaternions is concatenation, a.k.a Grassman product.
use std::f32::consts::PI;
let v = Vec4::unit_x();
let p = Quaternion::rotation_y(PI/2.);
let q = Quaternion::rotation_z(PI/2.);
assert_relative_eq!((p*q)*v, p*(q*v));
assert_relative_eq!(p*q*v, Vec4::unit_y());
assert_relative_eq!(q*p*v, -Vec4::unit_z());
3D vectors can be rotated by being premultiplied by a quaternion, assuming the quaternion is normalized.
3D vectors can be rotated by being premultiplied by a quaternion, assuming the quaternion is normalized.
3D vectors can be rotated by being premultiplied by a quaternion, assuming the
quaternion is normalized.
On Vec4
s, the w
element is preserved, so you can safely rotate
points and directions.
use std::f32::consts::PI;
let v = Vec4::unit_x();
let q = Quaternion::<f32>::identity();
assert_relative_eq!(q * v, v);
let q = Quaternion::rotation_z(PI);
assert_relative_eq!(q * v, -v);
let q = Quaternion::rotation_z(PI * 0.5);
assert_relative_eq!(q * v, Vec4::unit_y());
let q = Quaternion::rotation_z(PI * 1.5);
assert_relative_eq!(q * v, -Vec4::unit_y());
let angles = 32;
for i in 0..angles {
let theta = PI * 2. * (i as f32) / (angles as f32);
// See what rotating unit vectors do for most angles between 0 and 2*PI.
// It's helpful to picture this as a right-handed coordinate system.
let v = Vec4::unit_y();
let q = Quaternion::rotation_x(theta);
assert_relative_eq!(q * v, Vec4::new(0., theta.cos(), theta.sin(), 0.));
let v = Vec4::unit_z();
let q = Quaternion::rotation_y(theta);
assert_relative_eq!(q * v, Vec4::new(theta.sin(), 0., theta.cos(), 0.));
let v = Vec4::unit_x();
let q = Quaternion::rotation_z(theta);
assert_relative_eq!(q * v, Vec4::new(theta.cos(), theta.sin(), 0., 0.));
}
3D vectors can be rotated by being premultiplied by a quaternion, assuming the
quaternion is normalized.
On Vec4
s, the w
element is preserved, so you can safely rotate
points and directions.
use std::f32::consts::PI;
let v = Vec4::unit_x();
let q = Quaternion::<f32>::identity();
assert_relative_eq!(q * v, v);
let q = Quaternion::rotation_z(PI);
assert_relative_eq!(q * v, -v);
let q = Quaternion::rotation_z(PI * 0.5);
assert_relative_eq!(q * v, Vec4::unit_y());
let q = Quaternion::rotation_z(PI * 1.5);
assert_relative_eq!(q * v, -Vec4::unit_y());
let angles = 32;
for i in 0..angles {
let theta = PI * 2. * (i as f32) / (angles as f32);
// See what rotating unit vectors do for most angles between 0 and 2*PI.
// It's helpful to picture this as a right-handed coordinate system.
let v = Vec4::unit_y();
let q = Quaternion::rotation_x(theta);
assert_relative_eq!(q * v, Vec4::new(0., theta.cos(), theta.sin(), 0.));
let v = Vec4::unit_z();
let q = Quaternion::rotation_y(theta);
assert_relative_eq!(q * v, Vec4::new(theta.sin(), 0., theta.cos(), 0.));
let v = Vec4::unit_x();
let q = Quaternion::rotation_z(theta);
assert_relative_eq!(q * v, Vec4::new(theta.cos(), theta.sin(), 0., 0.));
}
This method tests for self
and other
values to be equal, and is used
by ==
. Read more
This method tests for !=
.
The default relative tolerance for testing values that are far-apart. Read more
A test for equality that uses a relative comparison if the values are far apart.
The inverse of RelativeEq::relative_eq
.
type Output = Quaternion<T>
type Output = Quaternion<T>
The resulting type after performing the SLERP operation.
Performs spherical linear interpolation without implictly constraining factor
to
be between 0 and 1. Read more
The default ULPs to tolerate when testing values that are far-apart. Read more
A test for equality that uses units in the last place (ULP) if the values are far apart.
Auto Trait Implementations
impl<T> RefUnwindSafe for Quaternion<T> where
T: RefUnwindSafe,
impl<T> Send for Quaternion<T> where
T: Send,
impl<T> Sync for Quaternion<T> where
T: Sync,
impl<T> Unpin for Quaternion<T> where
T: Unpin,
impl<T> UnwindSafe for Quaternion<T> where
T: UnwindSafe,
Blanket Implementations
Mutably borrows from an owned value. Read more