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

标签 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
            }
        }

最佳答案

正如我之前在 your post 中所写的那样这是一个万向节锁问题。 万向节锁定是三维机构中一个自由度的损失。 SceneKit 中有两个变量:eulerAngles(固有欧拉角,以弧度表示,表示绕 x-y-z 轴 3 次旋转的序列,顺序如下:Z-Y-X滚动偏航俯仰)和方向(节点的方向,以四元数表示)。

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

(x * x) + (y * y) + (z * z) + (w * w) == 1

为了正确应用四元数,您还需要使用此结构的第四个组件 (w)。四元数以 SCNVector4 表示,其中 x-y-z 值是归一化分量,w 字段包含旋转角度(以弧度为单位)或扭矩大小(以牛顿米为单位)。

enter image description here

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

关于ios - SCNNode Z轴旋转轴保持不变,而X轴和Y轴在节点旋转时发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50997832/

相关文章:

swift - 如何在 Swift 中使用 Bezier 路径连接 3D 空间中的两个 SCNSphere?

ios - 如何将 UINavigationcontroller 动画与 Motion 库一起使用?

ios - 如何将 bool 值链接到 UISwitch 的开/关状态?

objective-c - ios 不允许使用 arc 将间接指针隐式转换为指向 id 的 objective-c 指针

objective-c - 我应该怎么做才能调用audioPlayerDidFinishPlaying :

objective-c - 按层次结构消除 UINavigationController 中所有呈现的 ViewControlelrs

ios - 从 xc10 > xc11 迁移 SceneKit 应用程序,我遇到 "xcrun: error: unable to find utility "scntool",不是开发人员工具或在 PATH 中"

ios - Swift:关于 presentScene() 的安全实践

ios - dispatch_barrier_async 不等待 CoreImage 完成处理

iphone - 为 IOS 编译 ffmpeg(R_ABS reloc 错误)