Search code examples
iosswiftmetalcore-motion

How to cast a CMRotationMatrix into a float4x4?


I am building a Metal app that uses float4x4 matrices to rotate 3D objects and/or the world view.

The app is also reading the device attitude that can be expressed as a rotation matrix in the CMRotationMatrix format (CoreMotion).

How can I cast my attitude.rotationMatrix into a float4x4 object?


Solution

  • You can create an extension that allows you to initialize a float4x4 from the elements of a CMRotationMatrix:

    extension float4x4 {
        init(_ m: CMRotationMatrix) {
            let x = float4(Float(m.m11), Float(m.m21), Float(m.m31), 0)
            let y = float4(Float(m.m12), Float(m.m22), Float(m.m32), 0)
            let z = float4(Float(m.m13), Float(m.m23), Float(m.m33), 0)
            let w = float4(           0,            0,            0, 1)
            self.init(columns: (x, y, z, w))
        }
    }
    

    Using it is as simple as calling the initializer:

    let simdMatrix = float4x4(deviceMotion.attitude.rotationMatrix)
    

    This creates a matrix that is suitable for transforming objects whose transformations are expressed relative to the reference attitude frame. You may find that you need to permute the columns so that they match the world coordinate system of your application.