SceneKit中无需虚拟SCNNode实现两个欧拉角相加的方法
欧拉角相加的优化实现(无需虚拟SCNNode)
问题描述
我需要实现两个欧拉角的相加操作。目前的做法是将欧拉角转换为旋转矩阵后相乘,但最终从旋转矩阵还原欧拉角时,不得不依赖一个虚拟SCNNode,这感觉不够规范。我编写了如下代码:
import SceneKit import Spatial // A helper function func eulerToRotation(eulerAngles: SCNVector3) -> SCNVector4 { let rotation = Rotation3D(eulerAngles: .init(angles: [eulerAngles.x, eulerAngles.y, eulerAngles.z], order: .xyz)) return SCNVector4( simd_double4(rotation.axis.vector, rotation.angle.radians) )} func addEulerAngles(e1: SCNVector3, e2: SCNVector3) -> SCNVector3 { let r1 = eulerToRotation(eulerAngles: e1), r2 = eulerToRotation(eulerAngles: e2) let m1 = SCNMatrix4MakeRotation(r1.w, r1.x, r1.y, r1.z), m2 = SCNMatrix4MakeRotation(r2.w, r2.x, r2.y, r2.z) let m = SCNMatrix4Mult(m1, m2) // Hacky here let node = SCNNode() node.transform = m return node.eulerAngles }请问有没有不使用该虚拟SCNNode的更优实现方式?
优化方案
可以直接利用simd库的四元数(simd_quatd)处理旋转组合,无需借助虚拟SCNNode,代码更高效且逻辑更清晰。
核心实现代码
import SceneKit import Spatial // 辅助函数:欧拉角转四元数(比转旋转矩阵更高效) func eulerToQuaternion(eulerAngles: SCNVector3) -> simd_quatd { return simd_quatd(rotation: Rotation3D(eulerAngles: .init(angles: [eulerAngles.x, eulerAngles.y, eulerAngles.z], order: .xyz))) } // 优化后的欧拉角相加函数 func addEulerAngles(e1: SCNVector3, e2: SCNVector3) -> SCNVector3 { // 将两个欧拉角转成四元数 let q1 = eulerToQuaternion(eulerAngles: e1) let q2 = eulerToQuaternion(eulerAngles: e2) // 复合旋转:先应用e1的旋转,再应用e2的旋转,四元数相乘顺序为q2 * q1 let combinedQuaternion = q2 * q1 // 将复合四元数转回欧拉角(XYZ顺序,和SCNNode.eulerAngles逻辑一致) let euler = combinedQuaternion.eulerAngles return SCNVector3(euler.x, euler.y, euler.z) }
补充:若坚持使用旋转矩阵的实现方式
如果需要保留旋转矩阵的处理逻辑,也可以直接从矩阵转四元数再转欧拉角,无需虚拟节点:
func addEulerAnglesWithMatrix(e1: SCNVector3, e2: SCNVector3) -> SCNVector3 { let q1 = eulerToQuaternion(eulerAngles: e1) let q2 = eulerToQuaternion(eulerAngles: e2) // 四元数转矩阵后相乘 let combinedMatrix = simd_double4x4(q2) * simd_double4x4(q1) // 矩阵转四元数再转欧拉角 let combinedQuaternion = simd_quatd(combinedMatrix) let euler = combinedQuaternion.eulerAngles return SCNVector3(euler.x, euler.y, euler.z) }
关键说明
- 四元数处理旋转的效率高于旋转矩阵,且能避免欧拉角的万向锁问题(中间用四元数复合更稳定)。
- 旋转顺序需注意:欧拉角相加对应先执行
e1的旋转,再执行e2的旋转,因此四元数相乘顺序为q2 * q1(四元数的右乘特性决定),和矩阵相乘的m2 * m1逻辑一致。
内容的提问来源于stack exchange,提问作者OMGPOP
相关产品推荐
相关产品推荐

