Not only is using column-major vs row-major counter-intuitive, Apple's documentation on "Working with Matrices" further exacerbates the confusion by their examples of "constructing" a "Translate Matrix" and a "Rotation Matrix" in 2D.
Translate Matrix Per Apple's Documentation ()
Translate A translate matrix takes the following form:
1 0 0 0 1 0 tx ty 1
The simd library provides constants for identity matrices (matrices with ones along the diagonal, and zeros elsewhere). The 3 x 3 Float identity matrix is matrix_identity_float3x3.
The following function returns a simd_float3x3 matrix using the specified tx and ty translate values by setting the elements in an identity matrix:
func makeTranslationMatrix(tx: Float, ty: Float) -> simd_float3x3 { var matrix = matrix_identity_float3x3 matrix[0, 2] = tx matrix[1, 2] = ty return matrix }
My Issue with it
The line of code matrix[0, 2] = tx
sets the value of the first column and the third row to tx
. let translationMatrix = makeTranslationMatrix(tx: 1, ty: 3)
and printing out the 2nd column print(translationMatrix.columns.2)
will yield float3(0.0, 0.0, 1.0)
. I am very confused regarding why it is the last row that contains the translation values, rather than the column. This convention is not used when using SCNMatrix4MakeTranslation
and creating a simd_float4x4
out of the SCNMatrix4
object.
var A = SCNMatrix4MakeTranslation(1,2,3)
var Asimd = simd_float4x4(A)
A.m41 // 1
A.m42 // 2
A.m43 // 3
A.m44 // 1
Asimd.columns.3 // float4(1.0, 2.0, 3.0, 1.0)
Both SCNMatrix4
and simd_float4x4
follow the column major naming convention. In the 2D example from Apple, it is the last row that contains the translation values, whereas with SCNMatrix4
and converting to simd_float4x4
, it is the last column that contains the translation values. Apple's example seems to be doing the same with the Rotation Matrices as well.
What am I missing?
This can be confusing, yes.
The documentation you mentions makes the following computation:
let translatedVector = positionVector * translationMatrix
Note that the matrix is on the right side of the multiplication.
You are probably used to the notation b = M * a
but if you take the transpose you get b' = a' * M'
which is what the sample does.
In SIMD there's no way to differentiate a vector from its transpose (b
from b'
) and the library allows you to make the multiplication in both ways:
static simd_float3 SIMD_CFUNC simd_mul(simd_float3x3 __x, simd_float3 __y);
static simd_float3 SIMD_CFUNC simd_mul(simd_float3 __x, simd_float3x3 __y) { return simd_mul(simd_transpose(__y), __x); }
来源:https://stackoverflow.com/questions/53435756/xcode-simd-issue-with-translation-and-rotation-matrix-example