使用欧拉角旋转与万向节死锁 rotate with eulerAngle and Gimbal Lock

用固定顺序的欧拉角来描述旋转时,如果第二次旋转的角度为90或-90度,则会产生万向节死锁

重现万向节死锁

步骤

  • Unity采用左手坐标系,Unity中的(Transform组件的以欧拉角表示的)旋转顺序为:z-x-y
  • 物体的默认朝向为世界空间的z轴,即(0,0,1f) image-20220422105249074
  • 绕物体自身z轴旋转30度,物体以世界空间为参考系绕z轴旋转了30度 image-20220422105402343
  • 绕物体自身x轴旋转-90度,发生了旋转 image-20220422111503750
  • 绕物体自身y轴旋转30度,物体以世界空间为参考系绕z轴旋转了30度 image-20220422111851736

解读

第二次绕x轴旋转90度后,第一次的绕绕物体自身z轴旋转和第三次的绕物体自身y轴旋转都是相对于以世界空间为参考系绕z轴旋转

此时(只要保持欧拉角x为-90不变)将欧拉角的y和z改为其他任何数值,物体都只能进行yaw,而不会(相对自身)进行roll了,这就发生了万向节死锁

第二次的绕x轴旋转-90度(或90度)使得第一次绕z轴旋转产生的(以自身为参考系)roll效果变为了(以自身为参考系的)yaw效果

Unity的Rotate和Transform.eulerAngles

unity的inspector面板中的欧拉角只是编辑器扩展的显示,实际是用四元数存储的,最后反推出欧拉角并显示

image-20220422113309814

如果像上一节中的方式操作,第三步操作中修改inspector的rotate的x分量为90时,会发现z分量和y分量也被修改了,z变为30,而y变为了-30

两者的关系

  • inspector里设置Transform.localEulerAngles等同于Transform.Rotate(eulerAngles, Space.Self)

  • inspector里设置Transform.eulerAngles等同于Transform.Rotate(eulerAngles, Space.World)

transform.localEulerAngles = (10f, 20f, 30f);

等同于以下,即设置transform.localEulerAngles相当于以当前(即未旋转前)的本地坐标系为参考,先后分别绕z-x-y轴旋转了30、10、20度

transform.Rotate(new Vector3(10f, 20f, 30f), Space.Self);

(虽然是按z-x-y的顺序使用欧拉角进行旋转)但不等同于以下,因为每次旋转操作都会改变当前坐标系,即下一次旋转时参考坐标系变了,而之前的操作(一次绕3个轴旋转)都是相对于旋转前的本地坐标系为参考,称为静态欧拉角

transform.Rotate(new Vector3(0f, 0f, 30f), Space.Self);
transform.Rotate(new Vector3(10f, 0f, 0f), Space.Self);
transform.Rotate(new Vector3(0f, 20f, 0f), Space.Self);

transform.eulerAnglestransform.Rotate(eulerAngles, Space.World)也类似前两者之间的关系。不同的是,旋转前参考的不是本地坐标系,而是世界坐标系

public void Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self);

参考:

静态/动态欧拉角

将物体放置在scene的root下(即没有任何父物体),如果分别设置inspector的rotate的x-y-z为90、30、30,无法得到和第一节相同的结果,看起来物体像是绕着世界坐标系的各个轴旋转的。

造成以上结果的原因是,Unity中的这些操作都是相对于旋转前的坐标轴,称为静态欧拉角。第一节中的操作是绕自身坐标轴旋转,而自身坐标轴是会因为旋转而改变的,称为动态欧拉角

具体来说就是:

  • 因为没有任何父物体,物体的本地坐标系就是世界坐标系

  • 修改inspector的rotate就是修改Transform.localEulerAngles,但这里的localEulerAngles已经等同于eulerAngles(相对于世界坐标系)

  • 设置transform.eulerAngles,相当于以当前(即未旋转前)的本地坐标系为参考,先后分别绕z-x-y轴旋转

参考:动态与静态欧拉角视角下的万向节死锁(Gimbal Lock)问题 - 知乎 (zhihu.com)

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值