|
|
|
@ -20,8 +20,41 @@ impl<const N: usize> fmt::Debug for FVec<N> {
@@ -20,8 +20,41 @@ impl<const N: usize> fmt::Debug for FVec<N> {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<const N: usize> FVec<N> { |
|
|
|
|
/// The vector's `x` component (also called the `i` component of `ijk[r]`).
|
|
|
|
|
#[doc(alias = "i")] |
|
|
|
|
pub fn x(self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.x } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The vector's `y` component (also called the `j` component of `ijk[r]`).
|
|
|
|
|
#[doc(alias = "j")] |
|
|
|
|
pub fn y(self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.y } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The vector's `i` component (also called the `k` component of `ijk[r]`).
|
|
|
|
|
#[doc(alias = "k")] |
|
|
|
|
pub fn z(self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.z } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl FVec4 { |
|
|
|
|
/// The vector's `w` component (also called `r` for the real component of `ijk[r]`).
|
|
|
|
|
#[doc(alias = "r")] |
|
|
|
|
pub fn w(self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.w } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Create a new [`FVec4`] from its components.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// let v = FVec4::new(1.0, 2.0, 3.0, 4.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec4_New")] |
|
|
|
|
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec4_New(x, y, z, w) }) |
|
|
|
@ -33,146 +66,185 @@ impl FVec4 {
@@ -33,146 +66,185 @@ impl FVec4 {
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// # use float_cmp::assert_approx_eq;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec4::splat(1.0);
|
|
|
|
|
/// assert_approx_eq!(FVec4, v, FVec4::new(1.0, 1.0, 1.0, 1.0));
|
|
|
|
|
/// assert_abs_diff_eq!(v, FVec4::new(1.0, 1.0, 1.0, 1.0));
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn splat(v: f32) -> Self { |
|
|
|
|
Self::new(v, v, v, v) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The vector's `w` component (sometimes also called `r` for the real
|
|
|
|
|
/// component of a quaternion `ijk[r]`).
|
|
|
|
|
#[doc(alias = "r")] |
|
|
|
|
pub fn w(&self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.w } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Divide the vector's XYZ components by its W component.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// # use float_cmp::assert_approx_eq;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec4::new(2.0, 4.0, 6.0, 2.0);
|
|
|
|
|
/// assert_approx_eq!(
|
|
|
|
|
/// FVec4,
|
|
|
|
|
/// v.perspective_divide(),
|
|
|
|
|
/// FVec4::new(1.0, 2.0, 3.0, 1.0)
|
|
|
|
|
/// );
|
|
|
|
|
/// assert_abs_diff_eq!(v.perspective_divide(), FVec4::new(1.0, 2.0, 3.0, 1.0));
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec4_PerspDivide")] |
|
|
|
|
pub fn perspective_divide(&self) -> Self { |
|
|
|
|
pub fn perspective_divide(self) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec4_PerspDivide(self.0) }) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The dot product of two vectors.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// # use float_cmp::assert_approx_eq;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v1 = FVec4::new(1.0, 2.0, 3.0, 4.0);
|
|
|
|
|
/// let v2 = FVec4::new(1.0, 0.5, 1.0, 0.5);
|
|
|
|
|
/// assert_approx_eq!(f32, v1.dot(&v2), 7.0);
|
|
|
|
|
/// assert_abs_diff_eq!(v1.dot(v2), 7.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec4_Dot")] |
|
|
|
|
pub fn dot(&self, rhs: &Self) -> f32 { |
|
|
|
|
pub fn dot(self, rhs: Self) -> f32 { |
|
|
|
|
unsafe { citro3d_sys::FVec4_Dot(self.0, rhs.0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The magnitude of the vector.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// # use float_cmp::assert_approx_eq;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec4::splat(1.0);
|
|
|
|
|
/// assert_approx_eq!(f32, v.magnitude(), 2.0);
|
|
|
|
|
/// assert_abs_diff_eq!(v.magnitude(), 2.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec4_Magnitude")] |
|
|
|
|
pub fn magnitude(&self) -> f32 { |
|
|
|
|
pub fn magnitude(self) -> f32 { |
|
|
|
|
unsafe { citro3d_sys::FVec4_Magnitude(self.0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Normalize the vector to a magnitude of `1.0`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec4;
|
|
|
|
|
/// # use float_cmp::assert_approx_eq;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec4::new(1.0, 2.0, 2.0, 4.0);
|
|
|
|
|
/// assert_approx_eq!(FVec4, v, FVec4::new(0.1, 0.4, 0.4, 0.8));
|
|
|
|
|
/// assert_abs_diff_eq!(v, FVec4::new(0.1, 0.4, 0.4, 0.8));
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Normalize")] |
|
|
|
|
pub fn normalize(&self) -> Self { |
|
|
|
|
pub fn normalize(self) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec3_Normalize(self.0) }) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl FVec3 { |
|
|
|
|
/// Create a new [`FVec3`] from its components.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// let v = FVec3::new(1.0, 2.0, 3.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_New")] |
|
|
|
|
pub fn new(x: f32, y: f32, z: f32) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec3_New(x, y, z) }) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Create a new [`FVec3`], setting each component to the given `v`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// let v = FVec3::splat(1.0);
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn splat(v: f32) -> Self { |
|
|
|
|
Self::new(v, v, v) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The distance between two points in 3D space.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let l = FVec3::new(1.0, 3.0, 4.0);
|
|
|
|
|
/// let r = FVec3::new(0.0, 1.0, 2.0);
|
|
|
|
|
///
|
|
|
|
|
/// assert_abs_diff_eq!(l.distance(r), 3.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Distance")] |
|
|
|
|
pub fn distance(&self, rhs: &Self) -> f32 { |
|
|
|
|
pub fn distance(self, rhs: Self) -> f32 { |
|
|
|
|
unsafe { citro3d_sys::FVec3_Distance(self.0, rhs.0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The cross product of two 3D vectors.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let l = FVec3::new(1.0, 0.0, 0.0);
|
|
|
|
|
/// let r = FVec3::new(0.0, 1.0, 0.0);
|
|
|
|
|
/// assert_abs_diff_eq!(l.cross(r), FVec3::new(0.0, 0.0, 1.0));
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Cross")] |
|
|
|
|
pub fn cross(&self, rhs: &Self) -> Self { |
|
|
|
|
pub fn cross(self, rhs: Self) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec3_Cross(self.0, rhs.0) }) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The dot product of two vectors.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let l = FVec3::new(1.0, 2.0, 3.0);
|
|
|
|
|
/// let r = FVec3::new(3.0, 2.0, 1.0);
|
|
|
|
|
/// assert_abs_diff_eq!(l.dot(r), 10.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Dot")] |
|
|
|
|
pub fn dot(&self, rhs: &Self) -> f32 { |
|
|
|
|
pub fn dot(self, rhs: Self) -> f32 { |
|
|
|
|
unsafe { citro3d_sys::FVec3_Dot(self.0, rhs.0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The magnitude of the vector.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec3::splat(3.0f32.sqrt());
|
|
|
|
|
/// assert_abs_diff_eq!(v.magnitude(), 3.0);
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Magnitude")] |
|
|
|
|
pub fn magnitude(&self) -> f32 { |
|
|
|
|
pub fn magnitude(self) -> f32 { |
|
|
|
|
unsafe { citro3d_sys::FVec3_Magnitude(self.0) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Normalize the vector to a magnitude of `1.0`.
|
|
|
|
|
///
|
|
|
|
|
/// # Example
|
|
|
|
|
/// ```
|
|
|
|
|
/// # let _runner = test_runner::GdbRunner::default();
|
|
|
|
|
/// # use citro3d::math::FVec3;
|
|
|
|
|
/// # use approx::assert_abs_diff_eq;
|
|
|
|
|
/// let v = FVec3::splat(2.0);
|
|
|
|
|
/// assert_abs_diff_eq!(v.normalize(), FVec3::splat(1.0));
|
|
|
|
|
/// ```
|
|
|
|
|
#[doc(alias = "FVec3_Normalize")] |
|
|
|
|
pub fn normalize(&self) -> Self { |
|
|
|
|
pub fn normalize(self) -> Self { |
|
|
|
|
Self(unsafe { citro3d_sys::FVec3_Normalize(self.0) }) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<const N: usize> FVec<N> { |
|
|
|
|
/// The vector's `x` component (sometimes also called the `i` component of `ijk[r]`).
|
|
|
|
|
pub fn x(&self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.x } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The vector's `y` component (sometimes also called the `j` component of `ijk[r]`).
|
|
|
|
|
pub fn y(&self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.y } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// The vector's `i` component (sometimes also called the `k` component of `ijk[r]`).
|
|
|
|
|
pub fn z(&self) -> f32 { |
|
|
|
|
unsafe { self.0.__bindgen_anon_1.z } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
mod tests { |
|
|
|
|
use float_cmp::assert_approx_eq; |
|
|
|
|
use approx::assert_abs_diff_eq; |
|
|
|
|
|
|
|
|
|
use super::*; |
|
|
|
|
|
|
|
|
@ -181,7 +253,7 @@ mod tests {
@@ -181,7 +253,7 @@ mod tests {
|
|
|
|
|
let v = FVec4::new(1.0, 2.0, 3.0, 4.0); |
|
|
|
|
let actual = [v.x(), v.y(), v.z(), v.w()]; |
|
|
|
|
let expected = [1.0, 2.0, 3.0, 4.0]; |
|
|
|
|
assert_approx_eq!(&[f32], &actual, &expected); |
|
|
|
|
assert_abs_diff_eq!(&actual[..], &expected[..]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
@ -189,25 +261,6 @@ mod tests {
@@ -189,25 +261,6 @@ mod tests {
|
|
|
|
|
let v = FVec3::new(1.0, 2.0, 3.0); |
|
|
|
|
let actual = [v.x(), v.y(), v.z()]; |
|
|
|
|
let expected = [1.0, 2.0, 3.0]; |
|
|
|
|
assert_approx_eq!(&[f32], &actual, &expected); |
|
|
|
|
|
|
|
|
|
let l = FVec3::new(2.0, 2.0, 2.0); |
|
|
|
|
|
|
|
|
|
assert_eq!(l, FVec3::splat(2.0)); |
|
|
|
|
|
|
|
|
|
for component in [l.x(), l.y(), l.z()] { |
|
|
|
|
assert_approx_eq!(f32, component, 2.0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let dot = l.dot(&FVec3::splat(3.0)); |
|
|
|
|
assert_approx_eq!(f32, dot, 18.0); |
|
|
|
|
|
|
|
|
|
assert_approx_eq!(f32, l.magnitude(), f32::sqrt(12.0)); |
|
|
|
|
|
|
|
|
|
let norm = l.normalize(); |
|
|
|
|
assert_approx_eq!(f32, norm.magnitude(), 1.0); |
|
|
|
|
for component in [l.y(), l.z()] { |
|
|
|
|
assert_approx_eq!(f32, l.x(), component); |
|
|
|
|
} |
|
|
|
|
assert_abs_diff_eq!(&actual[..], &expected[..]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|