use nalgebra::{Quaternion, UnitQuaternion};
#[inline(always)]
pub fn quaternion_to_nalgebra(q: &[f32; 4]) -> Quaternion<f32> {
Quaternion::new(q[0], q[1], q[2], q[3])
}
#[inline(always)]
pub fn quaternion_from_nalgebra(q: &Quaternion<f32>) -> [f32; 4] {
[q.w, q.i, q.j, q.k]
}
#[inline(always)]
pub fn quaternion_to_unit_nalgebra(q: &[f32; 4]) -> UnitQuaternion<f32> {
UnitQuaternion::from_quaternion(quaternion_to_nalgebra(q))
}
#[inline(always)]
pub fn quaternion_from_unit_nalgebra(q: &UnitQuaternion<f32>) -> [f32; 4] {
quaternion_from_nalgebra(q.quaternion())
}
#[cfg(test)]
mod tests {
extern crate std;
use super::*;
#[test]
fn quaternion_round_trips_through_nalgebra() {
let q = [0.5f32, 0.5, 0.5, 0.5];
let back = quaternion_from_nalgebra(&quaternion_to_nalgebra(&q));
assert_eq!(back, q);
}
#[test]
fn unit_quaternion_round_trips_for_already_normalized_input() {
let q = [0.5f32, 0.5, 0.5, 0.5]; let back = quaternion_from_unit_nalgebra(&quaternion_to_unit_nalgebra(&q));
for i in 0..4 {
assert!((back[i] - q[i]).abs() < 1e-6, "component {i}: {back:?} vs {q:?}");
}
}
#[test]
fn unit_quaternion_conversion_normalizes() {
let q = [2.0f32, 0.0, 0.0, 0.0]; let uq = quaternion_to_unit_nalgebra(&q);
assert!((uq.quaternion().norm() - 1.0).abs() < 1e-6);
let back = quaternion_from_unit_nalgebra(&uq);
assert!((back[0] - 1.0).abs() < 1e-6);
}
#[test]
fn matches_quaternion_module_normalize() {
let mut q = [3.0f32, 0.0, 4.0, 0.0]; crate::quaternion::quaternion_normalize_f32(&mut q);
let via_nalgebra = quaternion_from_unit_nalgebra(&quaternion_to_unit_nalgebra(&[
3.0, 0.0, 4.0, 0.0,
]));
for i in 0..4 {
assert!(
(via_nalgebra[i] - q[i]).abs() < 1e-6,
"component {i}: {via_nalgebra:?} vs {q:?}"
);
}
}
}