如何使用SceneKit实现3D指南针

时间:2017-02-21 09:37:59

标签: ios swift scenekit

目前我在制作3D指南针功能方面感到困惑。使用SceneKit,我加载了一个箭头对象,然后获取了传感器数据,如下面的代码(效果为this video

let motionManager = CMMotionManager()
motionManager.deviceMotionUpdateInterval = 1.0/60.0
if motionManager.isDeviceMotionAvailable {
    motionManager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: { (devMotion, error) -> Void in
        arrow.orientation = SCNQuaternion(-CGFloat((motionManager.deviceMotion?.attitude.quaternion.x)!), -CGFloat((motionManager.deviceMotion?.attitude.quaternion.y)!), -CGFloat((motionManager.deviceMotion?.attitude.quaternion.z)!), CGFloat((motionManager.deviceMotion?.attitude.quaternion.w)!))

        })}

完成此操作后,如果用户在任何轴上旋转设备,箭头也可以旋转。由于这是一个3D指南针,我需要箭头指向方向。所以我通过CLLocationManager获取了标题数据,然后问题就来了。

let gq1: GLKQuaternion = GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(heading), 0, 0, 1)
arrow.orientation = SCNVector4(gq1.x,gq1.y,gq1.z,gq1.w)

上面的代码在2D中完美地完成,如下图所示,它正确指向东方向。但我想在3D环境中使用它,所以我确实喜欢下面的

motionManager.deviceMotionUpdateInterval = 1.0/60.0
    if motionManager.isDeviceMotionAvailable {
        motionManager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: { (devMotion, error) -> Void in
            arrow.orientation = orient(q: (motionManager.deviceMotion?.attitude.quaternion)!, angle: heading)
    }
func orient(q:CMQuaternion,angle:Float) -> SCNQuaternion{
     GLKQuaternionMakeWithAngleAndAxis(GLKMathDegreesToRadians(-angle), 0, 0, 1)
    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 SCNVector4(-Float(rq.x), -Float(rq.y), -Float(rq.z), Float(rq.w))
}

有一个错误(this video显示),如果我绕z轴旋转设备,箭头仍围绕y轴旋转。我做错了吗?

enter image description here

1 个答案:

答案 0 :(得分:0)

如果我通过这种方法绕z轴旋转设备,方向数据会连续出现。结果,我无法使用CLLocationManager来实现我的目标。这thread就是我想要的。