The source of my confusion is the documentation on SCNMatrix4 from Apple:
SceneKit uses matrices to represent coordinate space transformations, which in turn can represent the combined position, rotation or orientation, and scale of an object in three-dimensional space. SceneKit matrix structures are in row-major order, so they are suitable for passing to shader programs or OpenGL APIs that accept matrix parameters.
This seems contradictory since OpenGL uses column-major transformation matrices!
In general the documentation of Apple on this topic is poor:
- GLKMatrix4 does not talk about column vs. row major at all, but I am certain from all discussions online that GLKMatrix is plain and simple column-major.
- simd_float4x4 does not talk about the topic, but at least the variable names make it clear that it is stored as columns:
From simd/float.h
:
typedef struct { simd_float4 columns[4]; } simd_float4x4;
Some discussion online about SCNMatrix4 talk as if SCNMatrix4 is different from GLKMatrix4, but looking at the code for SCNMatrix4 give some hints that it might just be column-order as expected:
/* Returns a transform that translates by '(tx, ty, tz)':
* m' = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1]. */
NS_INLINE SCNMatrix4 SCNMatrix4MakeTranslation(float tx, float ty, float tz) {
SCNMatrix4 m = SCNMatrix4Identity;
m.m41 = tx;
m.m42 = ty;
m.m43 = tz;
return m;
}
So is SCNMatrix4
row-major (storing translations in m14
, m24
, m34
) or column-major (storing translations in m41
, m42
, m43
)?