首页 文章

SceneKit - 围绕 X 和 Z 轴旋转对象

提问于
浏览
0

我正在使用 ARKit 和 SceneKit。当用户按下按钮时,我创建一个锚点,并向与其对应的 SCNNode 添加一个 3D 对象(从项目中的.scn 文件加载)。

3D 物体面向相机放置,相机具有相同的方向。我想让它看起来像物体放在一个平面上,如果是那样的话就不会倾斜。所以,如果我做对了,我需要应用一个旋转变换,使它围绕 X 和 Z 轴的旋转变为 0。

我的尝试是:取节点的 x 和 z eulerAngles,将它们反转,并围绕每个轴旋转该量

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 根本不起作用。

3 回答

  • 3

    我遇到过这个,并发现我遇到了万向节锁。解决方案是围绕一个轴旋转节点,将其父节点旋转到另一个轴SCNNode(),然后围绕另一个轴旋转父节点。希望有所帮助。

  • 1

    您不必对矩阵进行节点变换,只需围绕特定轴旋转,就旋转逻辑而言可能更简单一些。

    你可以这样做:

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

    不确定这是否是您正在寻找的东西,但它比使用 SCNMatrix4 进行旋转更简单

  • 0

    好吧,我设法解决了一个问题,但我并不是真的很满意,所以我不会回答这个问题。基本上我定义了 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))
        }
    }
    

相关问题