SCNNode Z旋转轴保持不变,而X和Y轴在节点旋转时发生变化

时间:2018-06-23 04:02:37

标签: ios swift scenekit augmented-reality arkit

我有一个用户可以通过平移手势旋转的节点。用户可以选择X,Y或Z轴并进行平移,节点将围绕该轴旋转。

问题:节点的正面朝向相机。假设用户向右平移并围绕Y轴旋转节点。节点的正面现在朝向右侧。如果用户切换到X轴并向下平移,则节点的前部将从其初始的面向右方向向下旋转(或从用户角度顺时针旋转)。这是期望的行为。当用户切换到Z旋转时会出现问题。如果用户切换到Z轴旋转并向右平移,则该节点将向下旋转(从用户角度来看为顺时针方向)。

从本质上讲,节点的Z轴始终是恒定的,永远不会偏离其初始方向,但是X轴和Y轴的确会发生变化,受其他轴的旋转影响。

谁能解释这是什么原因?

下面是我用来旋转节点的代码:

let translation = sender.translation(in: sceneView)
        var newAngleX = Float(translation.y)*Float((Double.pi)/180.0)
        var newAngleY = Float(translation.x)*Float((Double.pi)/180.0)
        var newAngleZ = Float(translation.x)*Float((Double.pi)/180.0)

        if axisSelected == "x" {
            newAngleX += currentAngleX
            node.eulerAngles.x = newAngleX
            if(sender.state == .ended) {
                currentAngleX = newAngleX
            }
        }
        if axisSelected == "y" {
            newAngleY += currentAngleY
            node.eulerAngles.y = newAngleY
            if(sender.state == .ended) {
                currentAngleY = newAngleY
            }
        }
        if axisSelected == "z" {
            newAngleZ += currentAngleZ
            node.eulerAngles.z = newAngleZ
            if(sender.state == .ended) {
                currentAngleZ = newAngleZ
            }
        }

1 个答案:

答案 0 :(得分:1)

正如我先前在your post中所写,这是一个Gimbal Lock问题。 万向节锁定是在三维机制中失去一个自由度。 SceneKit中有两个变量:eulerAngles(以弧度表示的本征欧拉角代表围绕xyz轴的3旋转序列,顺序如下:Z-Y-{{ 1}}或Xrollyaw)和pitch(节点的方向,表示为四元数)。

要摆脱ARKit和SceneKit中的万向节锁定,您需要使用单元四元数,其四元数满足以下条件:

orientation

为正确应用四元数,您也需要使用该结构的第四部分((x * x) + (y * y) + (z * z) + (w * w) == 1 )。四元数用SCNVector4表示,其中w-x-y的值是归一化的分量,z字段包含以弧度为单位的旋转角度或以牛顿米)。

enter image description here

万向节锁定在将(三个万向节中的两个)轴驱动为平行配置时发生。