# Matrix Details

## Matrix Details

A matrix is a rectangular array that can describe a transformation from one coordinate system to another. Transformations include translation (shifting), scaling, and rotation. Functions dealing with matrices begin with "mat". A 3x3 or 4x4 matrix has 9 or 16 elements, respectively.

This section contains detailed information on matrices.

## Contents

## Arrangement

In mathematical publications, matrices are often notated in column-major order, in which each element of the matrix is placed in columns as opposed to rows, as in the following example:

$\left[\begin{array}{cccc}\mathrm{matrix[0]}& \mathrm{matrix[4]}& \mathrm{matrix[8]}& \mathrm{matrix[12]}\\ \mathrm{matrix[1]}& \mathrm{matrix[5]}& \mathrm{matrix[9]}& \mathrm{matrix[13]}\\ \mathrm{matrix[2]}& \mathrm{matrix[6]}& \mathrm{matrix[10]}& \mathrm{matrix[14]}\\ \mathrm{matrix[3]}& \mathrm{matrix[7]}& \mathrm{matrix[11]}& \mathrm{matrix[15]}\end{array}\right]$The numbers in brackets in the matrix above are the zero-based indices
into the matrix arrays passed to `H3DU.Math`

's matrix methods.

For 3x3 matrices, the elements are arranged in the following order:

$\left[\begin{array}{ccc}\mathrm{matrix[0]}& \mathrm{matrix[3]}& \mathrm{matrix[6]}\\ \mathrm{matrix[1]}& \mathrm{matrix[4]}& \mathrm{matrix[7]}\\ \mathrm{matrix[2]}& \mathrm{matrix[5]}& \mathrm{matrix[8]}\end{array}\right]$### A Matrix Transforms Between Coordinate Systems

A transformed 3D coordinate system is made up of an X, Y, and Z axis, and a center of the coordinate system. These are four 3-element vectors that describe how the three axes and the center map to the new coordinate system in relation to the old coordinate system.

The following depiction of a 4x4 matrix illustrates the meaning of each of its elements. To keep things simple, this matrix's transformation is one that keeps straight lines straight and parallel lines parallel.

$\left[\begin{array}{cccc}\mathrm{[0]\; X-axis\; X}& \mathrm{[4]\; Y-axis\; X}& \mathrm{[8]\; Z-axis\; X}& \mathrm{[12]\; Center\; X}\\ \mathrm{[1]\; X-axis\; Y}& \mathrm{[5]\; Y-axis\; Y}& \mathrm{[9]\; Z-axis\; Y}& \mathrm{[13]\; Center\; Y}\\ \mathrm{[2]\; X-axis\; Z}& \mathrm{[6]\; Y-axis\; Z}& \mathrm{[10]\; Z-axis\; Z}& \mathrm{[14]\; Center\; Z}\\ \mathrm{[3]\; 0}& \mathrm{[7]\; 0}& \mathrm{[11]\; 0}& \mathrm{[15]\; 1}\end{array}\right]$The following is an example of a transformation matrix.

$\left[\begin{array}{cccc}1& 0& 0& 2\\ 0& \mathrm{0.5}& -0.866025& 3\\ 0& \mathrm{0.866025}& \mathrm{0.5}& 4\\ 0& 0& 0& 1\end{array}\right]$Here, the first column shows an X-axis vector at (1, 0, 0), the second column shows a Y-axis vector at (0, 0.5, 0.866025), the third column shows a Z-axis vector at (0, -0.866025, 0.5), and the fourth column centers the coordinate system at (2, 3, 4).

Provided the matrix can be inverted, the three axis vectors are
*basis vectors* of the coordinate system.

### Why a 4x4 Matrix?

A matrix can describe *linear transformations* from one vector in space
to another. These transformations, which include scaling,
rotation, and shearing, can change where a vector points *at*,
but not where it points *from*. It's enough to use a 3x3 matrix to describe
linear transformations in 3D space.

But certain other transformations, such as translation and perspective, are common in 3D computer graphics. To describe translation and perspective in 3D, the 3x3 matrix must be augmented by an additional row and column, turning it into a 4x4 matrix.

A 4x4 matrix can describe linear transformations in 4D space and
transform 4-element vectors. A 4-element vector has four components:
X, Y, Z, and W. If a 4-element vector represents a 3D point, these
components are the point's *homogeneous coordinates* (unless the
vector's W is 0). To convert these coordinates back to 3D, divide
X, Y, and Z by W. This is usually only required, however, if the
matrix describes a perspective projection (see
"Projective Transformations").

A similar situation applies in 2D between 2x2 and 3x3 matrices as it does in 3D between 3x3 and 4x4 matrices.

## Transforming Points

The transformation formula multiplies a matrix by a 3D point to change that point's position:

**a′**_{x}= matrix[0] ⋅**a**_{x}+ matrix[4] ⋅**a**_{y}+ matrix[8] ⋅**a**_{z}+ matrix[12] ⋅**a**_{w}**a′**_{y}= matrix[1] ⋅**a**_{x}+ matrix[5] ⋅**a**_{y}+ matrix[9] ⋅**a**_{z}+ matrix[13] ⋅**a**_{w}**a′**_{z}= matrix[2] ⋅**a**_{x}+ matrix[6] ⋅**a**_{y}+ matrix[10] ⋅**a**_{z}+ matrix[14] ⋅**a**_{w}**a′**_{w}= matrix[3] ⋅**a**_{x}+ matrix[7] ⋅**a**_{y}+ matrix[11] ⋅**a**_{z}+ matrix[15] ⋅**a**_{w}

For more on why **a′**_{w} appears here, see "Why a 4x4 Matrix?". In each formula that follows, **a**_{w} is assumed to be 1 (indicating a conventional 3D point).

The following sections describe different kinds of matrix transformations in more detail.

Related functions:

- H3DU.Math.mat4transform() - Transforms a 4-element vector with a 4x4 matrix
- H3DU.Math.mat3transform() - Transforms a 3-element vector with a 3x3 matrix
- H3DU.Math.mat4projectVec3 - Does a perspective-correct transformation of a 3D point with a 4x4 matrix

### Scaling

Scaling changes an object's size. Scaling uses the 1st, 6th, and 11th elements of the matrix as seen here:

$\left[\begin{array}{cccc}\mathrm{sx}& 0& 0& 0\\ 0& \mathrm{sy}& 0& 0\\ 0& 0& \mathrm{sz}& 0\\ 0& 0& 0& 1\end{array}\right]$where the X coordinate is multiplied by `sx`

, the Y coordinate is multiplied by `sy`

, and
the Z coordinate is multiplied by `sz`

.

The scaling formula would look like:

**a′**_{x}= sx ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 0**a′**_{y}= 0 ⋅**a**_{x}+ sy ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 0**a′**_{z}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ sz ⋅**a**_{z}+ 0**a′**_{w}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 1 = 1

For example, we multiply the input x by `sx`

to get the output x. If `sx`

is 1, x
remains unchanged. Likewise for y and z.

If `sx`

, `sy`

, or `sz`

is -1, that coordinate is *reflected* along the corresponding axis.

If `sx`

, `sy`

, and `sz`

are all 1, we have an *identity matrix*, where the input vector
is equal to the output vector.

When the transformed X, Y, or Z axis has a length other than 1, the coordinate
system will be scaled up or down along that axis. The scalings given
here will scale the lengths of the corresponding axes. For example,
if `sx`

is 2, the X axis will be (2, 0, 0) and thus have a length of 2.

Related functions:

- H3DU.Math.mat4scaled() - Returns a scaling matrix
- H3DU.Math.mat4scale() - Multiplies a matrix by a scaling.
- H3DU.Math.mat4scaleInPlace() - Multiplies a matrix in place by a scaling.
- H3DU.Math.mat4identity() - Returns a 4x4 identity matrix
- H3DU.Math.mat3identity() - Returns a 3x3 identity matrix

### Translation

A translation is a shifting of an object's position. In a transformation matrix, this shifting effectively happens after all other transformations such as scaling and rotation. It uses the 13th, 14th, and 15th elements of the matrix as seen here:

$\left[\begin{array}{cccc}1& 0& 0& \mathrm{tx}\\ 0& 1& 0& \mathrm{ty}\\ 0& 0& 1& \mathrm{tz}\\ 0& 0& 0& 1\end{array}\right]$where `tx`

is added to the X coordinate, `ty`

is added to the Y coordinate, and
`tz`

is added to the Z coordinate. The transformation formulas would look like:

**a′**_{x}= 1 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ tx**a′**_{y}= 0 ⋅**a**_{x}+ 1 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ ty**a′**_{z}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 1 ⋅**a**_{z}+ tz**a′**_{w}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 1 = 1

For example, we add the input x and `tx`

to get the output x. If `tx`

is 0, x
remains unchanged. Likewise for y and z.

Related functions:

- H3DU.Math.mat4translated() - Returns a translation matrix
- H3DU.Math.mat4translate() - Multiplies a matrix by a translation.

### Rotation

Rotation changes an object's orientation. Given an angle of rotation, θ, the transformation matrix for rotating 3D points is as follows. (For a list of common sines and cosines, see the end of this section.)

Note that:

- When we rotate a point about the X axis, the X coordinate is unchanged and the Y and Z coordinates are adjusted in the rotation. For rotations about the Y axis or the Z axis, the Y or Z coordinate, respectively, is likewise unchanged.
- If the axis of rotation points toward the viewer, positive rotations mean counterclockwise rotation in right-handed coordinate systems. For example, 60 degrees about the axis means 60 degrees counterclockwise, and negative 60 degrees means 60 degrees clockwise.
- Rotating a point around an arbitrary axis of rotation is more complicated to describe.
When describing an axis of rotation,
`[1, 0, 0]`

is the X axis,`[0, 1, 0]`

is the Y axis, and`[0, 0, 1]`

is the Z axis.

See "Rotation example" for an illustration of a rotation transformation.

Related functions:

- H3DU.Math.mat4rotated() - Returns a rotation matrix
- H3DU.Math.mat4rotate() - Multiplies a matrix by a translation.

A list of common sines and cosines follows. Values shown with three decimal places are approximate.

0° | 22.5° | 30° | 45° | 60° | 67.5° | 90° | 112.5° | 120° | 135° | 150° | 157.5° | 180° | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|

sin | 0 | 0.383 | 0.5 | 0.707 | 0.866 | 0.924 | 1 | 0.924 | 0.866 | 0.707 | 0.5 | 0.383 | 0 |

cos | 1 | 0.924 | 0.866 | 0.707 | 0.5 | 0.383 | 0 | -0.383 | -0.5 | -0.707 | -0.866 | -0.924 | -1 |

180° | 202.5° | 210° | 225° | 240° | 247.5° | 270° | 292.5° | 300° | 315° | 330° | 337.5° | 360° | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|

sin | 0 | -0.383 | -0.5 | -0.707 | -0.866 | -0.924 | -1 | -0.924 | -0.866 | -0.707 | -0.5 | -0.383 | 0 |

cos | -1 | -0.924 | -0.866 | -0.707 | -0.5 | -0.383 | 0 | 0.383 | 0.5 | 0.707 | 0.866 | 0.924 | 1 |

### Matrix Multiplication

When two matrices are multiplied, the combined matrix will be such that the transformations they describe happen in reverse order. For example, if the first matrix (input matrix) describes a translation and the second matrix describes a scaling, the multiplied matrix will describe the effect of scaling then translation.

Matrix multiplication is not commutative; the order of multiplying matrices is important.

To get an insight of how matrix multiplication works, treat the second matrix as a group of column vectors (with the same number of rows as the number of columns in the first matrix). Multiplying the two matrices transforms these vectors to new ones in the same way as if the column vectors were transformed individually. (This also explains why there can be one or more column vectors in the second matrix and not just four in the case of a 4x4 matrix, and also why transforming a column vector is the same as multiplying a 4x4 matrix by a matrix with one column and four rows.*)

This insight reveals a practical use of matrix multiplication: transforming four 4-element vectors at once using a single matrix operation involving two 4x4 matrices. After the matrix multiplication, each of the transformed vectors will be contained in one of the four columns of the output matrix.

The methods `mat4multiply`

, `mat4scale`

, `mat4scaleInPlace`

, `mat4translate`

, and
mat4rotate involve multiplying 4x4 matrices.

Related functions:

- H3DU.Math.mat4multiply() - Multiplies two matrices

* Reading the tutorial by Dmitry Sokolov led me to this highly useful insight.

### Projective Transformations

In all the transformations described above, the last row in the transformation matrix is
(0, 0, 0, 1). (Such transformations are called *affine transformations*, those that
keep parallel lines parallel.) However, this is not the case for
some transformations in the `H3DU.Math`

library.

Transformations that don't necessarily preserve parallelism of lines are called *projective transformations*.
An NxN matrix can describe certain projective transformations if it has one more row and one more column
than the number of dimensions. For example, a 4x4 matrix can describe 3D projective transformations
in the form of linear transformations on homogeneous coordinates (see
"Why a 4x4 Matrix?"). For a 3D projective transformation, the last row
in the matrix is not necessarily (0, 0, 0, 1).

One example of a projective transformation is found in a *perspective projection* matrix,
as returned by H3DU.Math.mat4perspective or H3DU.Math.mat4frustum. When
a 4-element vector is transformed with this matrix, its W component is generated by setting
it to the negative Z coordinate in *eye space*, or more specifically, as follows:

**a′**_{w}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ -1 ⋅**a**_{z}+ 0

For more on perspective projections, see *The "Camera" and Geometric Transforms*.

Related functions:

- H3DU.Math.mat4frustum() - Returns a frustum matrix
- H3DU.Math.mat4perspective() - Returns a field-of-view perspective matrix

### Matrix Inversions

An inverted matrix describes a transformation that undoes another transformation. For example, if a scaling enlarges an object, the inverted matrix reduces the object to its original size.

To invert a **translation**, reverse the sign of the translation elements (given above as `tx`

, `ty`

, and `tz`

)
and generate a new translation matrix with the new translation elements. For example,
to invert the translation (5, 2, -3), use the translation (-5, -2, 3).

To invert a **scaling**, use 1 divided by each of the scaling elements (given above as `sx`

, `sy`

, and `sz`

)
and generate a new scaling matrix with those elements.
For example, to invert the scaling (2, 3, 4), use the scaling (1/2, 1/3, 1/4).

To invert a **rotation** for a 4x4 matrix, swap the 2nd and 5th elements of the matrix,
the 3rd and 9th elements, and the 7th and 10th elements of the matrix (zero-based
elements 1, 4, 2, 8, 6, and 9 respectively). The effect is like reversing the angle of the
rotation to reset an object to its previous orientation. In general, to invert an NxN
rotation matrix, *transpose* that matrix (so that its rows become its columns and vice versa).

#### Inverting a General NxN Matrix

Matrices that use some combination of translation, scaling, and rotation as well as other kinds of matrices are more complicated to invert. In fact, some matrices can't be inverted at all. Many 4x4 or 3x3 matrices can be inverted using the H3DU.Math.mat4invert() or H3DU.Math.mat3invert() methods, respectively.

To describe how inverting a matrix works, we will need to define some terms:

- A matrix cell's
*row index*and*column index*tell where that cell appears in the matrix. For example, a cell on the first row has row index 0 and a cell on the second column has column index 1. - A matrix's
*minor*at a given cell is a smaller matrix generated by eliminating the row and column where that cell appears. - A matrix's
*determinant*is its overall scaling factor. Only an NxN matrix with a determinant other than 0 can be inverted. To find a matrix's determinant:- For each cell in the first row (or first column), find the determinant of the matrix's minor at that cell.
- Label the minors' determinants (A, B, C, D, ...), in that order.
- The matrix's determinant is (A - B + C - D + ...).

To invert an NxN matrix:

- Create a new NxN matrix.
- For each cell in the original matrix, find the determinant of its minor at that cell, and set the corresponding cell in the new matrix to that value.
- In the new matrix, reverse the sign of each cell whose row index plus column index is odd. (These cells will alternate in a checkerboard pattern in the matrix.)
- Transpose the new matrix (convert its rows to columns and vice versa).
- Find the original matrix's determinant and divide each cell in the new matrix by that value.
- The new matrix will be the inverted form of the original NxN matrix.

## Rotation Example

As an example, say we rotate 60 degrees about the X axis (`mat4rotated(60, 1, 0, 0)`

,
θ = 60°). First, we find the rotation formula for the X axis:

**a′**_{x}= 1 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 0**a′**_{y}= 0 ⋅**a**_{x}+ (cos θ) ⋅**a**_{y}+ -(sin θ) ⋅**a**_{z}+ 0**a′**_{z}= 0 ⋅**a**_{x}+ (sin θ) ⋅**a**_{y}+ (cos θ) ⋅**a**_{z}+ 0**a′**_{w}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 1 = 1

We calculate *cos θ* as 0.5 and *sin θ* as about 0.866025.
We plug those numbers into the rotation formula to get a formula for rotating a
point 60 degrees about the X axis.

**a′**_{x}= 1 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 0 =**a**_{x}**a′**_{y}~= 0 ⋅**a**_{x}+ 0.5 ⋅**a**_{y}+ -0.866025 ⋅**a**_{z}+ 0**a′**_{z}~= 0 ⋅**a**_{x}+ 0.866025 ⋅**a**_{y}+ 0.5 ⋅**a**_{z}+ 0**a′**_{w}= 0 ⋅**a**_{x}+ 0 ⋅**a**_{y}+ 0 ⋅**a**_{z}+ 1 = 1

If a point is located at (10, 20, 30), the rotated point would now be:

**a′**_{x}= 1 ⋅ 10 + 0 ⋅ 20 + 0 ⋅ 30 + 0- = 1 ⋅ 10
- = 10
**a′**_{y}~= 0 ⋅ 10 + 0.5 ⋅ 20 + -0.866025 ⋅ 30 + 0- ~= 0.5 ⋅ 20 + -0.866025 ⋅ 30
- ~= 10 + -25.98075
- ~= -15.98075
**a′**_{z}~= 0 ⋅ 10 + 0.866025 ⋅ 20 + 0.5 ⋅ 30 + 0- ~= 0.866025 ⋅ 20 + 0.5 ⋅ 30
- ~= 17.3205 + 15
- ~= 32.3205
**a′**_{w}= 0 ⋅ 10 + 0 ⋅ 20 + 0 ⋅ 30 + 1- = 1

So the rotated point would be at about (10, -15.98075, 32.3205).