I am doing an app with a functionality like a 3D compass, it can point to the direction where I want. The code is
extension AR: CLLocationManagerDelegate{
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
heading = Float(newHeading.trueHeading)
motionManager.deviceMotionUpdateInterval = 1.0/60.0
if motionManager.isDeviceMotionAvailable {
motionManager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: { (devMotion, error) -> Void in
self.node.orientation = self.orient(q: (self.motionManager.deviceMotion?.attitude.quaternion)!,angle: self.heading)
})}
}
}
func orient(q:CMQuaternion,angle:Float) -> SCNQuaternion{
let gq1: GLKQuaternion = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-angle), 0, 0, 1)
// add a rotation in z axis
let gq2: GLKQuaternion = GLKQuaternionMake(Float(q.x), Float(q.y), Float(q.z), Float(q.w))
// the current orientation
let qp: GLKQuaternion = GLKQuaternionMultiply(gq1, gq2)
// get the "new" orientation
var rq = CMQuaternion()
rq.x = Double(qp.x)
rq.y = Double(qp.y)
rq.z = Double(qp.z)
rq.w = Double(qp.w)
return SCNQuaternion(Float(rq.x), Float(rq.y), Float(rq.z), -Float(rq.w))
}
At first I got the device's orientation to apply to my object ("node") in z axis so that it can point to the right direction. However, I figure out there is gimbal lock coming. When I rotate the device in x & y axis, the object can rotate in x & y axis as well. But if I rotate the device in z axis, there are two situations:
one, the device is holding up, the object still rotates in y axis (Seems rotation in z axis disappears).
two, the device is lying down, the object rotates in z axis.
How can I avoid first situation?