use super::{matrix::structures::Matrix, quat::Quat};
#[cfg(test)]
mod test;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AxisAngle {
pub radians: f64,
pub x: f64,
pub y: f64,
pub z: f64,
}
impl AxisAngle {
pub fn magnitude(&self) -> f64 {
let x = self.x;
let y = self.y;
let z = self.z;
(x * x + y * y + z * z).sqrt()
}
pub fn matches_closely(
&self,
other: &Self,
tolerance: f64,
) -> bool {
(self.radians - other.radians).abs() <= tolerance
&& (self.x - other.x).abs() <= tolerance
&& (self.y - other.y).abs() <= tolerance
&& (self.z - other.z).abs() <= tolerance
}
pub fn matches_exactly(
&self,
other: &Self,
) -> bool {
self.radians == other.radians
&& self.x == other.x
&& self.y == other.y
&& self.z == other.z
}
pub fn normalize(&mut self) -> &mut Self {
let magnitude = self.magnitude();
self.x /= magnitude;
self.y /= magnitude;
self.z /= magnitude;
self
}
}
impl Default for AxisAngle {
fn default() -> Self {
Self {
radians: 0.0,
x: 1.0,
y: 0.0,
z: 0.0,
}
}
}
impl From<AxisAngle> for Matrix<3, 3> {
fn from(axis_angle: AxisAngle) -> Self {
let AxisAngle {
radians,
x,
y,
z,
} = axis_angle;
let c = radians.cos();
let s = radians.sin();
Matrix {
rows: [
[
c + (1.0 - c) * x * x,
(1.0 - c) * x * y - s * z,
(1.0 - c) * x * z + s * y,
],
[
(1.0 - c) * x * y + s * z,
c + (1.0 - c) * y * y,
(1.0 - c) * y * z - s * x,
],
[
(1.0 - c) * x * z - s * y,
(1.0 - c) * y * z + s * x,
c + (1.0 - c) * z * z,
],
],
}
}
}
impl From<AxisAngle> for Quat {
fn from(axis_angle: AxisAngle) -> Self {
let half_radians = axis_angle.radians / 2.0;
let sin_half_radians = half_radians.sin();
Quat {
w: half_radians.cos(),
x: sin_half_radians * axis_angle.x,
y: sin_half_radians * axis_angle.y,
z: sin_half_radians * axis_angle.z,
}
}
}