use super::*;
pub fn make_rot(radians: f32) -> Rot {
let cs = compute_cos_sin(radians);
Rot {
c: cs.cosine,
s: cs.sine,
}
}
pub fn make_rot_from_unit_vector(unit_vector: Vec2) -> Rot {
debug_assert!(is_normalized(unit_vector));
Rot {
c: unit_vector.x,
s: unit_vector.y,
}
}
pub fn is_normalized_rot(q: Rot) -> bool {
let qq = q.s * q.s + q.c * q.c;
1.0 - 0.0006 < qq && qq < 1.0 + 0.0006
}
pub fn invert_rot(a: Rot) -> Rot {
Rot { c: a.c, s: -a.s }
}
pub fn nlerp(q1: Rot, q2: Rot, t: f32) -> Rot {
let omt = 1.0 - t;
let q = Rot {
c: omt * q1.c + t * q2.c,
s: omt * q1.s + t * q2.s,
};
let mag = (q.s * q.s + q.c * q.c).sqrt();
let inv_mag = if mag > 0.0 { 1.0 / mag } else { 0.0 };
Rot {
c: q.c * inv_mag,
s: q.s * inv_mag,
}
}
pub fn compute_angular_velocity(q1: Rot, q2: Rot, inv_h: f32) -> f32 {
inv_h * (q2.s * q1.c - q2.c * q1.s)
}
pub fn rot_get_angle(q: Rot) -> f32 {
atan2(q.s, q.c)
}
pub fn rot_get_x_axis(q: Rot) -> Vec2 {
Vec2 { x: q.c, y: q.s }
}
pub fn rot_get_y_axis(q: Rot) -> Vec2 {
Vec2 { x: -q.s, y: q.c }
}
pub fn mul_rot(q: Rot, r: Rot) -> Rot {
Rot {
s: q.s * r.c + q.c * r.s,
c: q.c * r.c - q.s * r.s,
}
}
pub fn inv_mul_rot(a: Rot, b: Rot) -> Rot {
Rot {
s: a.c * b.s - a.s * b.c,
c: a.c * b.c + a.s * b.s,
}
}
pub fn relative_angle(a: Rot, b: Rot) -> f32 {
let s = a.c * b.s - a.s * b.c;
let c = a.c * b.c + a.s * b.s;
atan2(s, c)
}
pub fn unwind_angle(radians: f32) -> f32 {
remainder_f32(radians, 2.0 * PI)
}
fn remainder_f32(x: f32, y: f32) -> f32 {
if y == 0.0 || x.is_infinite() || x.is_nan() || y.is_nan() {
return f32::NAN;
}
let q = (x as f64 / y as f64).round_ties_even();
(x as f64 - q * y as f64) as f32
}
pub fn rotate_vector(q: Rot, v: Vec2) -> Vec2 {
Vec2 {
x: q.c * v.x - q.s * v.y,
y: q.s * v.x + q.c * v.y,
}
}
pub fn inv_rotate_vector(q: Rot, v: Vec2) -> Vec2 {
Vec2 {
x: q.c * v.x + q.s * v.y,
y: -q.s * v.x + q.c * v.y,
}
}