Chapter 5 - MathLibrary matrix calculation (confusion about column-major)

Hello,

I am new to computer graphics, and I am having trouble understanding MathLibrary.swift in chapter 5.

As far as I know, the translation matrix should look like the following since Metal uses column-major matrix:
[1, 0, 0, Tx],
[0, 1, 0, Ty],
[0, 0, 1, Tz],
[0, 0, 0, 1 ]

However, the MathLibrary.swift has the code like the following:
[ 1 , 0 , 0 , 0 ],
[ 0 , 1. , 0 , 0 ],
[ 0 , 0 , 1 , 0 ],
[Tx , Ty , Tz , 1 ]

I also checked these lines in chapter 4.

matrix.columns.3 = [0.3, -0.4, 0, 1]

Following on from that code, process each vertex and multiply by the transformation marrix.

vertices = vertices.map {
let vertex = matrix * float4($0, 1)
return [vertex.x, vertex.y, vertex.z]
}

Could anyone explain some more details?

1 Like

Hi @ssume and welcome to the forums!

A translation matrix looks like this:

1    0    0    tx
0    1    0    ty
0    0    1    tz
0    0    0    1

If you take the columns, you end up with:

[  1 ,  0 ,  0 ,  0 ],  // col 1
[  0 ,  1 ,  0 ,  0 ],  // col 2
[  0 ,  0 ,  1 ,  0 ],  // col 3
[ tx ,  ty , tz , 1 ]   // col 4

You can initialize a matrix using rows if you’d like:

let rows = [
    simd_float3(1, 2, 3),
    simd_float3(4, 5, 6),
    simd_float3(7, 8, 9)
]
print(float3x3(rows: rows))

prints the result:

simd_float3x3([[1.0, 4.0, 7.0],  // col 1
               [2.0, 5.0, 8.0],  // col 2
               [3.0, 6.0, 9.0]]) // col 3

Apple article on working with matrices:

https://developer.apple.com/documentation/accelerate/working_with_matrices

I’m not sure what you’re asking about this code:

vertices = vertices.map {
  let vertex = matrix * float4($0, 1)
  return [vertex.x, vertex.y, vertex.z]
}

Are you familiar with how map(_:_:) works?

If not, a for loop would look like this:

var newVertices: [float3] = []
for vertex in vertices {
  // 1
  let newVertex = matrix * float4(vertex, 1)
  // 2
   newVertices.append([
      newVertex.x, newVertex.y, newVertex.z])
}
// 3
vertices = newVertices

map(_:_:) is a functional programming way of doing the same thing.

  1. Because you have a 4x4 matrix, you can’t multiply a 1x3 vector - it has to be a 1x4 vector. newVertex is a 1x4 vector.
  2. Take the first 3 components of newVertex and add them to newVertices.
  3. Update vertices with the new calculated vertices.

So your old vertices are:

[[0, 0, 0.5]]

map(_:_:) changes each vertex. You only have one vertex in vertices and the matrix contains:

[  1 ,    0 ,  0 ,  0 ],  // col 1
[  0 ,    1 ,  0 ,  0 ],  // col 2
[  0 ,    0 ,  1 ,  0 ],  // col 3
[ 0.3 , -0.4 , 0 ,  1 ]   // col 4

Perform:

let vertex = matrix * ([0, 0, 0.5, 1]) 

After this, vertex contains [0.3, -0.4, 0.5, 1].

To append to vertices, you take the x, y, z and lose the fourth w component.

1 Like

If you can’t run the playground, btw, it’s because the code for creating the library has changed.

In Utility.swift, change createLibrary() to:

public func createLibrary() -> MTLLibrary {
  device.makeDefaultLibrary()! 
}

Hi @caroline ,

I thought I added some description why I cannot get the code quoted from chapter 4, but I didn’t. It’s my mistake, sorry.

My problem was solved with the second matrix you explained. Thanks a lot for your kindness and detailed explaination.
The problems came from misunderstanding about matix, which I thought it is written like:

[ 1 , 0 , 0 , 0 ], // row 1
[ 0 , 1 , 0 , 0 ], // row 2
[ 0 , 0 , 1 , 0 ], // row 3
[ tx , ty , tz , 1 ] // row 4

I’ve checked matrices at playground before I uploaded the question, but maybe there’s something wrong in the code I wrote.

Your book is amazing and it helps me a lot to learn Metal! :+1:

p.s. Oh and I’ve already seen the change in Utility.swift from forum, and also thanks for the concerns. :slight_smile:

1 Like