Click or drag to resize
DigitalRune3D Math Conventions

Do you multiply matrices and quaternions from the left or from the right? Do you use a left-handed or a right handed coordinate system? How do you define the front side of a triangle? What units of measurement do you use? – This article explores the math conventions that we use and a few more helpful details...

This topic contains the following sections:

DigitalRune conventions
Coordinate system

We use a standard right-handed coordinate system. Hopefully, everyone is familiar with the Right-Hand Rule. The x-axis is our right axis, the y-axis is our up axis, and the z-axis points to the camera, which means "forward" is –z. To help us with everyday coordinate system troubles, we use following tool: 3D Programmer’s Best Friend

Counter-clockwise orientation and outward pointing normals

If an observer is looking at a front side of a triangle face, the vertices (v0, v1, v2) are oriented counter-clockwise. Face normals are computed using (v1 – v0) x (v2 – v0) and point "outwards". In other words: If an observer is looking at the front side, the normal points to the viewer.

Units

For many game libraries it is not relevant which units of measurement are used. This is not exactly true for all game libraries, especially not for game physics libraries because physics libraries often rely on finely tuned constants. They have default values that assume that the properties of a physics engine are in a certain range. Therefore, we use SI standard units for our game objects (m, s, kg, ... see International System of Units). Angles are measured in radians.

Order of matrix and quaternion multiplications

Matrices

In our libraries, matrices are multiplied from the left (pre-multiplication). That means:

v' = M2 · M1 · v

The transformation of M1 is applied before the transformation of M2. The order depends on whether column vectors or row vectors are used. We have settled on column vectors, which means that we have no other choice than multiplying the matrices from the left side.

In my experience, column vectors are usually preferred by math and physics guys. Whereas, row vectors are preferred by graphics guys. Even in our small team we are divided on this issue but have agreed on column vectors. The same order is used in OpenGL. Other libraries and APIs use post-multiplication, like XNA, DirectX or OpenSceneGraph.

Quaternions

Quaternions are multiplied in the same order:

q' = q2 · q1

q' represents the rotation q1 followed by the rotation q2.

Important note Important

Important XNA note: In XNA matrices and quaternions use a different order of multiplication! That means, XNA uses the same quaternion multiplication order as we do – but it uses the other order for matrix multiplication. In contrast, DirectX and Managed DirectX use the same order for matrices and quaternions.

Changing the multiplication order

Since we are often dealing with libraries that are not under our control, or we are reading scientific papers that use the other multiplication order, we need to be able to switch between them. In the simplest case, we just transpose all matrices, change the order of the matrix and multiply from the other side . But can we follow this rule blindly for all kinds of equations? - When in doubt, I think of vectors as matrices with only 1 row or column and apply matrix rules:

Using our math book we can find a few rules, like:

(A · B)T = BT · AT

Given following equation with two matrices and two column vectors,

v' = M2 · M1 · v

we transpose the whole equation:

v’T = (M2 · M1 · v)T

→ v’T = ((M2 · M1) · v)T

→ v’T = vT · (M2 · M1)T

→ v’T= vT · M1T · M2T

Note that vT is a row vector. We have just converted the equation from OpenGL style to XNA style using mathematics.

Which convention is the best?

I have worked with left-handed and right-handed coordinates systems, inward and outward pointing normals, different units, pre- and post-multiplied matrices… and personally I do not care. My only wish is: If your are a software developer or scientific author, please document which convention you are following and do not assume that everyone is automatically using the same.