# Posts tagged ‘Matrices’

I’m going to cover broad topics in vectors, matrices and the likes, so i’t may appear that i’m skipping specific’s at time. But hopefully I’ll give a good enough understanding and hopefully be able to add specifics in due course. So onto matrices:

A matrix is an object made up of columns and rows – by association an n x m is row by column matrix of n rows and m columns like so (the …n just denotes the list of values):

M C O L U M N S
N                            ..n
R                            ..n
O                            ..n
W                            ..n
S                             ..n

Another way to look at it is that each column represents a dimension, if we have say a 3 x 3 matrix we can represent an objects orientation, with each row representing an axis:

X0 Y0 Z0
X1 Y1 Z1
X2 Y2 Z2

In this example each row is a vector (direction) with an x, y and z component and by this three dimensional. This vector is also known as a ‘row vector’, similarly if we got the first components of each row we can call that a ‘column vector. Matrices have no know bounds  – theres no limit to them which makes them important in n-dimensional workflows (stuff that i dig).

There are 4 main big functions of matrices – Transpose, multiplication, determinant and inverse. These 4 are the grease that allows powerful manipulation of matrices. We’ll throw mean (average) in there two because its important in data analysis.

Transpose

We’ll start with something relatively simple but that’ll make a difference when we get to multiplication. All that transpose does is swap rows for columns and vice versa. So a matrix that looked like this:

1 2 3
4 5 6

Becomes this:

1 4
2 5
3 6

Doing this in pseudo code we can do something like this:

for i in column:

for j in rows:

collect rows[i][j]

So we’ve  transposed the matrix, why is this important – we’ll to multiply a matrix with another matrix it needs to have the same amount of columns as the other has rows! We’ll discuss square and identity matrices next…

So the cross product along with the dot product is the bread and butter of vector math – but I’d never known really whats happening internally. Essentially the cross product of two vectors (two directions), creates a new vector thats orthogonal to them. This means its a vector thats 90 degrees perpendicular to product of the other two.

So if we have two vectors [1,0,0] and [0,1,0], the cross product will be [0,0,1] – Likewise if we swap these vectors the cross product will be [0, 0, -1]. Even though we doing multiplication internally, we’re also doing subraction and vector order matters here. We can use sarrus’ rule, to get the cross product which is like finding the determinant – which i’ll discuss in matrix math:

If we have two vectors, [1, 0, 0] and [0, 1, 0] we can put them into a 3 by 3 matrix, with an imaginary row at the top:

I J K
1 0 0
0 1 0

We’ll get the determinant of each part of the imaginary row. Starting with the I, we’ll disregard any row and column it crosses and keep the rest. So for I it’ll become:

0 0
1 0

Next we’ll multiply the first value of the first row, by the last value of the last row – in this case 0, 0 and subtract it from first value of the last multiplied by the last value of the first row:

I = 1 * ((0 * 0) – (1 * 0)) = 0

This is the first part of a new vector – Lets see how this looks for the whole thing: cross ([1, 0, 0], [0,1,0]) =

I = 1 * ((0 * 0) – (1 * 0)) = 0
J = 1 * ((1 * 0) – (0 * 0)) = 0
K = 1 * ((1 * 1) – ( 0 * 0) = 1

We can see that the last part makes a difference, we’re doing (1 *1) – (0 * 0), so 1 – 0. If we’d have swapped the initial vectors around we’d have (0 * 0) – (1 * 1) = -1. Next up we’ll break into matrices..

For the life of me I can’t figure this out – If I have a null and a cube at the origin, with the cube rotated and the null placed at [0,20,0] – Setting the nulls transform by multiplying it by that of the cubes should put it into the coordinate space of the cubes. (Essentially orbiting it about the cube)

This doesn’t appear to be the case though, as it appears to be doing the transformation in-place I.e. doing the transform with the first 3 rows and then adding the position part 4th row.

`from pyfbsdk import *`
`box = FBFindModelByName('Cube')`
`null = FBFindModelByName('Null')`

`k = FBMatrix()`
`box.GetMatrix(k)`

`j = FBMatrix()`
`null.GetMatrix(j)`

`m = FBMatrix(j * k)`
`null.SetMatrix(m)`

EDIT:

Just found out the FBMatrixMult – seems to do the job.

I found this PDF on motion capture formats – funnily enough its called “Motion Capture File Formats Explained” and it is really essential if you’re trying to figure out why everything appears to work but doesn’t.

Motion Capture Formats Explained

Read on from page 16 if you like me, having built a correct matrix from the global data and offset find out that inaccuracies get past done the chain because of discrepancies in this very global matrix (due to the communicative problems of matrices). I will add this to my research page, and possibly keep a copy on my server for backup.

1. In 3d the product of matrix multiplication is always in world space.
2. An objects transform is a product of its target space multiplied by its reference space.

This second part is really vital to understand, (I dont think I’ve phased it myself well enough here even) But basically it means that if your transforming an object by the world, but the object is parented the difference between the object and its target space need to be multiplied by the objects local space.

I’ll try to describe this more with pics.

All object transforms have a reference coordinate system i.e. the space they exist in even if there parented to an object or not. For example if I’m driving a vehicle, I’m relative to the vehicle which in turn is relative to the earth, and in turn the sun.

When we want to find the difference or offset of an objects transform relative to its space – be it’s parent, world or an other object we use whats called the inverse. Now this is where it gets a little tricky so ill go slow – to transform an object by another object or get it transform relative to that object we use matrix multiplication. Matrix multiplication in laymen’s terms is basically addition like 10 + 10, but most importantly is non-communicative.

This means simply that  if one matrix is 20 and another matrix is 30, 20 + 30 will equal 50 but 30 + 20 wont. Or simply put its like subtraction. This is due to how matrices are multiplied together.

If we got back to our start matrix – [1,0,0] [0,1,0] [0,0,1] [0,0,0] we can classify each vector as a ‘row’ i.e.

[a,b,c] – row 1

[d,e,f] – row 2

[h,i, j] – row3

[k,l,m] – row 4

With perpendicular values such as a,d,h,k being ‘columns’. In our example above we have 3 columns by 4 rows or a 3×4 matrix. The crucial rule you have to keep in mind when multiplying matrices is that the initial matrix must have the same amount columns as the matrix your multiplying it against has rows. For example if our initial matrix looks like this:

[1,2,3]

[4,5,6]

Our multiplying matrix must have the same amount of rows like so,

[a,d]

[b,e]

[c,f]

We multiply a matrix like so: 1 x a, 2  x  b, 3  x c and so on and so forth…

When we get the relative transform of one object to another, we multiply its transform by the inverse of our target object, parent or space. Now this is a quite a bit more complex so i’ll discuss it very simply.

If we treat two matrices as single values for example 10 and 20, when we get the relative space of 10 to 20 what we do is 10 + -20. Which gives us -10; in other words we’re finding the difference we need to go our base objects transform from our target object, parent or space. Were getting the transform ‘offset’ we need to apply to our target object to get our base objects transform. This offset is always in world space – because it’s the difference thats needed.

Most object transforms in 3d software are matrices’ heres a rough breakdown of what they are.

A matrix in 3d is an axis defined by three vectors: X,Y and Z and fourth being it’s positional offset from an origin. The length of each axis from the origin defines the scale of that axis; 1.0 being 100%. The ‘identity’ matrix is an objects base transform e.g.

matrix3 [1,0,0] [0,1,0] [0,0,1] [0,0,0] – for the X, Y, Z axis’ and the positional offset from the origin.

So for instance if we wanted to scale an object by 200% along its X axis our matrix transform would look like this – matrix3 [2,0,0] [0,1,0] [0,0,1] [0,0,0]

Notice also that each axis is perpendicular to each other axis (90 degrees) – this is important is if it wasnt we would get skewing. Now each axis’ can point in any direction as long as the other two are perpendicular to it.

Sorry for the delay, pretty busy here at work essentially rebuilding some big pipeline tools, systems etc etc.

First up I’ve got a new idea for an animation controller which I’m sort of keeping under wraps. Basically rigs are hooked together by controllers which are animated, problem is most of these tend to be custom – what im planning is a very basic controller that does advanced transforms very well – on top of this customly defined controls can be added on top – which get sort of ‘wired’ into the system.

Secondly I’ve been trying to explain (hopefully) transforms over at CGTalk. A transform is basically a direction with a spin projected by an offset about a coordinate system. Now this sounds a little complex so over the next few posts i’ll explain them a little bit better hopefully with some interesting examples.