SceneKit - 绕X和Z轴旋转对象

4
我正在使用ARKit和SceneKit。当用户按下按钮时,我会创建一个锚点,并向其对应的SCNNode添加一个3D对象(从项目中的.scn文件加载)。
3D对象被放置在面向相机的位置,并与相机具有相同的方向。我想让它看起来像是放在平面表面上,如果它是倾斜的话,就不是这样。因此,如果我理解正确,我需要应用旋转变换,使其绕X和Z轴的旋转角度为0。
我尝试过:获取节点的x和z欧拉角,反转它们,并围绕每个轴旋转该量。
let rotationZ = rotationMatrixAroundZ(radians: -node.eulerAngles.z)
let rotationX = rotationMatrixAroundX(radians: -node.eulerAngles.x) 

let rotationTransform = simd_mul(rotationTransformX, rotationTransformZ)
node.transform = SCNMatrix4(simd_mul(simd_float4x4(node.transform), rotationTransform))

对于大多数情况来说,这样做是可以的,但是在某些情况下,对象的旋转方式完全是奇怪的。我该把旋转角度设置为除当前欧拉角的倒数之外的其他值吗?将角度直接设置为0根本不起作用。


你使用约束吗? - Vasilii Muravev
不,我尝试使用SCNLookAtConstraint和look(at:)方法进行实验,但它们都不能满足我的需求。 - leandrodemarco
你可以发布一下rotationMatrixAroundZ()函数的功能吗? - jpulikkottil
3个回答

5

我遇到了这个问题,发现自己遇到了万向节锁定。解决方法是将节点围绕一个轴旋转,将其父级设为另一个SCNNode(),然后使父级沿着另一个轴旋转。希望这能帮到你。


谢谢!我想我遇到了万向节锁定问题,但是没有想到这种解决方法! - leandrodemarco
这是一个非常棒的解决方案!我创建了一个包装类,以便在任何节点上轻松应用所有3个旋转。 - Senseful

3

您不必对矩阵进行节点变换,只需围绕特定轴旋转即可,这在执行旋转时的逻辑上可能会更简单一些。

您可以尝试如下操作:

node.runAction(SCNAction.rotateBy(x: x, y: y, z: z, duration: 0.0))

不确定您是否正在寻找这种信息,但它比使用SCNMatrix4进行旋转更简单。


谢谢建议,我还没有探索过这个选项。我会尝试一下的! - leandrodemarco

1

好的,我想出了一个解决办法,但我并不完全满意,所以我将保留这个问题未回答。基本上,我定义了一个2度的阈值,并持续应用旋转,直到X和Z周围的欧拉角都低于上述阈值。

func layDownNode(_ node: SCNNode) {
    let maxErrDegrees: Float = 2.0
    let maxErrRadians = GLKMathDegreesToRadians(maxErrDegrees)

    while (abs(node.eulerAngles.x) > maxErrRadians || abs(node.eulerAngles.z) > maxErrRadians) {
        let rotationZ = -node.eulerAngles.z
        let rotationX = -node.eulerAngles.x

        let rotationTransformZ = rotationMatrixAroundZ(radians: rotationZ)
        let rotationTransformX = rotationMatrixAroundX(radians: rotationX)

        let rotationTransform = simd_mul(rotationTransformX, rotationTransformZ)

        node.transform = SCNMatrix4(simd_mul(simd_float4x4(node.transform), rotationTransform))
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接