如何用4D向量表示3D旋转?SceneKit中SCNVector4相关疑问
哥们,我太懂你这种盯着SCNVector4一脸懵的感觉了!当初刚碰SceneKit的时候,我也对着applyTorque和rotation里的四个值挠头——好好的3D旋转,为啥要用四个数?搜半天还净是些4D空间旋转的内容,完全不对路子,那些sin、cos公式更是看得人脑袋大。
你搜错方向啦!SceneKit里的SCNVector4用来表示旋转/扭矩的时候,本质是“轴角表示法”(Axis-Angle),和4D空间旋转半毛钱关系都没有。它的四个值分工明确:
x, y, z:代表3D空间里的一个旋转轴方向向量(比如(0,1,0)就是Y轴)w:代表绕这个轴旋转的角度(弧度)(在扭矩场景里则代表扭矩的大小)
你想想,要描述一个3D物体怎么转,是不是得说清楚两个核心信息:
- 绕哪根轴转?(用x/y/z三个值定义方向)
- 转多少度?(用w值定义角度)
这四个值刚好把这两个信息装下,而且还能避免欧拉角的“万向锁”问题——这也是SceneKit优先用它的原因。
比如你想让一个节点绕Y轴转180度(也就是翻面),直接这么写:
yourNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: .pi)
这里(0,1,0)是Y轴方向,.pi就是180度的弧度值,是不是很直观?
再比如给物理体施加一个绕X轴的扭矩,让它翻滚:
yourPhysicsBody.applyTorque(SCNVector4(x: 1, y: 0, z: 0, w: 3), asImpulse: true)
这里(1,0,0)是X轴方向,w:3是扭矩的大小,数值越大转得越猛。
你看到的那些带sin、cos的内容,是底层四元数的计算逻辑。四元数是数学上更优雅的3D旋转表示法,轴角表示法和四元数可以互相转换:
四元数的四个分量是 (cos(θ/2), sin(θ/2)*ax, sin(θ/2)*ay, sin(θ/2)*az),其中θ是旋转角度,ax/ay/az是轴的单位向量。
但!SceneKit已经帮你把这些转换都封装好了,你根本不用自己算这些三角函数——直接传你要的轴和角度就行,它内部会自动转成四元数来处理旋转。
当你自定义旋转轴的时候(不是X/Y/Z轴),记得把x,y,z组成的向量归一化(也就是让x²+y²+z²=1),不然旋转的效果会出错。比如你想绕(1,1,0)这个对角线轴转,先把它变成单位向量:(√2/2, √2/2, 0),再传给SCNVector4。
内容的提问来源于stack exchange,提问作者Sweeper

