viva_math/quaternion
Unit quaternions for 3-D rotation.
A quaternion w + xi + yj + zk extends complex numbers to four
dimensions. Unit quaternions provide a numerically stable,
gimbal-lock-free representation of 3-D rotation that interpolates
smoothly via SLERP.
Conventions
q.wis the scalar (real) part.(q.x, q.y, q.z)is the vector (imaginary) part.- Rotation by angle
θaround unit axis(ax, ay, az):q = cos(θ/2) + sin(θ/2)·(ax·i + ay·j + az·k). - Right-handed coordinates.
When to use
- Smooth interpolation between two orientations (
slerp). - Composing rotations without matrix multiplication overhead.
- Avoiding gimbal lock present in Euler-angle representations.
Types
pub type Quaternion {
Quaternion(w: Float, x: Float, y: Float, z: Float)
}
Constructors
-
Quaternion(w: Float, x: Float, y: Float, z: Float)
Values
pub fn conjugate(q: Quaternion) -> Quaternion
Quaternion conjugate (w, -x, -y, -z). For unit quaternions this is the inverse.
pub fn dot(a: Quaternion, b: Quaternion) -> Float
Quaternion-quaternion dot product (treating each as a 4-vector).
pub fn from_axis_angle(
axis: vector.Vec3,
theta: Float,
) -> Quaternion
Build a unit quaternion from an axis-angle representation.
axis need not be normalised — this function normalises it. theta is
the rotation angle in radians.
pub fn inverse(q: Quaternion) -> Quaternion
Inverse conj(q) / |q|². For unit quaternions equals the conjugate.
pub fn is_close(a: Quaternion, b: Quaternion, tol: Float) -> Bool
Approximate equality up to a tolerance.
pub fn magnitude_squared(q: Quaternion) -> Float
Squared magnitude (cheaper than magnitude when only comparison is needed).
pub fn mul(a: Quaternion, b: Quaternion) -> Quaternion
Hamilton product a · b. Non-commutative.
pub fn nlerp(
a: Quaternion,
b: Quaternion,
t: Float,
) -> Quaternion
Linear interpolation (LERP) between two quaternions, then normalise.
Cheaper than SLERP but yields non-uniform angular speed. Acceptable for
small angular distances (< ~30°). For large or critical interpolations
use slerp.
pub fn normalize(q: Quaternion) -> Quaternion
Normalise to unit length. Returns identity if the input is zero.
pub fn raw(w: Float, x: Float, y: Float, z: Float) -> Quaternion
Build a quaternion from raw components without normalisation.
pub fn rotate(q: Quaternion, v: vector.Vec3) -> vector.Vec3
Rotate a 3-D vector v by unit quaternion q.
Computes q · v · q⁻¹ using the optimised Rodrigues-style formula that
skips two of the quaternion products.
pub fn slerp(
a: Quaternion,
b: Quaternion,
t: Float,
) -> Quaternion
Spherical linear interpolation (SLERP) — constant angular velocity.
Falls back to nlerp when the angle between the quaternions is very
small (sin(θ) < 1e-6), where SLERP becomes numerically unstable.
pub fn to_axis_angle(q: Quaternion) -> #(vector.Vec3, Float)
Quaternion → axis-angle. Returns (axis, angle) with axis unit-length.
When the rotation is identity returns (z-axis, 0) by convention.