SCNNode Z 旋转轴保持不变,而 X 和 Y 轴在节点旋转时发生变化 [英] SCNNode Z-rotation axis stays constant, while X and Y axes change when node is rotated

查看:22
本文介绍了SCNNode Z 旋转轴保持不变,而 X 和 Y 轴在节点旋转时发生变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用户可以通过平移手势旋转的节点.用户可以选择 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)如果轴选择 == "x" {newAngleX += currentAngleXnode.eulerAngles.x = newAngleXif(sender.state == .ended) {currentAngleX = newAngleX}}如果轴选择 == "y" {newAngleY += currentAngleYnode.eulerAngles.y = newAngleYif(sender.state == .ended) {currentAngleY = newAngleY}}如果轴选择 == "z" {newAngleZ += currentAngleZnode.eulerAngles.z = newAngleZif(sender.state == .ended) {currentAngleZ = newAngleZ}}

解决方案

正如我之前在

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

I have a node that the user can rotate via a pan gesture. The user can select either X, Y, or Z axis and pan, and the node will rotate around that axis.

The Issue: The node's front is facing the camera. Let's say the user pans to the right and rotates the node around the Y axis. The node's front is now facing the right. If the user switches to the X axis and pans down, the node's front will rotate downward (or clockwise from the user's perspective) from it's initial right-facing orientation. This is desired behavior. The problem arises when the user switches to the Z rotation. If the user switches to Z axis rotation and pans right, the node will rotate down (clockwise from the user's perspective).

Essentially, the Z axis of the node is always constant, never moving from it's initial orientation, but the X and Y axes do change, affected by other axes' rotations.

Can anyone explain what's causing this?

Below is the code I'm using to rotate the node:

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

解决方案

As I wrote earlier in your post it's a Gimbal Lock issue. Gimbal Lock is the loss of one DoF in a three-dimensional mechanism. There are two variables in SceneKit: eulerAngles (intrinsic euler angles, expressed in radians, represent a sequence of 3 rotations about the x-y-z axis with the following order: Z-Y-X or roll, yaw, pitch) and orientation (node’s orientation, expressed as quaternion).

To get rid of gimbal lock in ARKit and SceneKit you need to use unit quaternions, whose components satisfy the equation:

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

For applying quaternions correctly you need to use the fourth component of this structure too (w). Quaternions are expressed in SCNVector4, where x-y-z values are normalized components, and the w field contains the rotation angle, in radians, or torque magnitude, in newton-meters).

Gimbal Lock occurs when the axes (of two of the three gimbals) are driven into a parallel configuration.

这篇关于SCNNode Z 旋转轴保持不变,而 X 和 Y 轴在节点旋转时发生变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆