use glam::{Quat, Vec3};
#[inline(always)]
pub fn transform_rotate(point: Vec3, rotation: Quat) -> Vec3 {
rotation.conjugate() * point
}
#[inline(always)]
pub fn transform_rotate_inverse(point: Vec3, rotation: Quat) -> Vec3 {
rotation * point
}
#[inline(always)]
pub fn transform_rotate_euler(point: Vec3, x: f32, y: f32, z: f32) -> Vec3 {
let rotation = Quat::from_euler(glam::EulerRot::XYZ, x, y, z);
transform_rotate(point, rotation)
}
#[cfg(test)]
mod tests {
use super::*;
use std::f32::consts::PI;
#[test]
fn test_rotate_identity() {
let point = Vec3::new(1.0, 2.0, 3.0);
let rotation = Quat::IDENTITY;
let result = transform_rotate(point, rotation);
assert!((result - point).length() < 0.0001);
}
#[test]
fn test_rotate_90_y() {
let point = Vec3::new(1.0, 0.0, 0.0);
let rotation = Quat::from_rotation_y(PI / 2.0);
let result = transform_rotate(point, rotation);
let expected = Vec3::new(0.0, 0.0, 1.0);
assert!((result - expected).length() < 0.0001);
}
#[test]
fn test_rotate_inverse_roundtrip() {
let point = Vec3::new(1.0, 2.0, 3.0);
let rotation = Quat::from_euler(glam::EulerRot::XYZ, 0.5, 0.3, 0.7);
let transformed = transform_rotate(point, rotation);
let restored = transform_rotate_inverse(transformed, rotation);
assert!((restored - point).length() < 0.0001);
}
#[test]
fn test_rotate_euler() {
let point = Vec3::new(1.0, 0.0, 0.0);
let result = transform_rotate_euler(point, 0.0, PI / 2.0, 0.0);
let expected = Vec3::new(0.0, 0.0, 1.0);
assert!((result - expected).length() < 0.0001);
}
}