[ / main / writing / matrix ]

    Matrix Math



©1997 Jeff Weeks and Codex software

Matrix math is commonly used in 3D engines, unfortunately, I haven't found any tutorials on matrix math itself. I hope this one will help some people out. If you find this tutorial useful, please give me credit. That's all I ask.




Since the most common use of matrix math is 3D math, I will focus on this almost exclusively. What this means is that I will be using 4x4 matrices, and I will be describing typical 3D matrices (rotation, translation, etc).




Okay, with that out of the way, what is a matrix? Simply put, it's an array which holds numbers. In 3D math, we typically use a 4x4 matrix, which is analogous to a 4x4 array.




0, 0 0, 1 0, 2 0, 3
1, 0 1, 1 1, 2 1, 3
2, 0 2, 1 2, 2 2, 3
3, 0 3, 1 3, 2 3, 3

A 4x4 Matrix. Note that Matrices are referenced as (row, column) not (x, y).




Well, that's simple enough, right? But, why do we do it? What's the point? I asked the same questions myself. Matrices have some interesting properties. One of which is the ability to concatenate many math operations into one matrix. What this means is that just one matrix can perform the task of literally hundreds of operations.




Matrices are also very easy to use. A matrix multiply routine is really all you need. The algebra is also fairly well hidden from the programmer which, therefore, makes the code easier to read. And, as one professional told me, matrices are very intuitive. By that he meant that you can look at a matrix, and can actually visualize something as complex as a rotation, just by the way the numbers are aranged.




So, how do we use matices? In computer terms, we simply use a multidimensional array. The only thing that's even the least bit complicated is how to matrix multiply. This is how we concatenate multiple matices into one. The following is how you would matrix multiply a 4x4 matrix, by another 4x4 matrix.




1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
x
A B C D
E F G H
I J K L
M N O P
=
1A+ 2E+ 3I+ 4M 1B+ 2F+ 3J+ 4N 1C+ 2G+ 3K+ 4O 1D+ 2H+ 3L+ 4P
5A+ 6E+ 7I+ 8M 5B+ 6F+ 7J+ 8N 5C+ 6G+ 7K+ 8O 5D+ 6H+ 7L+ 8P
9A+10E+11I+12M 9B+10F+11J+12N 9C+10G+11K+12O 9D+10H+11L+12P
13A+14E+15I+16M 13B+14F+15J+16N 13C+14G+15K+16O 13D+14H+15L+16P



That may look complicated but it really isn't. Just take a look at it and you'll see the simple pattern. Now, you may be thinking, 'Okay, now I can concatenate matrices, but what can I concatenate!' Fair enough. Let's take a look at the matrix form of some 3D algebra.




1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Identity
1 0 0 0
0 cos(x) -sin(x) 0
0 sin(x) cos(x) 0
0 0 0 1
X Rotation
cos(y) 0 sin(y) 0
0 1 0 0
-sin(y) 0 cos(y) 0
0 0 0 1
Y Rotation
cos(z) -sin(z) 0 0
sin(z) cos(z) 0 0
0 0 1 0
0 0 0 1
Z Rotation
1 0 0 Tx
0 1 0 Ty
0 0 1 Tz
0 0 0 1
Translation
Sx 0 0 0
0 Sy 0 0
0 0 Sz 0
0 0 0 1
Scaling



About the only matrix there that you may not understand is the indentity matrix. It is really very simple, actually. It's like multiplying by 1. You can multiply any matrix by the indentity matrix, and the result will be the original matrix.




Okay, now you can concatenate many different operations, including 3D algebra operations, into a single matrix. Now what? How do we use this final matrix? Here's where matrices really shine. If you want to perform all the operations in the final matrix to a 3D point, all you must do is multiply the matrix and the point. The result will be a 3D point transformed by the matrix. Here's what that looks like.




1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
x
X
Y
Z
1
=
1X+ 2Y+ 3Z+ 4
5X+ 6Y+ 7Z+ 8
9X+10Y+11Z+12
13X+14Y+15Z+16



As you can see, in matrix math, we treat 3D points as 4x1 matrices (often called vertices). The points/vertices are homogeneous coordinates, hense the need for the 1. Okay, I supposed now you're thinking how all this can be related to code. It's really quite simple actually, but I will provide a couple functions for completeness.




    Matrix Matrix_Multiply(Matrix mat1, Matrix mat2) {
      int i, j, k;
      Matrix mat;
      // For speed reasons, use the unroll-loops option of your compiler
      for(i = 0; i < 4; i++)
        for(j = 0; j < 4; j++)
          for(k = 0, mat[i][j] = 0; k < 4; k++)
            mat[i][j] += mat1[i][k] * mat2[k][j];
      return mat;
    }
    Vertex Matrix_Vertex_Multiply(Matrix mat, Vertex Vert) {
      Vertex v;
      v.x = vert.x * mat.matrix[0][0] +
            vert.y * mat.matrix[0][1] +
            vert.z * mat.matrix[0][2] +
                     mat.matrix[0][3];
      v.y = vert.x * mat.matrix[1][0] +
            vert.y * mat.matrix[1][1] +
            vert.z * mat.matrix[1][2] +
                     mat.matrix[1][3];
      v.z = vert.x * mat.matrix[2][0] +
            vert.y * mat.matrix[2][1] +
            vert.z * mat.matrix[2][2] +
                     mat.matrix[2][3];
      return v;
    }



That should be enough to start you off. If anybody happens to find any errors, or would like extra clarification, please mail me.