Search guides and the APICtrl K
  1. API reference
  2. Native GUI

gfx/maths3d.h

Three-dimensional vectors, 4x4 matrices, quaternions, and an arcball that turns mouse drags into a rotation.

#include <sonore/gfx/maths3d.h>
On this page

Design notes

Why these live beside the OpenGL classes and not in geometry.h

geometry.h is the 2D world every widget is laid out in, and everything there is float because a knob at 63.5 pixels is a real position. These are the types a shader is FED: a model-view-projection matrix, a camera orbiting a spectrum waterfall, the orientation a user dragged a 3D scope into. Nothing in the 2D toolkit needs them, and nothing here needs a Component -- so they get a header of their own, with no platform code in it, and are usable (and tested) without a GL context at all.

The conventions, stated once

  • Right-handed. A positive rotation about an axis turns counter-clockwise when the axis points at the viewer, which is what every GL tutorial, every textbook and every glm-style library assumes. Getting the hand wrong produces a scene that is mirrored, which does not read as a maths bug -- it reads as "the camera is behind the object".
  • Matrix3D is COLUMN-MAJOR, mat[column * 4 + row], because that is the order glUniformMatrix4fv takes with transpose = GL_FALSE. A row-major store would need a transpose on every upload, or worse, would be uploaded untransposed and work until the first non-symmetric matrix.
  • Products read right to left, as in the maths: (A * B) applied to v is A(B(v)), so projection * view * model is the usual spelling and a point goes through the model first. Transform in geometry.h names its composition then precisely because left-to-right is the trap; here the operator is kept because a reader porting shader maths expects it.
  • Quaternions are unit quaternions whenever they represent a rotation. fromAngle produces one; a product of two is one up to rounding, so anything that accumulates thousands of them -- an arcball does, once per mouse move -- renormalises as it goes. A quaternion that has drifted to length 1.01 rotates AND scales, and the object visibly grows.

Types 4

template <typename Type> class Vector3D

x, y and z, with the arithmetic a shader's inputs need.

template <typename Type> class Matrix3D

A 4x4 matrix, column-major, as OpenGL takes it.

Default-constructed it is the identity -- the one default for which "I forgot to set the model matrix" still draws something.

template <typename Type> class Quaternion

A rotation as a unit quaternion: the vector part and the scalar part.

Why not just matrices: interpolating two rotation matrices element by element produces something that is not a rotation at all -- the object shrinks through the middle of the move -- and composing thousands of them accumulates skew. A quaternion interpolates on the sphere (slerp) and renormalises with one division.

An arcball: mouse drags inside a rectangle turned into a rotation.

The rectangle is treated as the silhouette of a sphere. A point pressed on it is lifted onto the sphere's front surface, and dragging rotates the sphere so the point under the pointer STAYS under the pointer -- which is what makes it feel like grabbing an object rather than steering it. Outside the sphere's outline the point is held on the rim, so a drag around the edge spins about the view axis, the other thing a user expects to be able to do.

Coordinates are this SDK's: logical, y DOWN. The flip to the maths' y-up happens once, in the projection.

↑↓ to move↵ to openEvery public name in the headers, and every guide