QUATERNION(3)

πŸ“¦ version 0_git20260208, in alpine 3.24, arch rolling, nixos 26.05, nixpkgs unstable

πŸ’… QUATERNION(3) β€” bestie's guide to quaternion math

okay so first things first: this is the QUATERNION(3) page from the Library Functions Manual, and it's literally all about quaternion arithmetic. it's giving "math but make it 3D rotation" and honestly? iconic. let's get into it πŸ¦‹


✨ NAME ✨

so the whole squad here is qtom, mtoq, qadd, qsub, qneg, qmul, qdiv, qunit, qinv, qlen, slerp, qmid, and qsqrt β€” and collectively they're the Quaternion arithmetic department. every single one of them is in this page, no crumbs left behind πŸŽ€


🌸 SYNOPSIS 🌸

grab your headers first, bestie:

#include <draw.h>

#include <geometry.h>

and here's the full roster of function signatures β€” copy-paste ready, no cap:

Quaternion qadd(Quaternion q, Quaternion r)

Quaternion qsub(Quaternion q, Quaternion r)

Quaternion qneg(Quaternion q)

Quaternion qmul(Quaternion q, Quaternion r)

Quaternion qdiv(Quaternion q, Quaternion r)

Quaternion qinv(Quaternion q)

double qlen(Quaternion p)

Quaternion qunit(Quaternion q)

void qtom(Matrix m, Quaternion q)

Quaternion mtoq(Matrix mat)

Quaternion slerp(Quaternion q, Quaternion r, double a)

Quaternion qmid(Quaternion q, Quaternion r)

Quaternion qsqrt(Quaternion q)

like, look at all of them. the whole family showed up πŸ’–


✨ DESCRIPTION ✨

🧚 the lore (aka what even IS a quaternion)

okay so. the Quaternions are a non-commutative extension field of the Real numbers, and they were designed to do for rotations in 3-space what the complex numbers do for rotations in 2-space. literally the glow-up of complex numbers, we love to see it πŸ‘‘

a quaternion has a real component r and an imaginary vector component v=(i,j,k). they add componentwise, and they multiply according to this rule:

(r,v)(s,w)=(rs-v.w, rw+vs+vΓ—w)

where . and Γ— are the ordinary vector dot and cross products. and the multiplicative inverse of a non-zero quaternion (r,v) is:

(r,-v)/(r2-v.v)
⚠️ note the "non-zero" bestie β€” that inverse only exists when it exists. don't come for me, that's just how it is πŸ™ˆ

🫢 the struct (so you know what you're holding)

the following routines do arithmetic on quaternions, represented as:

typedef struct Quaternion Quaternion;
struct Quaternion{
      double r, i, j, k;
};

four doubles. that's it. that's the whole vibe. r, i, j, k, and honestly the way these four little fields run the entire 3D rotation economy is giving main character energy ⭐

πŸ’… the routine rundown

  • qadd β€” Add two quaternions.
  • qsub β€” Subtract two quaternions.
  • qneg β€” Negate a quaternion.
  • qmul β€” Multiply two quaternions.
  • qdiv β€” Divide two quaternions.
  • qinv β€” Return the multiplicative inverse of a quaternion.
  • qlen β€” Return sqrt(q.r*q.r+q.i*q.i+q.j*q.j+q.k*q.k), the length of a quaternion.
  • qunit β€” Return a unit quaternion (length=1) with components proportional to q's.

like, clean. simple. each one does exactly one thing and does it well. periodt 🌈

πŸ¦‹ rotations, the actual reason you're here

so a rotation by angle ΞΈ about axis A (where A is a unit vector) can be represented by the unit quaternion:

q=(cos ΞΈ/2, Asin ΞΈ/2)

and here's the iconic twist: the same rotation is represented by βˆ’q. also, a rotation by βˆ’ΞΈ about βˆ’A is the same as a rotation by ΞΈ about A. double coverage, no notes πŸ’€

the quaternion q transforms points by:

(0,x',y',z') = q-1(0,x,y,z)q

and quaternion multiplication composes rotations β€” stack 'em, chain 'em, they just work ✨

the orientation of an object in 3-space can be represented by a quaternion giving its rotation relative to some standard orientation. that's the whole concept, and honestly it ate.

🌟 the routines that operate on rotations / orientations (as unit quaternions)

  • mtoq β€” Convert a rotation matrix (see matrix(3)) to a unit quaternion.
  • qtom β€” Convert a unit quaternion to a rotation matrix.
  • slerp β€” Spherical lerp. Interpolate between two orientations. The rotation that carries q to r is q-1r, so slerp(q, r, t) is q(q-1r)t.
  • qmid β€” slerp(q, r, .5)
  • qsqrt β€” The square root of q. This is just a rotation about the same axis by half the angle.

ngl slerp is the moment. spherical interpolation? the way it just smoothly carries you from one orientation to another? obsessed πŸ’œ


πŸŽ€ SOURCE πŸŽ€

/src/libgeometry/quaternion.c

that's where she lives, if you ever wanna go visit 🏠


πŸ”₯ SEE ALSO πŸ”₯

go read those too, bestie, they're friends of the family 🫢


πŸ’€ BUGS πŸ’€

okay so this is important and kind of a jump-scare: to avoid name conflicts with NetBSD, qdiv is a preprocessor macro defined as p9qdiv; see intro(3).

like β€” yes, the function is called qdiv, but under the hood the preprocessor is out here living a double life as p9qdiv. don't get caught lacking by that one πŸ™ˆ


✨ that's the whole page, you're officially quaternion-literate ✨

this was the QUATERNION(3) page, from the Library Functions Manual, sourced from /src/libgeometry/quaternion.c β€” and yeah, no date stamped on this one, she's timeless πŸ’… see you in the next man page, bestie πŸ’–