Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

418
vendor/glam/src/f64/daffine2.rs vendored Normal file
View File

@@ -0,0 +1,418 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{DMat2, DMat3, DVec2};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 2D affine transform, which can represent translation, rotation, scaling and shear.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct DAffine2 {
pub matrix2: DMat2,
pub translation: DVec2,
}
impl DAffine2 {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix2: DMat2::ZERO,
translation: DVec2::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix2: DMat2::IDENTITY,
translation: DVec2::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix2: DMat2::NAN,
translation: DVec2::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec2, y_axis: DVec2, z_axis: DVec2) -> Self {
Self {
matrix2: DMat2::from_cols(x_axis, y_axis),
translation: z_axis,
}
}
/// Creates an affine transform from a `[f64; 6]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f64; 6]) -> Self {
Self {
matrix2: DMat2::from_cols_array(&[m[0], m[1], m[2], m[3]]),
translation: DVec2::from_array([m[4], m[5]]),
}
}
/// Creates a `[f64; 6]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f64; 6] {
let x = &self.matrix2.x_axis;
let y = &self.matrix2.y_axis;
let z = &self.translation;
[x.x, x.y, y.x, y.y, z.x, z.y]
}
/// Creates an affine transform from a `[[f64; 2]; 3]`
/// 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f64; 2]; 3]) -> Self {
Self {
matrix2: DMat2::from_cols(m[0].into(), m[1].into()),
translation: m[2].into(),
}
}
/// Creates a `[[f64; 2]; 3]` 2D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f64; 2]; 3] {
[
self.matrix2.x_axis.into(),
self.matrix2.y_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 6 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f64]) -> Self {
Self {
matrix2: DMat2::from_cols_slice(&slice[0..4]),
translation: DVec2::from_slice(&slice[4..6]),
}
}
/// Writes the columns of `self` to the first 6 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 6 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
self.matrix2.write_cols_to_slice(&mut slice[0..4]);
self.translation.write_to_slice(&mut slice[4..6]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: DVec2) -> Self {
Self {
matrix2: DMat2::from_diagonal(scale),
translation: DVec2::ZERO,
}
}
/// Creates an affine transform from the given rotation `angle`.
#[inline]
#[must_use]
pub fn from_angle(angle: f64) -> Self {
Self {
matrix2: DMat2::from_angle(angle),
translation: DVec2::ZERO,
}
}
/// Creates an affine transformation from the given 2D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: DVec2) -> Self {
Self {
matrix2: DMat2::IDENTITY,
translation,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation)
#[inline]
#[must_use]
pub fn from_mat2(matrix2: DMat2) -> Self {
Self {
matrix2,
translation: DVec2::ZERO,
}
}
/// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a
/// translation vector.
///
/// Equivalent to
/// `DAffine2::from_translation(translation) * DAffine2::from_mat2(mat2)`
#[inline]
#[must_use]
pub fn from_mat2_translation(matrix2: DMat2, translation: DVec2) -> Self {
Self {
matrix2,
translation,
}
}
/// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `DAffine2::from_translation(translation) *
/// DAffine2::from_angle(angle) * DAffine2::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
let rotation = DMat2::from_angle(angle);
Self {
matrix2: DMat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y),
translation,
}
}
/// Creates an affine transform from the given 2D rotation `angle` (in radians) and
/// `translation`.
///
/// Equivalent to `DAffine2::from_translation(translation) * DAffine2::from_angle(angle)`
#[inline]
#[must_use]
pub fn from_angle_translation(angle: f64, translation: DVec2) -> Self {
Self {
matrix2: DMat2::from_angle(angle),
translation,
}
}
/// The given `DMat3` must be an affine transform,
#[inline]
#[must_use]
pub fn from_mat3(m: DMat3) -> Self {
use crate::swizzles::Vec3Swizzles;
Self {
matrix2: DMat2::from_cols(m.x_axis.xy(), m.y_axis.xy()),
translation: m.z_axis.xy(),
}
}
/// Extracts `scale`, `angle` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix2` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_angle_translation(self) -> (DVec2, f64, DVec2) {
use crate::f64::math;
let det = self.matrix2.determinant();
glam_assert!(det != 0.0);
let scale = DVec2::new(
self.matrix2.x_axis.length() * math::signum(det),
self.matrix2.y_axis.length(),
);
glam_assert!(scale.cmpne(DVec2::ZERO).all());
let angle = math::atan2(-self.matrix2.y_axis.x, self.matrix2.y_axis.y);
(scale, angle, self.translation)
}
/// Transforms the given 2D point, applying shear, scale, rotation and translation.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
self.matrix2 * rhs + self.translation
}
/// Transforms the given 2D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point2()`] instead.
#[inline]
pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
self.matrix2 * rhs
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix2.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix2.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.matrix2.abs_diff_eq(rhs.matrix2, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix2 = self.matrix2.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix2 * self.translation);
Self {
matrix2,
translation,
}
}
}
impl Default for DAffine2 {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for DAffine2 {
type Target = crate::deref::Cols3<DVec2>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for DAffine2 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for DAffine2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for DAffine2 {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(DAffine2))
.field("matrix2", &self.matrix2)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for DAffine2 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation
)
} else {
write!(
f,
"[{}, {}, {}]",
self.matrix2.x_axis, self.matrix2.y_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for DAffine2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for DAffine2 {
type Output = DAffine2;
#[inline]
fn mul(self, rhs: DAffine2) -> Self::Output {
Self {
matrix2: self.matrix2 * rhs.matrix2,
translation: self.matrix2 * rhs.translation + self.translation,
}
}
}
impl MulAssign for DAffine2 {
#[inline]
fn mul_assign(&mut self, rhs: DAffine2) {
*self = self.mul(rhs);
}
}
impl From<DAffine2> for DMat3 {
#[inline]
fn from(m: DAffine2) -> DMat3 {
Self::from_cols(
m.matrix2.x_axis.extend(0.0),
m.matrix2.y_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<DMat3> for DAffine2 {
type Output = DMat3;
#[inline]
fn mul(self, rhs: DMat3) -> Self::Output {
DMat3::from(self) * rhs
}
}
impl Mul<DAffine2> for DMat3 {
type Output = DMat3;
#[inline]
fn mul(self, rhs: DAffine2) -> Self::Output {
self * DMat3::from(rhs)
}
}

566
vendor/glam/src/f64/daffine3.rs vendored Normal file
View File

@@ -0,0 +1,566 @@
// Generated from affine.rs.tera template. Edit the template, not the generated file.
use crate::{DMat3, DMat4, DQuat, DVec3};
use core::ops::{Deref, DerefMut, Mul, MulAssign};
/// A 3D affine transform, which can represent translation, rotation, scaling and shear.
#[derive(Copy, Clone)]
#[repr(C)]
pub struct DAffine3 {
pub matrix3: DMat3,
pub translation: DVec3,
}
impl DAffine3 {
/// The degenerate zero transform.
///
/// This transforms any finite vector and point to zero.
/// The zero transform is non-invertible.
pub const ZERO: Self = Self {
matrix3: DMat3::ZERO,
translation: DVec3::ZERO,
};
/// The identity transform.
///
/// Multiplying a vector with this returns the same vector.
pub const IDENTITY: Self = Self {
matrix3: DMat3::IDENTITY,
translation: DVec3::ZERO,
};
/// All NAN:s.
pub const NAN: Self = Self {
matrix3: DMat3::NAN,
translation: DVec3::NAN,
};
/// Creates an affine transform from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3, w_axis: DVec3) -> Self {
Self {
matrix3: DMat3::from_cols(x_axis, y_axis, z_axis),
translation: w_axis,
}
}
/// Creates an affine transform from a `[f64; 12]` array stored in column major order.
#[inline]
#[must_use]
pub fn from_cols_array(m: &[f64; 12]) -> Self {
Self {
matrix3: DMat3::from_cols_array(&[
m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8],
]),
translation: DVec3::from_array([m[9], m[10], m[11]]),
}
}
/// Creates a `[f64; 12]` array storing data in column major order.
#[inline]
#[must_use]
pub fn to_cols_array(&self) -> [f64; 12] {
let x = &self.matrix3.x_axis;
let y = &self.matrix3.y_axis;
let z = &self.matrix3.z_axis;
let w = &self.translation;
[x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z]
}
/// Creates an affine transform from a `[[f64; 3]; 4]`
/// 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub fn from_cols_array_2d(m: &[[f64; 3]; 4]) -> Self {
Self {
matrix3: DMat3::from_cols(m[0].into(), m[1].into(), m[2].into()),
translation: m[3].into(),
}
}
/// Creates a `[[f64; 3]; 4]` 3D array storing data in
/// column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub fn to_cols_array_2d(&self) -> [[f64; 3]; 4] {
[
self.matrix3.x_axis.into(),
self.matrix3.y_axis.into(),
self.matrix3.z_axis.into(),
self.translation.into(),
]
}
/// Creates an affine transform from the first 12 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
#[must_use]
pub fn from_cols_slice(slice: &[f64]) -> Self {
Self {
matrix3: DMat3::from_cols_slice(&slice[0..9]),
translation: DVec3::from_slice(&slice[9..12]),
}
}
/// Writes the columns of `self` to the first 12 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 12 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
self.matrix3.write_cols_to_slice(&mut slice[0..9]);
self.translation.write_to_slice(&mut slice[9..12]);
}
/// Creates an affine transform that changes scale.
/// Note that if any scale is zero the transform will be non-invertible.
#[inline]
#[must_use]
pub fn from_scale(scale: DVec3) -> Self {
Self {
matrix3: DMat3::from_diagonal(scale),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform from the given `rotation` quaternion.
#[inline]
#[must_use]
pub fn from_quat(rotation: DQuat) -> Self {
Self {
matrix3: DMat3::from_quat(rotation),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around a normalized
/// rotation `axis` of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
Self {
matrix3: DMat3::from_axis_angle(axis, angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the x axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_x(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the y axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_y(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform containing a 3D rotation around the z axis of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f64) -> Self {
Self {
matrix3: DMat3::from_rotation_z(angle),
translation: DVec3::ZERO,
}
}
/// Creates an affine transformation from the given 3D `translation`.
#[inline]
#[must_use]
pub fn from_translation(translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::IDENTITY,
translation: translation.into(),
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
/// rotation)
#[inline]
#[must_use]
pub fn from_mat3(mat3: DMat3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: DVec3::ZERO,
}
}
/// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
/// and a translation vector.
///
/// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_mat3(mat3)`
#[inline]
#[must_use]
pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: mat3.into(),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `scale`, `rotation` and
/// `translation`.
///
/// Equivalent to `DAffine3::from_translation(translation) *
/// DAffine3::from_quat(rotation) * DAffine3::from_scale(scale)`
#[inline]
#[must_use]
pub fn from_scale_rotation_translation(
scale: DVec3,
rotation: DQuat,
translation: DVec3,
) -> Self {
let rotation = DMat3::from_quat(rotation);
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::from_cols(
rotation.x_axis * scale.x,
rotation.y_axis * scale.y,
rotation.z_axis * scale.z,
),
translation: translation.into(),
}
}
/// Creates an affine transform from the given 3D `rotation` and `translation`.
///
/// Equivalent to `DAffine3::from_translation(translation) * DAffine3::from_quat(rotation)`
#[inline]
#[must_use]
pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
#[allow(clippy::useless_conversion)]
Self {
matrix3: DMat3::from_quat(rotation),
translation: translation.into(),
}
}
/// The given `DMat4` must be an affine transform,
/// i.e. contain no perspective transform.
#[inline]
#[must_use]
pub fn from_mat4(m: DMat4) -> Self {
Self {
matrix3: DMat3::from_cols(
DVec3::from_vec4(m.x_axis),
DVec3::from_vec4(m.y_axis),
DVec3::from_vec4(m.z_axis),
),
translation: DVec3::from_vec4(m.w_axis),
}
}
/// Extracts `scale`, `rotation` and `translation` from `self`.
///
/// The transform is expected to be non-degenerate and without shearing, or the output
/// will be invalid.
///
/// # Panics
///
/// Will panic if the determinant `self.matrix3` is zero or if the resulting scale
/// vector contains any zero elements when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
use crate::f64::math;
let det = self.matrix3.determinant();
glam_assert!(det != 0.0);
let scale = DVec3::new(
self.matrix3.x_axis.length() * math::signum(det),
self.matrix3.y_axis.length(),
self.matrix3.z_axis.length(),
);
glam_assert!(scale.cmpne(DVec3::ZERO).all());
let inv_scale = scale.recip();
#[allow(clippy::useless_conversion)]
let rotation = DQuat::from_mat3(&DMat3::from_cols(
(self.matrix3.x_axis * inv_scale.x).into(),
(self.matrix3.y_axis * inv_scale.y).into(),
(self.matrix3.z_axis * inv_scale.z).into(),
));
#[allow(clippy::useless_conversion)]
(scale, rotation, self.translation.into())
}
/// Creates a left-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
#[inline]
#[must_use]
pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
Self::look_to_rh(eye, -dir, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a facing
/// direction.
///
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
#[inline]
#[must_use]
pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
let f = dir.normalize();
let s = f.cross(up).normalize();
let u = s.cross(f);
Self {
matrix3: DMat3::from_cols(
DVec3::new(s.x, u.x, -f.x),
DVec3::new(s.y, u.y, -f.y),
DVec3::new(s.z, u.z, -f.z),
),
translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)),
}
}
/// Creates a left-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_lh(eye, center - eye, up)
}
/// Creates a right-handed view transform using a camera position, an up direction, and a focal
/// point.
/// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
///
/// # Panics
///
/// Will panic if `up` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
glam_assert!(up.is_normalized());
Self::look_to_rh(eye, center - eye, up)
}
/// Transforms the given 3D points, applying shear, scale, rotation and translation.
#[inline]
pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z)
+ self.translation)
.into()
}
/// Transforms the given 3D vector, applying shear, scale and rotation (but NOT
/// translation).
///
/// To also apply translation, use [`Self::transform_point3()`] instead.
#[inline]
#[must_use]
pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
#[allow(clippy::useless_conversion)]
((self.matrix3.x_axis * rhs.x)
+ (self.matrix3.y_axis * rhs.y)
+ (self.matrix3.z_axis * rhs.z))
.into()
}
/// Returns `true` if, and only if, all elements are finite.
///
/// If any element is either `NaN`, positive or negative infinity, this will return
/// `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.matrix3.is_finite() && self.translation.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.matrix3.is_nan() || self.translation.is_nan()
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two 3x4 matrices contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.matrix3.abs_diff_eq(rhs.matrix3, max_abs_diff)
&& self.translation.abs_diff_eq(rhs.translation, max_abs_diff)
}
/// Return the inverse of this transform.
///
/// Note that if the transform is not invertible the result will be invalid.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let matrix3 = self.matrix3.inverse();
// transform negative translation by the matrix inverse:
let translation = -(matrix3 * self.translation);
Self {
matrix3,
translation,
}
}
}
impl Default for DAffine3 {
#[inline(always)]
fn default() -> Self {
Self::IDENTITY
}
}
impl Deref for DAffine3 {
type Target = crate::deref::Cols4<DVec3>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Self as *const Self::Target) }
}
}
impl DerefMut for DAffine3 {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self as *mut Self as *mut Self::Target) }
}
}
impl PartialEq for DAffine3 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation)
}
}
impl core::fmt::Debug for DAffine3 {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
fmt.debug_struct(stringify!(DAffine3))
.field("matrix3", &self.matrix3)
.field("translation", &self.translation)
.finish()
}
}
impl core::fmt::Display for DAffine3 {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}, {:.*}]",
p,
self.matrix3.x_axis,
p,
self.matrix3.y_axis,
p,
self.matrix3.z_axis,
p,
self.translation
)
} else {
write!(
f,
"[{}, {}, {}, {}]",
self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation
)
}
}
}
impl<'a> core::iter::Product<&'a Self> for DAffine3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| a * b)
}
}
impl Mul for DAffine3 {
type Output = DAffine3;
#[inline]
fn mul(self, rhs: DAffine3) -> Self::Output {
Self {
matrix3: self.matrix3 * rhs.matrix3,
translation: self.matrix3 * rhs.translation + self.translation,
}
}
}
impl MulAssign for DAffine3 {
#[inline]
fn mul_assign(&mut self, rhs: DAffine3) {
*self = self.mul(rhs);
}
}
impl From<DAffine3> for DMat4 {
#[inline]
fn from(m: DAffine3) -> DMat4 {
DMat4::from_cols(
m.matrix3.x_axis.extend(0.0),
m.matrix3.y_axis.extend(0.0),
m.matrix3.z_axis.extend(0.0),
m.translation.extend(1.0),
)
}
}
impl Mul<DMat4> for DAffine3 {
type Output = DMat4;
#[inline]
fn mul(self, rhs: DMat4) -> Self::Output {
DMat4::from(self) * rhs
}
}
impl Mul<DAffine3> for DMat4 {
type Output = DMat4;
#[inline]
fn mul(self, rhs: DAffine3) -> Self::Output {
self * DMat4::from(rhs)
}
}

529
vendor/glam/src/f64/dmat2.rs vendored Normal file
View File

@@ -0,0 +1,529 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
DMat2::from_cols(x_axis, y_axis)
}
/// A 2x2 column major matrix.
#[derive(Clone, Copy)]
#[cfg_attr(feature = "cuda", repr(align(16)))]
#[repr(C)]
pub struct DMat2 {
pub x_axis: DVec2,
pub y_axis: DVec2,
}
impl DMat2 {
/// A 2x2 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
/// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
Self {
x_axis: DVec2::new(m00, m01),
y_axis: DVec2::new(m10, m11),
}
}
/// Creates a 2x2 matrix from two column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
Self { x_axis, y_axis }
}
/// Creates a 2x2 matrix from a `[f64; 4]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f64; 4]) -> Self {
Self::new(m[0], m[1], m[2], m[3])
}
/// Creates a `[f64; 4]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f64; 4] {
[self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
}
/// Creates a 2x2 matrix from a `[[f64; 2]; 2]` 2D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
}
/// Creates a `[[f64; 2]; 2]` 2D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
[self.x_axis.to_array(), self.y_axis.to_array()]
}
/// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: DVec2) -> Self {
Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
}
/// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
/// `angle` (in radians).
#[inline]
#[must_use]
pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
}
/// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
#[inline]
#[must_use]
pub fn from_angle(angle: f64) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::new(cos, sin, -sin, cos)
}
/// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
#[inline]
#[must_use]
pub fn from_mat3(m: DMat3) -> Self {
Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
}
/// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 2.
#[inline]
#[must_use]
pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
(0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
(0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
(1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
(1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
(1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
(2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
(2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
(2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 2x2 matrix from the first 4 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f64]) -> Self {
Self::new(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the columns of `self` to the first 4 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 4 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.y_axis.x;
slice[3] = self.y_axis.y;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> DVec2 {
match index {
0 => self.x_axis,
1 => self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 1.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> DVec2 {
match index {
0 => DVec2::new(self.x_axis.x, self.y_axis.x),
1 => DVec2::new(self.x_axis.y, self.y_axis.y),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self {
x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f64 {
self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let inv_det = {
let det = self.determinant();
glam_assert!(det != 0.0);
det.recip()
};
Self::new(
self.y_axis.y * inv_det,
self.x_axis.y * -inv_det,
self.y_axis.x * -inv_det,
self.x_axis.x * inv_det,
)
}
/// Transforms a 2D vector.
#[inline]
#[must_use]
pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
#[allow(clippy::suspicious_operation_groupings)]
DVec2::new(
(self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
(self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
)
}
/// Multiplies two 2x2 matrices.
#[inline]
#[must_use]
pub fn mul_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
}
/// Adds two 2x2 matrices.
#[inline]
#[must_use]
pub fn add_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
}
/// Subtracts two 2x2 matrices.
#[inline]
#[must_use]
pub fn sub_mat2(&self, rhs: &Self) -> Self {
Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
}
/// Multiplies a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f64) -> Self {
Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
}
/// Divides a 2x2 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f64) -> Self {
let rhs = DVec2::splat(rhs);
Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
}
#[inline]
pub fn as_mat2(&self) -> Mat2 {
Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
}
}
impl Default for DMat2 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<DMat2> for DMat2 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat2(&rhs)
}
}
impl AddAssign<DMat2> for DMat2 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat2(&rhs);
}
}
impl Sub<DMat2> for DMat2 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat2(&rhs)
}
}
impl SubAssign<DMat2> for DMat2 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat2(&rhs);
}
}
impl Neg for DMat2 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
}
}
impl Mul<DMat2> for DMat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat2(&rhs)
}
}
impl MulAssign<DMat2> for DMat2 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat2(&rhs);
}
}
impl Mul<DVec2> for DMat2 {
type Output = DVec2;
#[inline]
fn mul(self, rhs: DVec2) -> Self::Output {
self.mul_vec2(rhs)
}
}
impl Mul<DMat2> for f64 {
type Output = DMat2;
#[inline]
fn mul(self, rhs: DMat2) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f64> for DMat2 {
type Output = Self;
#[inline]
fn mul(self, rhs: f64) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f64> for DMat2 {
#[inline]
fn mul_assign(&mut self, rhs: f64) {
*self = self.mul_scalar(rhs);
}
}
impl Div<DMat2> for f64 {
type Output = DMat2;
#[inline]
fn div(self, rhs: DMat2) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f64> for DMat2 {
type Output = Self;
#[inline]
fn div(self, rhs: f64) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f64> for DMat2 {
#[inline]
fn div_assign(&mut self, rhs: f64) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for DMat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for DMat2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for DMat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for DMat2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for DMat2 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f64; 4]> for DMat2 {
#[inline]
fn as_ref(&self) -> &[f64; 4] {
unsafe { &*(self as *const Self as *const [f64; 4]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f64; 4]> for DMat2 {
#[inline]
fn as_mut(&mut self) -> &mut [f64; 4] {
unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
}
}
impl fmt::Debug for DMat2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(DMat2))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.finish()
}
}
impl fmt::Display for DMat2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
} else {
write!(f, "[{}, {}]", self.x_axis, self.y_axis)
}
}
}

850
vendor/glam/src/f64/dmat3.rs vendored Normal file
View File

@@ -0,0 +1,850 @@
// Generated from mat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{FromEuler, ToEuler},
f64::math,
swizzles::*,
DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
DMat3::from_cols(x_axis, y_axis, z_axis)
}
/// A 3x3 column major matrix.
///
/// This 3x3 matrix type features convenience methods for creating and using linear and
/// affine transformations. If you are primarily dealing with 2D affine transformations the
/// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
/// using a 3x3 matrix.
///
/// Linear transformations including 3D rotation and scale can be created using methods
/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
/// [`Self::from_rotation_z()`].
///
/// The resulting matrices can be use to transform 3D vectors using regular vector
/// multiplication.
///
/// Affine transformations including 2D translation, rotation and scale can be created
/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
///
/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
/// are provided for performing affine transforms on 2D vectors and points. These multiply
/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
/// vectors respectively. These methods assume that `Self` contains a valid affine
/// transform.
#[derive(Clone, Copy)]
#[repr(C)]
pub struct DMat3 {
pub x_axis: DVec3,
pub y_axis: DVec3,
pub z_axis: DVec3,
}
impl DMat3 {
/// A 3x3 matrix with all elements set to `0.0`.
pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
/// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
/// All NAN:s.
pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
#[allow(clippy::too_many_arguments)]
#[inline(always)]
#[must_use]
const fn new(
m00: f64,
m01: f64,
m02: f64,
m10: f64,
m11: f64,
m12: f64,
m20: f64,
m21: f64,
m22: f64,
) -> Self {
Self {
x_axis: DVec3::new(m00, m01, m02),
y_axis: DVec3::new(m10, m11, m12),
z_axis: DVec3::new(m20, m21, m22),
}
}
/// Creates a 3x3 matrix from three column vectors.
#[inline(always)]
#[must_use]
pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
Self {
x_axis,
y_axis,
z_axis,
}
}
/// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
/// If your data is stored in row major you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array(m: &[f64; 9]) -> Self {
Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
}
/// Creates a `[f64; 9]` array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array(&self) -> [f64; 9] {
[
self.x_axis.x,
self.x_axis.y,
self.x_axis.z,
self.y_axis.x,
self.y_axis.y,
self.y_axis.z,
self.z_axis.x,
self.z_axis.y,
self.z_axis.z,
]
}
/// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
/// If your data is in row major order you will need to `transpose` the returned
/// matrix.
#[inline]
#[must_use]
pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
Self::from_cols(
DVec3::from_array(m[0]),
DVec3::from_array(m[1]),
DVec3::from_array(m[2]),
)
}
/// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
/// If you require data in row major order `transpose` the matrix first.
#[inline]
#[must_use]
pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
[
self.x_axis.to_array(),
self.y_axis.to_array(),
self.z_axis.to_array(),
]
}
/// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
#[doc(alias = "scale")]
#[inline]
#[must_use]
pub const fn from_diagonal(diagonal: DVec3) -> Self {
Self::new(
diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
)
}
/// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
#[inline]
#[must_use]
pub fn from_mat4(m: DMat4) -> Self {
Self::from_cols(
DVec3::from_vec4(m.x_axis),
DVec3::from_vec4(m.y_axis),
DVec3::from_vec4(m.z_axis),
)
}
/// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
/// and `j`th row.
///
/// # Panics
///
/// Panics if `i` or `j` is greater than 3.
#[inline]
#[must_use]
pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
match (i, j) {
(0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
(1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
(1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
(1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
(2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
(2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
(2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
(2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
(3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
(3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
(3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
(3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
_ => panic!("index out of bounds"),
}
}
/// Creates a 3D rotation matrix from the given quaternion.
///
/// # Panics
///
/// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_quat(rotation: DQuat) -> Self {
glam_assert!(rotation.is_normalized());
let x2 = rotation.x + rotation.x;
let y2 = rotation.y + rotation.y;
let z2 = rotation.z + rotation.z;
let xx = rotation.x * x2;
let xy = rotation.x * y2;
let xz = rotation.x * z2;
let yy = rotation.y * y2;
let yz = rotation.y * z2;
let zz = rotation.z * z2;
let wx = rotation.w * x2;
let wy = rotation.w * y2;
let wz = rotation.w * z2;
Self::from_cols(
DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
)
}
/// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
/// radians).
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
glam_assert!(axis.is_normalized());
let (sin, cos) = math::sin_cos(angle);
let (xsin, ysin, zsin) = axis.mul(sin).into();
let (x, y, z) = axis.into();
let (x2, y2, z2) = axis.mul(axis).into();
let omc = 1.0 - cos;
let xyomc = x * y * omc;
let xzomc = x * z * omc;
let yzomc = y * z * omc;
Self::from_cols(
DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
)
}
/// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
/// radians).
#[inline]
#[must_use]
pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
Self::from_euler_angles(order, a, b, c)
}
/// Extract Euler angles with the given Euler rotation order.
///
/// Note if the input matrix contains scales, shears, or other non-rotation transformations then
/// the resulting Euler angles will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
glam_assert!(
self.x_axis.is_normalized()
&& self.y_axis.is_normalized()
&& self.z_axis.is_normalized()
);
self.to_euler_angles(order)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f64) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
DVec3::X,
DVec3::new(0.0, cosa, sina),
DVec3::new(0.0, -sina, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f64) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
DVec3::new(cosa, 0.0, -sina),
DVec3::Y,
DVec3::new(sina, 0.0, cosa),
)
}
/// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f64) -> Self {
let (sina, cosa) = math::sin_cos(angle);
Self::from_cols(
DVec3::new(cosa, sina, 0.0),
DVec3::new(-sina, cosa, 0.0),
DVec3::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_translation(translation: DVec2) -> Self {
Self::from_cols(
DVec3::X,
DVec3::Y,
DVec3::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given 2D rotation `angle` (in
/// radians).
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_angle(angle: f64) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
DVec3::new(cos, sin, 0.0),
DVec3::new(-sin, cos, 0.0),
DVec3::Z,
)
}
/// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
/// radians) and `translation`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
#[must_use]
pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
let (sin, cos) = math::sin_cos(angle);
Self::from_cols(
DVec3::new(cos * scale.x, sin * scale.x, 0.0),
DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
DVec3::new(translation.x, translation.y, 1.0),
)
}
/// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
///
/// # Panics
///
/// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_scale(scale: DVec2) -> Self {
// Do not panic as long as any component is non-zero
glam_assert!(scale.cmpne(DVec2::ZERO).any());
Self::from_cols(
DVec3::new(scale.x, 0.0, 0.0),
DVec3::new(0.0, scale.y, 0.0),
DVec3::Z,
)
}
/// Creates an affine transformation matrix from the given 2x2 matrix.
///
/// The resulting matrix can be used to transform 2D points and vectors. See
/// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
#[inline]
pub fn from_mat2(m: DMat2) -> Self {
Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
}
/// Creates a 3x3 matrix from the first 9 values in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
#[must_use]
pub const fn from_cols_slice(slice: &[f64]) -> Self {
Self::new(
slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
slice[8],
)
}
/// Writes the columns of `self` to the first 9 elements in `slice`.
///
/// # Panics
///
/// Panics if `slice` is less than 9 elements long.
#[inline]
pub fn write_cols_to_slice(self, slice: &mut [f64]) {
slice[0] = self.x_axis.x;
slice[1] = self.x_axis.y;
slice[2] = self.x_axis.z;
slice[3] = self.y_axis.x;
slice[4] = self.y_axis.y;
slice[5] = self.y_axis.z;
slice[6] = self.z_axis.x;
slice[7] = self.z_axis.y;
slice[8] = self.z_axis.z;
}
/// Returns the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn col(&self, index: usize) -> DVec3 {
match index {
0 => self.x_axis,
1 => self.y_axis,
2 => self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns a mutable reference to the matrix column for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
match index {
0 => &mut self.x_axis,
1 => &mut self.y_axis,
2 => &mut self.z_axis,
_ => panic!("index out of bounds"),
}
}
/// Returns the matrix row for the given `index`.
///
/// # Panics
///
/// Panics if `index` is greater than 2.
#[inline]
#[must_use]
pub fn row(&self, index: usize) -> DVec3 {
match index {
0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
_ => panic!("index out of bounds"),
}
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(&self) -> bool {
self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
}
/// Returns `true` if any elements are `NaN`.
#[inline]
#[must_use]
pub fn is_nan(&self) -> bool {
self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
}
/// Returns the transpose of `self`.
#[inline]
#[must_use]
pub fn transpose(&self) -> Self {
Self {
x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
}
}
/// Returns the determinant of `self`.
#[inline]
#[must_use]
pub fn determinant(&self) -> f64 {
self.z_axis.dot(self.x_axis.cross(self.y_axis))
}
/// Returns the inverse of `self`.
///
/// If the matrix is not invertible the returned matrix will be invalid.
///
/// # Panics
///
/// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(&self) -> Self {
let tmp0 = self.y_axis.cross(self.z_axis);
let tmp1 = self.z_axis.cross(self.x_axis);
let tmp2 = self.x_axis.cross(self.y_axis);
let det = self.z_axis.dot(tmp2);
glam_assert!(det != 0.0);
let inv_det = DVec3::splat(det.recip());
Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
}
/// Transforms the given 2D vector as a point.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
}
/// Rotates the given 2D vector.
///
/// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
///
/// This method assumes that `self` contains a valid affine transform.
///
/// # Panics
///
/// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
}
/// Transforms a 3D vector.
#[inline]
#[must_use]
pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
let mut res = self.x_axis.mul(rhs.x);
res = res.add(self.y_axis.mul(rhs.y));
res = res.add(self.z_axis.mul(rhs.z));
res
}
/// Multiplies two 3x3 matrices.
#[inline]
#[must_use]
pub fn mul_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.mul(rhs.x_axis),
self.mul(rhs.y_axis),
self.mul(rhs.z_axis),
)
}
/// Adds two 3x3 matrices.
#[inline]
#[must_use]
pub fn add_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.add(rhs.x_axis),
self.y_axis.add(rhs.y_axis),
self.z_axis.add(rhs.z_axis),
)
}
/// Subtracts two 3x3 matrices.
#[inline]
#[must_use]
pub fn sub_mat3(&self, rhs: &Self) -> Self {
Self::from_cols(
self.x_axis.sub(rhs.x_axis),
self.y_axis.sub(rhs.y_axis),
self.z_axis.sub(rhs.z_axis),
)
}
/// Multiplies a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn mul_scalar(&self, rhs: f64) -> Self {
Self::from_cols(
self.x_axis.mul(rhs),
self.y_axis.mul(rhs),
self.z_axis.mul(rhs),
)
}
/// Divides a 3x3 matrix by a scalar.
#[inline]
#[must_use]
pub fn div_scalar(&self, rhs: f64) -> Self {
let rhs = DVec3::splat(rhs);
Self::from_cols(
self.x_axis.div(rhs),
self.y_axis.div(rhs),
self.z_axis.div(rhs),
)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two matrices contain similar elements. It works best
/// when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
&& self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
&& self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
}
/// Takes the absolute value of each element in `self`
#[inline]
#[must_use]
pub fn abs(&self) -> Self {
Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
}
#[inline]
pub fn as_mat3(&self) -> Mat3 {
Mat3::from_cols(
self.x_axis.as_vec3(),
self.y_axis.as_vec3(),
self.z_axis.as_vec3(),
)
}
}
impl Default for DMat3 {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl Add<DMat3> for DMat3 {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
self.add_mat3(&rhs)
}
}
impl AddAssign<DMat3> for DMat3 {
#[inline]
fn add_assign(&mut self, rhs: Self) {
*self = self.add_mat3(&rhs);
}
}
impl Sub<DMat3> for DMat3 {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
self.sub_mat3(&rhs)
}
}
impl SubAssign<DMat3> for DMat3 {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
*self = self.sub_mat3(&rhs);
}
}
impl Neg for DMat3 {
type Output = Self;
#[inline]
fn neg(self) -> Self::Output {
Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
}
}
impl Mul<DMat3> for DMat3 {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
self.mul_mat3(&rhs)
}
}
impl MulAssign<DMat3> for DMat3 {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_mat3(&rhs);
}
}
impl Mul<DVec3> for DMat3 {
type Output = DVec3;
#[inline]
fn mul(self, rhs: DVec3) -> Self::Output {
self.mul_vec3(rhs)
}
}
impl Mul<DMat3> for f64 {
type Output = DMat3;
#[inline]
fn mul(self, rhs: DMat3) -> Self::Output {
rhs.mul_scalar(self)
}
}
impl Mul<f64> for DMat3 {
type Output = Self;
#[inline]
fn mul(self, rhs: f64) -> Self::Output {
self.mul_scalar(rhs)
}
}
impl MulAssign<f64> for DMat3 {
#[inline]
fn mul_assign(&mut self, rhs: f64) {
*self = self.mul_scalar(rhs);
}
}
impl Div<DMat3> for f64 {
type Output = DMat3;
#[inline]
fn div(self, rhs: DMat3) -> Self::Output {
rhs.div_scalar(self)
}
}
impl Div<f64> for DMat3 {
type Output = Self;
#[inline]
fn div(self, rhs: f64) -> Self::Output {
self.div_scalar(rhs)
}
}
impl DivAssign<f64> for DMat3 {
#[inline]
fn div_assign(&mut self, rhs: f64) {
*self = self.div_scalar(rhs);
}
}
impl Sum<Self> for DMat3 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for DMat3 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for DMat3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for DMat3 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl PartialEq for DMat3 {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f64; 9]> for DMat3 {
#[inline]
fn as_ref(&self) -> &[f64; 9] {
unsafe { &*(self as *const Self as *const [f64; 9]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsMut<[f64; 9]> for DMat3 {
#[inline]
fn as_mut(&mut self) -> &mut [f64; 9] {
unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
}
}
impl fmt::Debug for DMat3 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(stringify!(DMat3))
.field("x_axis", &self.x_axis)
.field("y_axis", &self.y_axis)
.field("z_axis", &self.z_axis)
.finish()
}
}
impl fmt::Display for DMat3 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}]",
p, self.x_axis, p, self.y_axis, p, self.z_axis
)
} else {
write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
}
}
}

1396
vendor/glam/src/f64/dmat4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

940
vendor/glam/src/f64/dquat.rs vendored Normal file
View File

@@ -0,0 +1,940 @@
// Generated from quat.rs.tera template. Edit the template, not the generated file.
use crate::{
euler::{EulerRot, FromEuler, ToEuler},
f64::math,
DMat3, DMat4, DVec2, DVec3, DVec4, Quat,
};
use core::fmt;
use core::iter::{Product, Sum};
use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
/// Creates a quaternion from `x`, `y`, `z` and `w` values.
///
/// This should generally not be called manually unless you know what you are doing. Use
/// one of the other constructors instead such as `identity` or `from_axis_angle`.
#[inline]
#[must_use]
pub const fn dquat(x: f64, y: f64, z: f64, w: f64) -> DQuat {
DQuat::from_xyzw(x, y, z, w)
}
/// A quaternion representing an orientation.
///
/// This quaternion is intended to be of unit length but may denormalize due to
/// floating point "error creep" which can occur when successive quaternion
/// operations are applied.
#[derive(Clone, Copy)]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
#[cfg_attr(target_arch = "spirv", repr(simd))]
pub struct DQuat {
pub x: f64,
pub y: f64,
pub z: f64,
pub w: f64,
}
impl DQuat {
/// All zeros.
const ZERO: Self = Self::from_array([0.0; 4]);
/// The identity quaternion. Corresponds to no rotation.
pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
/// All NANs.
pub const NAN: Self = Self::from_array([f64::NAN; 4]);
/// Creates a new rotation quaternion.
///
/// This should generally not be called manually unless you know what you are doing.
/// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
///
/// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline(always)]
#[must_use]
pub const fn from_xyzw(x: f64, y: f64, z: f64, w: f64) -> Self {
Self { x, y, z, w }
}
/// Creates a rotation quaternion from an array.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline]
#[must_use]
pub const fn from_array(a: [f64; 4]) -> Self {
Self::from_xyzw(a[0], a[1], a[2], a[3])
}
/// Creates a new rotation quaternion from a 4D vector.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
#[inline]
#[must_use]
pub const fn from_vec4(v: DVec4) -> Self {
Self {
x: v.x,
y: v.y,
z: v.z,
w: v.w,
}
}
/// Creates a rotation quaternion from a slice.
///
/// # Preconditions
///
/// This function does not check if the input is normalized, it is up to the user to
/// provide normalized input or to normalized the resulting quaternion.
///
/// # Panics
///
/// Panics if `slice` length is less than 4.
#[inline]
#[must_use]
pub fn from_slice(slice: &[f64]) -> Self {
Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
}
/// Writes the quaternion to an unaligned slice.
///
/// # Panics
///
/// Panics if `slice` length is less than 4.
#[inline]
pub fn write_to_slice(self, slice: &mut [f64]) {
slice[0] = self.x;
slice[1] = self.y;
slice[2] = self.z;
slice[3] = self.w;
}
/// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
///
/// The axis must be a unit vector.
///
/// # Panics
///
/// Will panic if `axis` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
glam_assert!(axis.is_normalized());
let (s, c) = math::sin_cos(angle * 0.5);
let v = axis * s;
Self::from_xyzw(v.x, v.y, v.z, c)
}
/// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
///
/// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
#[inline]
#[must_use]
pub fn from_scaled_axis(v: DVec3) -> Self {
let length = v.length();
if length == 0.0 {
Self::IDENTITY
} else {
Self::from_axis_angle(v / length, length)
}
}
/// Creates a quaternion from the `angle` (in radians) around the x axis.
#[inline]
#[must_use]
pub fn from_rotation_x(angle: f64) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(s, 0.0, 0.0, c)
}
/// Creates a quaternion from the `angle` (in radians) around the y axis.
#[inline]
#[must_use]
pub fn from_rotation_y(angle: f64) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(0.0, s, 0.0, c)
}
/// Creates a quaternion from the `angle` (in radians) around the z axis.
#[inline]
#[must_use]
pub fn from_rotation_z(angle: f64) -> Self {
let (s, c) = math::sin_cos(angle * 0.5);
Self::from_xyzw(0.0, 0.0, s, c)
}
/// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
#[inline]
#[must_use]
pub fn from_euler(euler: EulerRot, a: f64, b: f64, c: f64) -> Self {
Self::from_euler_angles(euler, a, b, c)
}
/// From the columns of a 3x3 rotation matrix.
///
/// Note if the input axes contain scales, shears, or other non-rotation transformations then
/// the output of this function is ill-defined.
///
/// # Panics
///
/// Will panic if any axis is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub(crate) fn from_rotation_axes(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized());
// Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix`
let (m00, m01, m02) = x_axis.into();
let (m10, m11, m12) = y_axis.into();
let (m20, m21, m22) = z_axis.into();
if m22 <= 0.0 {
// x^2 + y^2 >= z^2 + w^2
let dif10 = m11 - m00;
let omm22 = 1.0 - m22;
if dif10 <= 0.0 {
// x^2 >= y^2
let four_xsq = omm22 - dif10;
let inv4x = 0.5 / math::sqrt(four_xsq);
Self::from_xyzw(
four_xsq * inv4x,
(m01 + m10) * inv4x,
(m02 + m20) * inv4x,
(m12 - m21) * inv4x,
)
} else {
// y^2 >= x^2
let four_ysq = omm22 + dif10;
let inv4y = 0.5 / math::sqrt(four_ysq);
Self::from_xyzw(
(m01 + m10) * inv4y,
four_ysq * inv4y,
(m12 + m21) * inv4y,
(m20 - m02) * inv4y,
)
}
} else {
// z^2 + w^2 >= x^2 + y^2
let sum10 = m11 + m00;
let opm22 = 1.0 + m22;
if sum10 <= 0.0 {
// z^2 >= w^2
let four_zsq = opm22 - sum10;
let inv4z = 0.5 / math::sqrt(four_zsq);
Self::from_xyzw(
(m02 + m20) * inv4z,
(m12 + m21) * inv4z,
four_zsq * inv4z,
(m01 - m10) * inv4z,
)
} else {
// w^2 >= z^2
let four_wsq = opm22 + sum10;
let inv4w = 0.5 / math::sqrt(four_wsq);
Self::from_xyzw(
(m12 - m21) * inv4w,
(m20 - m02) * inv4w,
(m01 - m10) * inv4w,
four_wsq * inv4w,
)
}
}
}
/// Creates a quaternion from a 3x3 rotation matrix.
///
/// Note if the input matrix contain scales, shears, or other non-rotation transformations then
/// the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_mat3(mat: &DMat3) -> Self {
Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
}
/// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
///
/// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
/// then the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
/// `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_mat4(mat: &DMat4) -> Self {
Self::from_rotation_axes(
mat.x_axis.truncate(),
mat.y_axis.truncate(),
mat.z_axis.truncate(),
)
}
/// Gets the minimal rotation for transforming `from` to `to`. The rotation is in the
/// plane spanned by the two vectors. Will rotate at most 180 degrees.
///
/// The inputs must be unit vectors.
///
/// `from_rotation_arc(from, to) * from ≈ to`.
///
/// For near-singular cases (from≈to and from≈-to) the current implementation
/// is only accurate to about 0.001 (for `f32`).
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[must_use]
pub fn from_rotation_arc(from: DVec3, to: DVec3) -> Self {
glam_assert!(from.is_normalized());
glam_assert!(to.is_normalized());
const ONE_MINUS_EPS: f64 = 1.0 - 2.0 * f64::EPSILON;
let dot = from.dot(to);
if dot > ONE_MINUS_EPS {
// 0° singularity: from ≈ to
Self::IDENTITY
} else if dot < -ONE_MINUS_EPS {
// 180° singularity: from ≈ -to
use core::f64::consts::PI; // half a turn = 𝛕/2 = 180°
Self::from_axis_angle(from.any_orthonormal_vector(), PI)
} else {
let c = from.cross(to);
Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
}
}
/// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means
/// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
///
/// The rotation is in the plane spanned by the two vectors. Will rotate at most 90
/// degrees.
///
/// The inputs must be unit vectors.
///
/// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn from_rotation_arc_colinear(from: DVec3, to: DVec3) -> Self {
if from.dot(to) < 0.0 {
Self::from_rotation_arc(from, -to)
} else {
Self::from_rotation_arc(from, to)
}
}
/// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is
/// around the z axis. Will rotate at most 180 degrees.
///
/// The inputs must be unit vectors.
///
/// `from_rotation_arc_2d(from, to) * from ≈ to`.
///
/// For near-singular cases (from≈to and from≈-to) the current implementation
/// is only accurate to about 0.001 (for `f32`).
///
/// # Panics
///
/// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
#[must_use]
pub fn from_rotation_arc_2d(from: DVec2, to: DVec2) -> Self {
glam_assert!(from.is_normalized());
glam_assert!(to.is_normalized());
const ONE_MINUS_EPSILON: f64 = 1.0 - 2.0 * f64::EPSILON;
let dot = from.dot(to);
if dot > ONE_MINUS_EPSILON {
// 0° singularity: from ≈ to
Self::IDENTITY
} else if dot < -ONE_MINUS_EPSILON {
// 180° singularity: from ≈ -to
const COS_FRAC_PI_2: f64 = 0.0;
const SIN_FRAC_PI_2: f64 = 1.0;
// rotation around z by PI radians
Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
} else {
// vector3 cross where z=0
let z = from.x * to.y - to.x * from.y;
let w = 1.0 + dot;
// calculate length with x=0 and y=0 to normalize
let len_rcp = 1.0 / math::sqrt(z * z + w * w);
Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
}
}
/// Returns the rotation axis (normalized) and angle (in radians) of `self`.
#[inline]
#[must_use]
pub fn to_axis_angle(self) -> (DVec3, f64) {
const EPSILON: f64 = 1.0e-8;
let v = DVec3::new(self.x, self.y, self.z);
let length = v.length();
if length >= EPSILON {
let angle = 2.0 * math::atan2(length, self.w);
let axis = v / length;
(axis, angle)
} else {
(DVec3::X, 0.0)
}
}
/// Returns the rotation axis scaled by the rotation in radians.
#[inline]
#[must_use]
pub fn to_scaled_axis(self) -> DVec3 {
let (axis, angle) = self.to_axis_angle();
axis * angle
}
/// Returns the rotation angles for the given euler rotation sequence.
#[inline]
#[must_use]
pub fn to_euler(self, order: EulerRot) -> (f64, f64, f64) {
self.to_euler_angles(order)
}
/// `[x, y, z, w]`
#[inline]
#[must_use]
pub fn to_array(&self) -> [f64; 4] {
[self.x, self.y, self.z, self.w]
}
/// Returns the vector part of the quaternion.
#[inline]
#[must_use]
pub fn xyz(self) -> DVec3 {
DVec3::new(self.x, self.y, self.z)
}
/// Returns the quaternion conjugate of `self`. For a unit quaternion the
/// conjugate is also the inverse.
#[inline]
#[must_use]
pub fn conjugate(self) -> Self {
Self {
x: -self.x,
y: -self.y,
z: -self.z,
w: self.w,
}
}
/// Returns the inverse of a normalized quaternion.
///
/// Typically quaternion inverse returns the conjugate of a normalized quaternion.
/// Because `self` is assumed to already be unit length this method *does not* normalize
/// before returning the conjugate.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn inverse(self) -> Self {
glam_assert!(self.is_normalized());
self.conjugate()
}
/// Computes the dot product of `self` and `rhs`. The dot product is
/// equal to the cosine of the angle between two quaternion rotations.
#[inline]
#[must_use]
pub fn dot(self, rhs: Self) -> f64 {
DVec4::from(self).dot(DVec4::from(rhs))
}
/// Computes the length of `self`.
#[doc(alias = "magnitude")]
#[inline]
#[must_use]
pub fn length(self) -> f64 {
DVec4::from(self).length()
}
/// Computes the squared length of `self`.
///
/// This is generally faster than `length()` as it avoids a square
/// root operation.
#[doc(alias = "magnitude2")]
#[inline]
#[must_use]
pub fn length_squared(self) -> f64 {
DVec4::from(self).length_squared()
}
/// Computes `1.0 / length()`.
///
/// For valid results, `self` must _not_ be of length zero.
#[inline]
#[must_use]
pub fn length_recip(self) -> f64 {
DVec4::from(self).length_recip()
}
/// Returns `self` normalized to length 1.0.
///
/// For valid results, `self` must _not_ be of length zero.
///
/// Panics
///
/// Will panic if `self` is zero length when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn normalize(self) -> Self {
Self::from_vec4(DVec4::from(self).normalize())
}
/// Returns `true` if, and only if, all elements are finite.
/// If any element is either `NaN`, positive or negative infinity, this will return `false`.
#[inline]
#[must_use]
pub fn is_finite(self) -> bool {
DVec4::from(self).is_finite()
}
/// Returns `true` if any elements are `NAN`.
#[inline]
#[must_use]
pub fn is_nan(self) -> bool {
DVec4::from(self).is_nan()
}
/// Returns whether `self` of length `1.0` or not.
///
/// Uses a precision threshold of `1e-6`.
#[inline]
#[must_use]
pub fn is_normalized(self) -> bool {
DVec4::from(self).is_normalized()
}
#[inline]
#[must_use]
pub fn is_near_identity(self) -> bool {
// Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
let threshold_angle = 0.002_847_144_6;
// Because of floating point precision, we cannot represent very small rotations.
// The closest f32 to 1.0 that is not 1.0 itself yields:
// 0.99999994.acos() * 2.0 = 0.000690533954 rad
//
// An error threshold of 1.e-6 is used by default.
// (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
// (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
//
// We don't really care about the angle value itself, only if it's close to 0.
// This will happen whenever quat.w is close to 1.0.
// If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
// a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
// the shortest path.
let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
positive_w_angle < threshold_angle
}
/// Returns the angle (in radians) for the minimal rotation
/// for transforming this quaternion into another.
///
/// Both quaternions must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn angle_between(self, rhs: Self) -> f64 {
glam_assert!(self.is_normalized() && rhs.is_normalized());
math::acos_approx(math::abs(self.dot(rhs))) * 2.0
}
/// Rotates towards `rhs` up to `max_angle` (in radians).
///
/// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
/// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
/// rotates towards the exact opposite of `rhs`. Will not go past the target.
///
/// Both quaternions must be normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn rotate_towards(&self, rhs: Self, max_angle: f64) -> Self {
glam_assert!(self.is_normalized() && rhs.is_normalized());
let angle = self.angle_between(rhs);
if angle <= 1e-4 {
return *self;
}
let s = (max_angle / angle).clamp(-1.0, 1.0);
self.slerp(rhs, s)
}
/// Returns true if the absolute difference of all elements between `self` and `rhs`
/// is less than or equal to `max_abs_diff`.
///
/// This can be used to compare if two quaternions contain similar elements. It works
/// best when comparing with a known value. The `max_abs_diff` that should be used used
/// depends on the values being compared against.
///
/// For more see
/// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
#[inline]
#[must_use]
pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
}
#[inline(always)]
#[must_use]
fn lerp_impl(self, end: Self, s: f64) -> Self {
(self * (1.0 - s) + end * s).normalize()
}
/// Performs a linear interpolation between `self` and `rhs` based on
/// the value `s`.
///
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
/// is `1.0`, the result will be equal to `rhs`.
///
/// # Panics
///
/// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
#[doc(alias = "mix")]
#[inline]
#[must_use]
pub fn lerp(self, end: Self, s: f64) -> Self {
glam_assert!(self.is_normalized());
glam_assert!(end.is_normalized());
let dot = self.dot(end);
let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
self.lerp_impl(end * bias, s)
}
/// Performs a spherical linear interpolation between `self` and `end`
/// based on the value `s`.
///
/// When `s` is `0.0`, the result will be equal to `self`. When `s`
/// is `1.0`, the result will be equal to `end`.
///
/// # Panics
///
/// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn slerp(self, mut end: Self, s: f64) -> Self {
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
glam_assert!(self.is_normalized());
glam_assert!(end.is_normalized());
// Note that a rotation can be represented by two quaternions: `q` and
// `-q`. The slerp path between `q` and `end` will be different from the
// path between `-q` and `end`. One path will take the long way around and
// one will take the short way. In order to correct for this, the `dot`
// product between `self` and `end` should be positive. If the `dot`
// product is negative, slerp between `self` and `-end`.
let mut dot = self.dot(end);
if dot < 0.0 {
end = -end;
dot = -dot;
}
const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
if dot > DOT_THRESHOLD {
// if above threshold perform linear interpolation to avoid divide by zero
self.lerp_impl(end, s)
} else {
let theta = math::acos_approx(dot);
let scale1 = math::sin(theta * (1.0 - s));
let scale2 = math::sin(theta * s);
let theta_sin = math::sin(theta);
((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
}
}
/// Multiplies a quaternion and a 3D vector, returning the rotated vector.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
glam_assert!(self.is_normalized());
let w = self.w;
let b = DVec3::new(self.x, self.y, self.z);
let b2 = b.dot(b);
rhs.mul(w * w - b2)
.add(b.mul(rhs.dot(b) * 2.0))
.add(b.cross(rhs).mul(w * 2.0))
}
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
#[must_use]
pub fn mul_quat(self, rhs: Self) -> Self {
let (x0, y0, z0, w0) = self.into();
let (x1, y1, z1, w1) = rhs.into();
Self::from_xyzw(
w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
)
}
/// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
///
/// Note if the input affine matrix contain scales, shears, or other non-rotation
/// transformations then the resulting quaternion will be ill-defined.
///
/// # Panics
///
/// Will panic if any input affine matrix column is not normalized when `glam_assert` is
/// enabled.
#[inline]
#[must_use]
pub fn from_affine3(a: &crate::DAffine3) -> Self {
#[allow(clippy::useless_conversion)]
Self::from_rotation_axes(
a.matrix3.x_axis.into(),
a.matrix3.y_axis.into(),
a.matrix3.z_axis.into(),
)
}
#[inline]
#[must_use]
pub fn as_quat(self) -> Quat {
Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
}
}
impl fmt::Debug for DQuat {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple(stringify!(DQuat))
.field(&self.x)
.field(&self.y)
.field(&self.z)
.field(&self.w)
.finish()
}
}
impl fmt::Display for DQuat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = f.precision() {
write!(
f,
"[{:.*}, {:.*}, {:.*}, {:.*}]",
p, self.x, p, self.y, p, self.z, p, self.w
)
} else {
write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
}
}
}
impl Add<DQuat> for DQuat {
type Output = Self;
/// Adds two quaternions.
///
/// The sum is not guaranteed to be normalized.
///
/// Note that addition is not the same as combining the rotations represented by the
/// two quaternions! That corresponds to multiplication.
#[inline]
fn add(self, rhs: Self) -> Self {
Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
}
}
impl Sub<DQuat> for DQuat {
type Output = Self;
/// Subtracts the `rhs` quaternion from `self`.
///
/// The difference is not guaranteed to be normalized.
#[inline]
fn sub(self, rhs: Self) -> Self {
Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
}
}
impl Mul<f64> for DQuat {
type Output = Self;
/// Multiplies a quaternion by a scalar value.
///
/// The product is not guaranteed to be normalized.
#[inline]
fn mul(self, rhs: f64) -> Self {
Self::from_vec4(DVec4::from(self) * rhs)
}
}
impl Div<f64> for DQuat {
type Output = Self;
/// Divides a quaternion by a scalar value.
/// The quotient is not guaranteed to be normalized.
#[inline]
fn div(self, rhs: f64) -> Self {
Self::from_vec4(DVec4::from(self) / rhs)
}
}
impl Mul<DQuat> for DQuat {
type Output = Self;
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly
/// normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
fn mul(self, rhs: Self) -> Self {
self.mul_quat(rhs)
}
}
impl MulAssign<DQuat> for DQuat {
/// Multiplies two quaternions. If they each represent a rotation, the result will
/// represent the combined rotation.
///
/// Note that due to floating point rounding the result may not be perfectly
/// normalized.
///
/// # Panics
///
/// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
#[inline]
fn mul_assign(&mut self, rhs: Self) {
*self = self.mul_quat(rhs);
}
}
impl Mul<DVec3> for DQuat {
type Output = DVec3;
/// Multiplies a quaternion and a 3D vector, returning the rotated vector.
///
/// # Panics
///
/// Will panic if `self` is not normalized when `glam_assert` is enabled.
#[inline]
fn mul(self, rhs: DVec3) -> Self::Output {
self.mul_vec3(rhs)
}
}
impl Neg for DQuat {
type Output = Self;
#[inline]
fn neg(self) -> Self {
self * -1.0
}
}
impl Default for DQuat {
#[inline]
fn default() -> Self {
Self::IDENTITY
}
}
impl PartialEq for DQuat {
#[inline]
fn eq(&self, rhs: &Self) -> bool {
DVec4::from(*self).eq(&DVec4::from(*rhs))
}
}
#[cfg(not(target_arch = "spirv"))]
impl AsRef<[f64; 4]> for DQuat {
#[inline]
fn as_ref(&self) -> &[f64; 4] {
unsafe { &*(self as *const Self as *const [f64; 4]) }
}
}
impl Sum<Self> for DQuat {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::ZERO, Self::add)
}
}
impl<'a> Sum<&'a Self> for DQuat {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
}
}
impl Product for DQuat {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(Self::IDENTITY, Self::mul)
}
}
impl<'a> Product<&'a Self> for DQuat {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
}
}
impl From<DQuat> for DVec4 {
#[inline]
fn from(q: DQuat) -> Self {
Self::new(q.x, q.y, q.z, q.w)
}
}
impl From<DQuat> for (f64, f64, f64, f64) {
#[inline]
fn from(q: DQuat) -> Self {
(q.x, q.y, q.z, q.w)
}
}
impl From<DQuat> for [f64; 4] {
#[inline]
fn from(q: DQuat) -> Self {
[q.x, q.y, q.z, q.w]
}
}

1856
vendor/glam/src/f64/dvec2.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1951
vendor/glam/src/f64/dvec3.rs vendored Normal file

File diff suppressed because it is too large Load Diff

2010
vendor/glam/src/f64/dvec4.rs vendored Normal file

File diff suppressed because it is too large Load Diff

21
vendor/glam/src/f64/float.rs vendored Normal file
View File

@@ -0,0 +1,21 @@
// Generated from float.rs.tera template. Edit the template, not the generated file.
use crate::float::FloatExt;
impl FloatExt for f64 {
#[inline]
fn lerp(self, rhs: f64, t: f64) -> f64 {
self + (rhs - self) * t
}
#[inline]
fn inverse_lerp(a: f64, b: f64, v: f64) -> f64 {
(v - a) / (b - a)
}
#[inline]
fn remap(self, in_start: f64, in_end: f64, out_start: f64, out_end: f64) -> f64 {
let t = f64::inverse_lerp(in_start, in_end, self);
f64::lerp(out_start, out_end, t)
}
}

205
vendor/glam/src/f64/math.rs vendored Normal file
View File

@@ -0,0 +1,205 @@
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
mod libm_math {
#[inline(always)]
pub(crate) fn abs(f: f64) -> f64 {
libm::fabs(f)
}
#[inline(always)]
pub(crate) fn acos_approx(f: f64) -> f64 {
libm::acos(f.clamp(-1.0, 1.0))
}
#[inline(always)]
pub(crate) fn atan2(f: f64, other: f64) -> f64 {
libm::atan2(f, other)
}
#[inline(always)]
pub(crate) fn sin(f: f64) -> f64 {
libm::sin(f)
}
#[inline(always)]
pub(crate) fn sin_cos(f: f64) -> (f64, f64) {
libm::sincos(f)
}
#[inline(always)]
pub(crate) fn tan(f: f64) -> f64 {
libm::tan(f)
}
#[inline(always)]
pub(crate) fn sqrt(f: f64) -> f64 {
libm::sqrt(f)
}
#[inline(always)]
pub(crate) fn copysign(f: f64, sign: f64) -> f64 {
libm::copysign(f, sign)
}
#[inline(always)]
pub(crate) fn signum(f: f64) -> f64 {
if f.is_nan() {
f64::NAN
} else {
copysign(1.0, f)
}
}
#[inline(always)]
pub(crate) fn round(f: f64) -> f64 {
libm::round(f)
}
#[inline(always)]
pub(crate) fn trunc(f: f64) -> f64 {
libm::trunc(f)
}
#[inline(always)]
pub(crate) fn ceil(f: f64) -> f64 {
libm::ceil(f)
}
#[inline(always)]
pub(crate) fn floor(f: f64) -> f64 {
libm::floor(f)
}
#[inline(always)]
pub(crate) fn exp(f: f64) -> f64 {
libm::exp(f)
}
#[inline(always)]
pub(crate) fn powf(f: f64, n: f64) -> f64 {
libm::pow(f, n)
}
#[inline(always)]
pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 {
libm::fma(a, b, c)
}
#[inline]
pub fn div_euclid(a: f64, b: f64) -> f64 {
// Based on https://doc.rust-lang.org/src/std/f64.rs.html#293
let q = libm::trunc(a / b);
if a % b < 0.0 {
return if b > 0.0 { q - 1.0 } else { q + 1.0 };
}
q
}
#[inline]
pub fn rem_euclid(a: f64, b: f64) -> f64 {
let r = a % b;
if r < 0.0 {
r + abs(b)
} else {
r
}
}
}
#[cfg(all(not(feature = "libm"), feature = "std"))]
mod std_math {
#[inline(always)]
pub(crate) fn abs(f: f64) -> f64 {
f64::abs(f)
}
#[inline(always)]
pub(crate) fn acos_approx(f: f64) -> f64 {
f64::acos(f64::clamp(f, -1.0, 1.0))
}
#[inline(always)]
pub(crate) fn atan2(f: f64, other: f64) -> f64 {
f64::atan2(f, other)
}
#[inline(always)]
pub(crate) fn sin(f: f64) -> f64 {
f64::sin(f)
}
#[inline(always)]
pub(crate) fn sin_cos(f: f64) -> (f64, f64) {
f64::sin_cos(f)
}
#[inline(always)]
pub(crate) fn tan(f: f64) -> f64 {
f64::tan(f)
}
#[inline(always)]
pub(crate) fn sqrt(f: f64) -> f64 {
f64::sqrt(f)
}
#[inline(always)]
pub(crate) fn copysign(f: f64, sign: f64) -> f64 {
f64::copysign(f, sign)
}
#[inline(always)]
pub(crate) fn signum(f: f64) -> f64 {
f64::signum(f)
}
#[inline(always)]
pub(crate) fn round(f: f64) -> f64 {
f64::round(f)
}
#[inline(always)]
pub(crate) fn trunc(f: f64) -> f64 {
f64::trunc(f)
}
#[inline(always)]
pub(crate) fn ceil(f: f64) -> f64 {
f64::ceil(f)
}
#[inline(always)]
pub(crate) fn floor(f: f64) -> f64 {
f64::floor(f)
}
#[inline(always)]
pub(crate) fn exp(f: f64) -> f64 {
f64::exp(f)
}
#[inline(always)]
pub(crate) fn powf(f: f64, n: f64) -> f64 {
f64::powf(f, n)
}
#[inline(always)]
pub(crate) fn mul_add(a: f64, b: f64, c: f64) -> f64 {
f64::mul_add(a, b, c)
}
#[inline]
pub fn div_euclid(a: f64, b: f64) -> f64 {
f64::div_euclid(a, b)
}
#[inline]
pub fn rem_euclid(a: f64, b: f64) -> f64 {
f64::rem_euclid(a, b)
}
}
#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))]
pub(crate) use libm_math::*;
#[cfg(all(not(feature = "libm"), feature = "std"))]
pub(crate) use std_math::*;