Search code examples
iosswiftcore-motion

Getting the right values for SCNCamera from CMMotionManager


I want to use core motion to control the view of the cameraNode using Euler angles. It works in the initial position but when I change the view to the right or left .roll values seem to be wrong.

This is the code so far...

 func cameraTracking() {
        motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
        motionManager.startDeviceMotionUpdates(to: OperationQueue.main) {
            [weak self](data: CMDeviceMotion?, error: Error?) in
            guard let data = data else { return }
            let attitude: CMAttitude = data.attitude

            self?.cameraNode.camera?.fieldOfView = 90

            self?.cameraNode.eulerAngles = SCNVector3Make(-Float(attitude.roll + Double.pi/2), Float(attitude.yaw), -Float(attitude.pitch) )

        }
    }

Thankful for any suggestions!


Solution

  • Don't try to use eulerAngles those lead to many problems beside yours like gimbal lock

    The proper way is to stay in the domain of quaternions

    i assume you're using landscape mode - otherwise you need to change the parameters in SCNVector4

    let attitude = data.attitude.quaternion
    let aq = GLKQuaternionMake(Float(attitude.x), Float(attitude.y), Float(attitude.z), Float(attitude.w))
    let cq = GLKQuaternionMakeWithAngleAndAxis(Float(Float.pi/2), 0, 1, 0)
    let q = GLKQuaternionMultiply(cq, aq)
    self?.cameraNode.orientation = SCNVector4(x: -q.y, y: q.x, z: q.z, w: q.w)