# Very handy matrix functions - part 1

• 05-09-2004
VirtualAce
Very handy matrix functions - part 1
I finished reading my 3D math book and let me tell you it was full of information that I've been searching for...for a very long time.

Granted the D3DX library of functions can do most anything with matrices but it is nice to know the math behind it.

For instance...here is how to find the determinant of a 2D matrix.

M=
[m11 m12]
[m21 m22]

(:<X>: denotes the determinant of matrix X)

:M:=((m11m22)-(m12m21))

So for a 3x3 would be:

M=
[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]

((m11m22m33)+(m12m23m31)+(m13m21m32))-
((m13m22m31)+(m12m21m33)+(m11m23m32))

=

m11(m22m33-m23m32)+m12(m23m31-m21m33)+m13(m21m32-m22m31)

But this changes for an n x n matrix.

Essentially you must divide the matrix up into submatrixes called cofactors. A cofactor is obtained by simply discarding the rows stated. So C11 would mean to discard the 1st column and 1st row - the matrix you have left is the cofactor.

Take the sum of all the determinants of the cofactors and you have the determinant of the matrix.

Here is an example of a cofactor:

M=
[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]

C11=
[m22 m23]
[m32 m33]

:C11:=(m22m33)-(m23m32)

So:
:C11:+
:C12:+
:C13:+
:C21:+
:C22:+
:C23:+
:C31:+
:C32:+
:C33:=
:M:

Now using this you can compute the inverse of a matrix...if it has one.

Once you compute the cofactors you can then find the adjoint of M

So our matrix of cofactors now looks like this (w/o having actually computed the determinants of the cofactors):

A=
[c11 c12 c13]
[c21 c22 c23]
[c31 c32 c33]

[c11 c21 c31]
[c12 c22 c32]
[c13 c23 c33]

Find the inverse by now dividing by the determinant of M

[c11 c21 c31]
[c12 c22 c32]
[c13 c23 c33]
-----------------
:M:

or

(X^-1 denotes X to the -1 or the inverse of X)

M^-1=
[c11/:M: c21/:M: c31/:M:]
[c12/:M: c22/:M: c32/:M:]
[c13/:M: c23/:M: c33/:M:]

so:

To test whether or not a matrix even has an inverse - its determinant cannot be zero. So if the determinant of a matrix is non-zero then it does have an inverse else it does not.

I've been looking for this info for a long time and finally found a good explanation of it.

Final XYZ rotation matrix

cosx=cos(x)
sinx=sin(x)

cosy=cos(y)
siny=sin(y)

cosz=cos(z)
sinz=sin(z)

R=
[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]

m11=(cosy)(cosz)+(siny)(sinx)(siny)
m12=(-cosy)(sinz)+(siny)(sinx)(cosz)
m13=(siny)(cosx)

m21=(sinz)(cosx)
m22=(cosz)(cosx)
m23=(-sinx)

m31=(-siny)(cosz)+(cosy)(sinx)(sinz)
m32=(sinz)(siny)+(cosy)(sinx)(cosz)
m33=(cosy)(cosx)
• 05-09-2004
VirtualAce
I have NO idea why this posted twice...and I cant delete either one.

• 05-09-2004
Does your book explain WHY matrices work in the first place? That's the one thing I've never had explained...I've read all of the rules for using them, but I don't get why multiplying matrices together, or multiplying them by something else or doing inverses or determinants etc even represents anything.
• 05-10-2004
VirtualAce
Yes..but I already knew about most of the matrix part from way back when. I just didn't know how to find the inverse...if there was one...to a matrix. Most texts called it out of the scope of the article which really got old after awhile.

www.gamedev.net has an excellent explanation of why and how matrices work but you can figure it out on your own.

If you look at a vector it is in reality a matrix.

V=[x y z]

A matrix is simply an array of vectors.

A square matrix is one who has equal number of rows and columns.

For instance a 3x3 matrix.

M=
[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]

The diagonal of this matrix is m11 m22 m33.

But here is the beauty of a matrix -> matrix multiplication or concatenation of matrices.

We all know that transformation is a linear process. Each transform must be done in a certain order (somewhat) and each one requires quite a bit of multiplication. Wouldn't it be nice to be able to multiply once by already transformed values? This would transform your vertex with one multiply. Well with matrices you can do just that. You start with an identity matrix. Then you create a translation matrix. Then you do rotations about x,y,z or arbitrary axes..whichever you choose. Multiply the translation matrix by the rotation matrix and you get a new matrix which is the result of the multiplication. Now you can use this new matrix as one of the operands in your next multiplication. Now you can do scaling on x,y,z or arbitrary axes. Multiply them together and you have effectively done a world transform.

The first step is from object space to inertial space. This a non-affine transform or simply a transform that does not have translation in it. So scaling and rotation are all non-affine transforms.

To transform a vertex from object space to inertial space simply concatentate the rotation matrix with the scaling matrix and then multiply your vector by the concatenated matrix.

Now you can perform translation which will 'move' your object to the correct world coordinates. Multiply this matrix by the concatenated matrix from above and you have done a world transform.

Now you need to construct a projection matrix to project from world space to camera space and then you need a clip matrix to transform from camera space to clip space.

Confused? It's really not too hard once you do it.

Here is how you multipy a scalar by a matrix.

kM=
[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]
=
[km11 km12 km13]
[km21 km22 km23]
[km31 km32 km33]

Here is how you multiply two matrices together.

The number of columns in A must match the number of rows in B or AB is undefined - they cannot be multiplied together.

Here is how you multiply a matrix together.

Quote:

3D Math Primer for Graphics and Game Development. Fletcher
Dunn and Ian Parberry

...For each element C(ij) locate row i in A and column j in B. Multiply the corresponding elements of the row and column, and sum the products. (Equivalent to the dot product of row i in A with column j in B.)

A=
[a11 a12]
[a21 a22]
[a31 a32]
[a41 a42]

B=
[b11 b12 b13 b14 b15]
[b21 b22 b23 b24 b25]

AB=

[c11 c12 c13 c14 c15]
[c21 c22 c23 c24 c25]
[c31 c32 c33 c34 c35]
[c41 c42 c43 c44 c45]

c24=a21b14 + a22b24;

Here is a 3x3 example:

AB=

[a11 a12 a13] [b11 b12 b13]
[a21 a22 a23] [b21 b22 b23]
[a31 a32 a33] [b31 b32 b33]

=

[a11b11+a12b21+a13b31 a11b12+a12b22+a13b32 a11b13+a12b23+a13b33]
[a21b11+a22b21+a23b31 a21b12+a22b22+a23b32 a21b13+a22b23+a23b33]
[a31b11+a32b21+a33b31 a31b12+a32b22+a33b32 a31b13+a32b23+a33b33]

I suggest purchasing a book from amazon.com - the one I quoted from is an excellent book. As I said though www.gamedev.net has excellent tutorials on matrices.

In order to understand why matrices transform vertexes you must manually work out the multiplication.

Here is how you multiply a vector by a matrix (code tags are simply to preserve spacing).
Code:

[x y z]*[m11 m12 m13]
[m21 m22 m23]
[m31 m32 m33]

=

[xm11+ym21+zm31  xm12+ym22+zm32  xm13+ym23+zm33]

As to why we use 4x4 matrices in 3D math instead of 3x3 - it's simply a mathematical trick to allow us to put a translation vector into the mix. Without the 4x4 there would be no way to do this. Since we want our pipeline to be relatively similar in operation at each stage...we use 4x4 matrices.

Identity matrix

I=
[1.0 0.0 0.0 0.0]
[0.0 1.0 0.0 0.0]
[0.0 0.0 1.0 0.0]
[0.0 0.0 0.0 1.0]

Multiply matrix A by this matrix results in matrix A. Or more succintly:

AI=A

Scaling matrix - scale on x y z only

s=[x y z w] where w=1.0

M(s)=
[s.x 0.0 0.0 0.0]
[0.0 s.y 0.0 0.0]
[0.0 0 0.s.z 0.0]
[0.0 0.0 0.0 s.w]

If you multiply vector v by this matrix you will get v=[(s.x)x (s.y)y (s.z)z 1.0]

Translation matrix

t=[x y z w] where w=1.0

M(t)=

[1.0 0.0 0.0 0.0]
[0.0 1.0 0.0 0.0]
[0.0 0.0 1.0 0.0]
[t.x t.y t.z t.w]

And finally some C code to multiply these matrices as 2D arrays. However, I rarely use 2D arrays or 1D arrays for matrices.

Code:

//Multiplies two 4x4 matrices together leaving the result in r[]
void MatrixMultiply4x4(float m1[4][4],float m2[4][4],float r[4][4])
{
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
r[i][j]=0.0f;
for (int k=0;k<4;k++)
{
r[i][j]+=m1[i][k]*m2[k][j];
}
}
}
}

• 05-10-2004
You put so much effort into these 'tutorial' type threads. I think you should write something for gamedev.net, because more people will read it.

I think I should try asking something about matrices just because you put all this work into making the threads but I can't come up with anything just quite yet (because it might've been in the thread already, and I haven't read all of it to be honest, because it is a lot).

EDIT:

What exactly is the determinant used for? I see that it is mentioned but I don't see its use (if it is in the thread point it out to me).
• 05-18-2004
Perspective
Quote:

What exactly is the determinant used for?

many things. in particualr, if a matrix has a zero determinant, it is not invertable.
• 05-20-2004
Fordy
All the silly posts have now been removed from this thread
• 05-20-2004
Shakti
Hey Bubba have you ever thought about writing some basic matrix tutorials that covers matrices from the beginning (or for dummies like myself :) ) to some more advanced things like you have posted (I dont understand squat of that lol). I think some here would be interested in such tutorial.

Edit: Damn my english :(
• 05-20-2004
Perspective
Quote:

Originally Posted by Shakti
Hey Bubba have you ever thought about writing some basic matrix tutorials that covers matrix from the beginning (or for dummies like myself :) ) to some more advanced things like you have posted (I dont understand squat of that lol). I think some here would be interested in such tutorial.

On that note, maybe some of bubba's tutorial threads could be moved to the FAQ so we can reference them for people who ask. <ignore me if they are already there, im to lazy to look>