SceneKit - 围绕 X 和 Z 轴旋转对象
SceneKit - Rotate object around X and Z axis
我正在使用 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根本不起作用。
好吧,我设法解决了这个问题,但我对它不是很满意,所以我不回答这个问题。基本上我定义了一个 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))
}
}
您不必在矩阵上进行节点变换,您可以简单地围绕特定轴旋转,就旋转逻辑而言,这可能会更简单一些。
你可以这样做:
node.runAction(SCNAction.rotateBy(x: x, y: y, z: z, duration: 0.0))
不确定这是否是您要找的东西,但它比使用 SCNMatrix4 进行旋转更简单
我遇到了这个,发现我 运行 变成了 gimbal lock。解决方案是围绕一个轴旋转节点,将其作为另一个 SCNNode()
的父节点,然后围绕另一个轴旋转父节点。希望对您有所帮助。
我正在使用 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根本不起作用。
好吧,我设法解决了这个问题,但我对它不是很满意,所以我不回答这个问题。基本上我定义了一个 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))
}
}
您不必在矩阵上进行节点变换,您可以简单地围绕特定轴旋转,就旋转逻辑而言,这可能会更简单一些。
你可以这样做:
node.runAction(SCNAction.rotateBy(x: x, y: y, z: z, duration: 0.0))
不确定这是否是您要找的东西,但它比使用 SCNMatrix4 进行旋转更简单
我遇到了这个,发现我 运行 变成了 gimbal lock。解决方案是围绕一个轴旋转节点,将其作为另一个 SCNNode()
的父节点,然后围绕另一个轴旋转父节点。希望对您有所帮助。