我有一个用户可以通过平移手势旋转的节点。用户可以选择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
}
}
答案 0 :(得分:1)
正如我先前在your post中所写,这是一个Gimbal Lock
问题。 万向节锁定是在三维机制中失去一个自由度。 SceneKit中有两个变量:eulerAngles
(以弧度表示的本征欧拉角代表围绕xyz轴的3旋转序列,顺序如下:Z
-Y
-{{ 1}}或X
,roll
,yaw
)和pitch
(节点的方向,表示为四元数)。
要摆脱ARKit和SceneKit中的万向节锁定,您需要使用单元四元数,其四元数满足以下条件:
orientation
为正确应用四元数,您也需要使用该结构的第四部分((x * x) + (y * y) + (z * z) + (w * w) == 1
)。四元数用SCNVector4表示,其中w
-x
-y
的值是归一化的分量,z
字段包含以弧度为单位的旋转角度或以牛顿米)。
万向节锁定在将(三个万向节中的两个)轴驱动为平行配置时发生。