How do I extract rotation values from a simdTransform in ARKit?

Viewed 884

I'm animating an ARSCNFaceGeometry within ARKit, using values captured from the iPhone's TrueDepth camera.

The camera provides transform data as simd_float4x4. This contains node rotation, position and scale. Here is a sample of what is produced:

simd_float4x4([
            [0.9482585, 0.0065377234, 0.31743154, 0.0],
            [-0.07080679, 0.9789629, 0.1913578, 0.0],
            [-0.3095027, -0.20393308, 0.9287729, 0.0],
            [0.13866597, 0.20701922, -0.57620335, 1.0]
])

I'm only interested in applying rotation to my FaceGeometry, and having separate control over it's position and scale. So I need to extract the relevant rotation values from the above matrix.

I can't find any 'off the shelf' methods for doing this in the Apple documentation, nor does it even explain which columns or rows of the matrix relate to rotation.

I've done the following, by creating a 'dummy' node, applying the simdTransform to it, then accessing it's rotation property, which works. But this feels hacky, in that I'm creating objects in the scene just to perform a programatic operation.

let tempNode = SCNNode(geometry: nil)
tempNode.simdTransform = faceTransformArray[index]
ARFaceNode.rotation = tempNode.rotation
tempNode.removeFromParentNode()

Can anybody offer a cleaner solution?

P.S. I'm new to working with matrices.

Thank you in advance.

1 Answers

The 3D rotation is expressed as a quaternion, which is made of a 3D vector, describing the axis that you are rotating around, and an angle, which describes the angle of rotation about that axis.

To get a quaternion from a 4x4 simd matrix, you can initialise simd_quatf from the matrix:

let m = simd_float4x4([
    [0.9482585, 0.0065377234, 0.31743154, 0.0],
    [-0.07080679, 0.9789629, 0.1913578, 0.0],
    [-0.3095027, -0.20393308, 0.9287729, 0.0],
    [0.13866597, 0.20701922, -0.57620335, 1.0]
])
let q = simd_quatf(m)

The rotation property of SCNNode is expressed as SCNVector4, which has x, y, and z properties describing the axis, and w describing the rotation. simd_quatf has axis (Float) and angle (SIMD3<Float>) properties, so to get your vector:

let sq = SCNVector4(q.axis.x, q.axis.y, q.axis.z, q.angle)

You can see here that the results are the same:

enter image description here

Related