SceneKit - Rotate object around X and Z axis

拈花ヽ惹草 提交于 2020-02-04 15:55:37

问题


I’m using ARKit with SceneKit. When user presses a button I create an anchor and to the SCNNode corresponding to it I add a 3D object (loaded from a .scn file in the project).

The 3D object is placed facing the camera, with the same orientation the camera has. I would like to make it look like the object is laying on a plane surface and not inclined if it is that way. So, if I got it right, I’d need to apply a rotation transformation so that it’s rotation around the X and Z axis become 0.

My attempt at this is: take the node’s x and z eulerAngles, invert them, and rotate that amount around each axis

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

This works all right for most cases, but in some the object is rotated in completely strange ways. Should I be setting the rotation angle to anything else than just the inverse of the current Euler Angle? Setting the angles to 0 directly did not work at all.


回答1:


I've come across this and figured out I was running into gimbal lock. The solution was to rotate the node around one axis, parent it to another SCNNode(), then rotate the parent around the other axis. Hope that helps.




回答2:


You don't have to the node transform on a matrix, you can simply rotate around a specific axis and that might be a bit simpler in terms of the logic of doing the rotation.

You could do something like:

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

Not sure if this is the kind of thing you're looking for, but it is simpler than doing the rotation with the SCNMatrix4




回答3:


Well, I managed a workaround, but I'm not truly happy with it, so I'll leave the question unanswered. Basically I define a threshold of 2 degrees and keep applying those rotations until both Euler Angles around X and Z are below the aforementioned threshold.

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


来源:https://stackoverflow.com/questions/45929532/scenekit-rotate-object-around-x-and-z-axis

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!