Initializing 3D Canvas...

The Matrix

1 min read1 page

From specific to generic

We accept points as specific instances of vectors, either a 2D or a 3D vector. They are a specific instance, because vectors can be 1D, 2D, 3D, 4D .... nD.

A vector being a list of numbers, with however many dimensions, can still sit within a higher dimension space - we call that a matrix. In this sense we can consider a vector to be a specific instance of a matrix, that either has 4 rows * 1 column or 4 columns * 1 row. Naturally this is a 2d matrix, which if everything above made sense, it necesarily follows that a 2d matrix is just a specific instance of a matrix which can be n-dimensional.

4 Rows × 1 Column Matrix
[x]
[y]
[z]
[w]
1 Column × 4 Rows Matrix
[x, y, z, w]

As described above (but we won't dive into that) a matrix can be n dimensional, at most lets say it can be m*n*t (m rows, n columns, t transpositions), can go higher but not relevant in this context.

the point is a specific instance of a vector
the vector is a specific instance of a matrix
2 min read1 page

The Core Idea

Modern 3D graphics is built on one core mathematical tool: the 4×4 transformation matrix. Every object in engines like Unity, Unreal, Blender, or WebGL is constantly transformed using them.

In 3D graphics, every point in space is represented as a column vector. Notice the extra coordinate at the bottom:

python
1# A 3D point is represented as a 4×1 column vector:
2# v = [x, y, z, 1]^T
3v = [
4 [x],
5 [y],
6 [z],
7 [1] # The w (homogeneous) coordinate!
8]
Why the extra 1? This extra value is called the homogeneous coordinate (w). Without it, simple translation (shifting points) cannot be achieved via matrix multiplication. That is why 3D graphics uses 4×4 matrices instead of 3×3 matrices.
X
3.00
Y
3.50
Z
2.00
Up untill this point, nothing different it is as if just defining a point/vector.
1 min read1 page

The Structure of a 4×4 Matrix

A general 3D transformation matrix contains several different operations encoded into exactly 16 numbers. It is divided into logical blocks that each serve a distinct purpose:

SectionPurpose
Upper-Left 3×3Rotation and Scaling
Right ColumnTranslation (Position)
Bottom RowHomogeneous Coordinate Mechanics
Use the dropdown above to highlight and activate the different sections of the matrix and see how they map directly to 3D space behaviors!
switch transform
1 min read1 page

Why 4x4 Instead of 3x3?

A standard 3x3 matrix can rotate, scale, and shear space. However, it is mathematically impossible for a 3x3 matrix to translate (move) an object.

A 3x3 matrix multiplication always maps the origin vector [0, 0, 0] strictly to [0, 0, 0]. It cannot add standalone translation constants like +5 or -2.

Observe the origin (Red Point): In 3x3 mode, changing Translation Sliders does nothing because the origin remains locked at [0, 0, 0]. Switching to 4x4 mode allows translation to occur because the homogeneous coordinate w = 1 activates the translation column!
3x3 vs 4x4
X
2.00
Y
1.50
2 min read1 page

Identity:

The Identity Matrix is the standard “do-nothing” transformation. Applying it to any point or vector leaves it completely unchanged. It acts like the number 1 in ordinary arithmetic.
python
1# The Identity Matrix (I):
2I = [
3 [1.0, 0.0, 0.0, 0.0], # Basis X vector
4 [0.0, 1.0, 0.0, 0.0], # Basis Y vector
5 [0.0, 0.0, 1.0, 0.0], # Basis Z vector
6 [0.0, 0.0, 0.0, 1.0] # Origin offset
7]
A crucial concept in linear algebra is that each column of a transformation matrix is simply the final position of a unit basis vector (X, Y, Z).
Adjust the sliders to warp the X and Y basis vectors. Watch how the corresponding columns of the matrix update live to represent the new coordinate system!
Skew X
0.00
Skew Y
0.00
2 min read1 page

Translation(Vector3d):

Translation shifts an object through 3D space by adding constants to its coordinates. In a 4×4 matrix, the translation amounts occupy the first three cells of the rightmost column: t_x, t_y, and t_z.
python
1# Translation Matrix:
2T = [
3 [1.0, 0.0, 0.0, tx ],
4 [0.0, 1.0, 0.0, ty ],
5 [0.0, 0.0, 1.0, tz ],
6 [0.0, 0.0, 0.0, 1.0]
7]
8# Applied to v = [x, y, z, 1]^T:
9# v_new = [x + tx, y + ty, z + tz, 1]^T
Notice that when translation is performed on points, the homogeneous coordinate w = 1 ensures the translation factor is added. If applied to a pure directional vector (where w = 0), the translation is ignored because directions are position-independent!
Translate X (tx)
1.50
Translate Y (ty)
-1.00
Translate Z (tz)
2.00
2 min read1 page

Scale(Vector3d):

Scaling adjusts the size of an object along individual coordinate axes. In a 4×4 matrix, the scaling factors reside directly on the main diagonal: s_x, s_y, and s_z.
python
1# Scaling Matrix:
2S = [
3 [sx , 0.0, 0.0, 0.0],
4 [0.0, sy , 0.0, 0.0],
5 [0.0, 0.0, sz , 0.0],
6 [0.0, 0.0, 0.0, 1.0]
7]
8# Applied to v = [x, y, z, 1]^T:
9# v_new = [sx*x, sy*y, sz*z, 1]^T
Scaling properties:
s > 1: stretches the object along that axis.
0 < s < 1: squashes the object.
s < 0: mirrors/flips the object across that plane! Try dragging any slider below zero.
Scale X (sx)
1.20
Scale Y (sy)
0.80
Scale Z (sz)
1.50
4 min read1 page

Determinant & Mirroring:

The determinant is a single scalar value that describes how the matrix scales volume. Crucially, if the determinant is negative, the coordinate space has been mirrored (flipped inside-out).
python
1def GetDeterminant(self) -> float:
2 """Calculates the determinant of the 4x4 matrix using Laplace expansion."""
3 m00, m01, m02, m03 = self.m00, self.m01, self.m02, self.m03
4 m10, m11, m12, m13 = self.m10, self.m11, self.m12, self.m13
5 m20, m21, m22, m23 = self.m20, self.m21, self.m22, self.m23
6 m30, m31, m32, m33 = self.m30, self.m31, self.m32, self.m33
7
8 d2_01_01 = m20 * m31 - m21 * m30
9 d2_01_02 = m20 * m32 - m22 * m30
10 d2_01_03 = m20 * m33 - m23 * m30
11 d2_01_12 = m21 * m32 - m22 * m31
12 d2_01_13 = m21 * m33 - m23 * m31
13 d2_01_23 = m22 * m33 - m23 * m32
14
15 minor0 = m11 * d2_01_23 - m12 * d2_01_13 + m13 * d2_01_12
16 minor1 = m10 * d2_01_23 - m12 * d2_01_03 + m13 * d2_01_02
17 minor2 = m10 * d2_01_13 - m11 * d2_01_03 + m13 * d2_01_01
18 minor3 = m10 * d2_01_12 - m11 * d2_01_02 + m12 * d2_01_01
19
20 return m00 * minor0 - m01 * minor1 + m02 * minor2 - m03 * minor3

Mirroring geometry is just scaling by -1 across an axis. However, this flips the matrix determinant to negative, which means mesh faces will render inside-out (normals are inverted).

Scale X
2.00
2 min read1 page

Rotation(Vector3d, float):

Unlike 2D, there is no single universal 3D rotation matrix. Instead, separate matrices exist for rotating around each coordinate axis: X, Y, and Z.
python
1# Rotation Matrices for axes X, Y, and Z:
2# Angle in radians: a
3
4# Rotate X:
5Rx = [
6 [1.0, 0.0, 0.0, 0.0],
7 [0.0, cos(a), -sin(a), 0.0],
8 [0.0, sin(a), cos(a), 0.0],
9 [0.0, 0.0, 0.0, 1.0]
10]
11
12# Rotate Y:
13Ry = [
14 [ cos(a), 0.0, sin(a), 0.0],
15 [ 0.0, 1.0, 0.0, 0.0],
16 [-sin(a), 0.0, cos(a), 0.0],
17 [ 0.0, 0.0, 0.0, 1.0]
18]
19
20# Rotate Z:
21Rz = [
22 [cos(a), -sin(a), 0.0, 0.0],
23 [sin(a), cos(a), 0.0, 0.0],
24 [0.0, 0.0, 1.0, 0.0],
25 [0.0, 0.0, 0.0, 1.0]
26]
AxisBehavior
X-AxisX coordinate remains fixed; Y and Z rotate.
Y-AxisY coordinate remains fixed; X and Z rotate.
Z-AxisZ coordinate remains fixed; X and Y rotate.
Observe how the selected axis remains completely stationary while the other two dimensions perform a circular orbit!
Rotation Axis (0: X, 1: Y, 2: Z)
2.00
Angle (Degrees)
45.00

LookAt(Eye, Target, Up):

Creates a rotation matrix that aligns an object to face a specific target point. This is the most common way to position cameras and orient objects in 3D pipelines.
python
1def LookAt(eye: 'Point3d', target: 'Point3d', up: 'Vector3d') -> 'Matrix4x4':
2 # 1. Forward Vector (Z)
3 forward = (target - eye).Unitize()
4
5 # 2. Right Vector (X) = Cross Product of Up and Forward
6 right = Vector3d.CrossProduct(up, forward).Unitize()
7
8 # 3. True Up Vector (Y) = Cross Product of Forward and Right
9 true_up = Vector3d.CrossProduct(forward, right)
10
11 # Build rotation matrix from these 3 basis vectors
12 return Matrix4x4([
13 right.X, true_up.X, forward.X, eye.X,
14 right.Y, true_up.Y, forward.Y, eye.Y,
15 right.Z, true_up.Z, forward.Z, eye.Z,
16 0, 0, 0, 1
17 ])
Target X
3.00
Target Y
3.00
1 min read1 page

Multiply(Matrix4x4, Matrix4x4):

One of the greatest features of matrices is composition. You can multiply multiple transformation matrices together to bake complex operations (Scale, Rotate, Translate) into a single 4×4 matrix. Instead of running multiple operations per vertex on the CPU, the GPU performs exactly one matrix multiplication.
python
1# Matrix multiplication order goes RIGHT to LEFT:
2# v_new = T * R * S * v
3# 1. Scale first (S)
4# 2. Rotate second (R)
5# 3. Translate last (T)
Matrix multiplication is non-commutative ($AB != BA$). The order of operations matters:
Order: TR vs RT
Translate X
2.50
Angle (Degrees)
45.00
Observe the Orbit!
Rotate then Translate (0): Spins the box in place, then pushes it out. The box stays close.
Translate then Rotate (1): Pushes the box out, then rotates around the origin, causing it to orbit along a large arc!
2 min read1 page

Decompose(Matrix4x4):

The reverse of matrix multiplication. It extracts the raw Translation, Rotation, and Scale values from a baked 4x4 matrix. Essential for UI and animation.
python
1def Decompose(self) -> tuple['Vector3d', 'Quaternion', 'Vector3d']:
2 """Extracts Translation, Rotation, and Scale from a 4x4 matrix."""
3
4 # 1. Translation is easily extracted from the 4th column
5 translation = Vector3d(self.m03, self.m13, self.m23)
6
7 # 2. Scale is the magnitude of the 3 basis vectors (columns)
8 scaleX = Vector3d(self.m00, self.m10, self.m20).Length
9 scaleY = Vector3d(self.m01, self.m11, self.m21).Length
10 scaleZ = Vector3d(self.m02, self.m12, self.m22).Length
11 scale = Vector3d(scaleX, scaleY, scaleZ)
12
13 # 3. Rotation is what's left after removing scale from the 3x3
14 # Usually returned as a Quaternion or Euler angles
15 rotation = ExtractRotation(self)
16
17 return translation, rotation, scale
Translate X
2.00
Scale
1.50
Rotate Z
1.00
1 min read1 page

Invert(Matrix4x4):

3D engines use multiple coordinate systems to map vertices from an artist's creation to the flat pixels on your screen:
  • Local Space: Object's own origin (model-relative).
  • World Space: Scene-wide origin (all models combined).
  • View Space: Relative to camera lens position.
  • Screen Space: Flattened 2D screen coordinates.
python
1# The standard vertex pipeline:
2# MVP = Projection * View * Model
3# v_screen = MVP * v_local
Observe how the coordinates and coordinate framework reshape at each step of the rendering chain!
Local -> Screen
0.00
1 min read1 page

What a Matrix Really Represents

A matrix does not simply “move individual points.” Instead, a matrix transforms the coordinate system itself.

When you apply a matrix to an object, you are warping, rotating, and scaling the entire fabric of space. The object's local coordinates remain unchanged — they only appear to deform because the space they sit in is mathematically reshaped.

Reshaping space: Observe the grid of instanced spheres. As you adjust the sliders, the entire coordinate space stretches, tilts, or shrinks. The basis vectors stretch along with the fabric of space!
Shear Space (X by Y)
0.00
Scale Space
1.00
Rotate Space (Degrees)
0.00