use crate::{base::Quaternion, coordinate_system::CoordinateSystem};
pub enum RotationOrder {
PYR,
PRY,
RPY,
RYP,
YPR,
YRP,
}
pub struct EulerAngles {
pub pitch: f32,
pub yaw: f32,
pub roll: f32,
pub order: RotationOrder,
}
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq)]
pub struct Rotation(pub(crate) Quaternion);
impl Rotation {
#[inline(always)]
pub fn euler(angles: EulerAngles, system: CoordinateSystem) -> Self {
let sin_pitch = (angles.pitch / 2f32).sin();
let cos_pitch = (angles.pitch / 2f32).cos();
let sin_yaw = (angles.yaw / 2f32).sin();
let cos_yaw = (angles.yaw / 2f32).cos();
let sin_roll = (angles.roll / 2f32).sin();
let cos_roll = (angles.roll / 2f32).cos();
let right = system.right;
let forward = system.forward;
let up = system.up;
let mut pitch = Quaternion(right.0 * sin_pitch);
pitch.set_w(cos_pitch);
let mut yaw = Quaternion(up.0 * sin_yaw);
yaw.set_w(cos_yaw);
let mut roll = Quaternion(forward.0 * sin_roll);
roll.set_w(cos_roll);
use RotationOrder::*;
Self(match angles.order {
PYR => pitch * yaw * roll,
PRY => pitch * roll * yaw,
RPY => roll * pitch * yaw,
RYP => roll * yaw * pitch,
YPR => yaw * pitch * roll,
YRP => yaw * roll * pitch,
})
}
}