better angles -> quat

This commit is contained in:
Robin Appelman 2024-12-29 20:32:29 +01:00
commit 2d01af156e

View file

@ -1,7 +1,8 @@
use crate::{ModelError, StringError}; use crate::{ModelError, StringError};
use arrayvec::ArrayString; use arrayvec::ArrayString;
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use cgmath::{Deg, Euler, InnerSpace, Matrix3, Matrix4, Rad, Rotation3, Transform, Vector3}; use cgmath::{Angle, Deg, Euler, InnerSpace, Matrix3, Matrix4, Rad, Rotation3, Transform, Vector3};
use std::f32::consts::PI;
use std::fmt; use std::fmt;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::{Add, Mul}; use std::ops::{Add, Mul};
@ -160,11 +161,32 @@ impl Mul<RadianEuler> for Quaternion {
#[derive(Debug, Clone, Copy, Zeroable, Pod, Default)] #[derive(Debug, Clone, Copy, Zeroable, Pod, Default)]
#[repr(C)] #[repr(C)]
pub struct RadianEuler { pub struct RadianEuler {
/// Roll
pub x: f32, pub x: f32,
/// Pitch
pub y: f32, pub y: f32,
/// Yaw
pub z: f32, pub z: f32,
} }
impl RadianEuler {
pub fn clamped(self) -> Self {
fn clamp(rad: f32) -> f32 {
if rad >= (2.0 * PI) - f32::EPSILON {
rad - 2.0 * PI
} else {
rad
}
}
Self {
x: clamp(self.x),
y: clamp(self.y),
z: clamp(self.z),
}
}
}
impl From<RadianEuler> for Euler<Rad<f32>> { impl From<RadianEuler> for Euler<Rad<f32>> {
fn from(e: RadianEuler) -> Self { fn from(e: RadianEuler) -> Self {
Euler { Euler {
@ -187,10 +209,22 @@ impl From<RadianEuler> for Euler<Deg<f32>> {
impl From<RadianEuler> for cgmath::Quaternion<f32> { impl From<RadianEuler> for cgmath::Quaternion<f32> {
fn from(value: RadianEuler) -> Self { fn from(value: RadianEuler) -> Self {
// angles are applied in roll, pitch, yaw order let (sy, cy) = Rad::sin_cos(Rad(value.z * 0.5));
cgmath::Quaternion::from_angle_y(Rad(value.y)) let (sp, cp) = Rad::sin_cos(Rad(value.y * 0.5));
* cgmath::Quaternion::from_angle_x(Rad(-value.x)) let (sr, cr) = Rad::sin_cos(Rad(-value.x * 0.5));
* cgmath::Quaternion::from_angle_z(Rad(value.z))
let sr_cp = sr * cp;
let cr_sp = cr * sp;
let cr_cp = cr * cp;
let sr_sp = sr * sp;
cgmath::Quaternion::new(
cr_cp * cy + sr_sp * sy,
sr_cp * cy - cr_sp * sy,
cr_sp * cy + sr_cp * sy,
cr_cp * sy - sr_sp * cy,
)
} }
} }