旋转变换是三维空间变换中相对不太直观的变换方式,而且旋转后的最终结果与变换顺序密切相关,比如对于一个旋转角度(30,40,50)来说,先x轴旋转30°,再y轴旋转40°,最后绕z轴旋转50°,这只是一种变换顺序,其结果与其他变换顺序不同。
Unity中旋转API接口为Transform.Rotate(),那么对于Transform.Rotate(new Vector3(30, 40, 50))来说,究竟是选用的哪一种顺序呢?Unity官方文档中有说明,欧拉角旋转顺序为Z、X、Y,然而实际测试中发现,下面的代码的执行结果
[csharp] view plain copy print ? transform.Rotate(new Vector3(30, 40, 50));
与下面代码中顺序1的执行结果相同!!!
// 顺序1 transform.Rotate(new Vector3(0, 40, 0)); transform.Rotate(new Vector3(30, 0, 0)); transform.Rotate(new Vector3(0, 0, 50)); // 顺序2 // transform.Rotate(new Vector3(0, 0, 50)); // transform.Rotate(new Vector3(30, 0, 0)); // transform.Rotate(new Vector3(0, 40, 0));为什么实际执行与官方文档说的顺序恰好相反呢?这是一个很有趣的问题。
我们仔细想想,其实旋转除了角度顺序外,还与一个重要的因素相关,那就是旋转时所用的坐标系!
对于一个给定的旋转顺序(比如官方所说的Z、X、Y)和旋转角度(α,β,r),我们其实有两种坐标系可以进行选择:
绕坐标系E下的Z轴旋转α,绕坐标系E下的Y轴旋转β,绕坐标系E下的X轴旋转r,三次旋转均使用同一坐标系;绕坐标系E下的Z轴旋转α,绕坐标系E在绕Z轴旋转α后的新坐标系E'下的Y轴旋转β,绕坐标系E'在绕Y轴旋转β后的新坐标系E''下的X轴旋转r,三次旋转分别使用了不同的坐标系; 对于第一种情况来说,进行一次旋转时并不一起旋转当前坐标系,此坐标系我们称为惯性坐标系;第二种情况下,在旋转操作时,我们把坐标系一起转动,此坐标系我们称之为物体坐标系。知道了这些,我们就可以探寻为什么代码编写与官方文档说明的顺序相反了。对于Transform.Rotate(new Vector3(30, 40, 50))来说,坐标轴在单个坐标轴旋转过程中不变,执行完transform.Rotate后,坐标轴才发生变化,因而一行代码合并执行采用的是上面的情况1
而分开单独执行采用的是上面的情况2
Transform.Rotate(new Vector3(0, 40, 0));
Transform.Rotate(new Vector3(30, 0, 0));
Transform.Rotate(new Vector3(0, 0, 50));
于是,问题的焦点转移到:是否情况1中的zxy顺序旋转与情况2中的yxz顺序旋转得到的结果是一样的吗?答案是的!Unity
官方文档说明的旋转顺序指的是情况1下的顺序。这也就解释清楚了上面代码执行的问题
为什么情况1中的zxy顺序旋转与情况2中的yxz顺序旋转得到的结果是一样的呢?可以参考这篇文章
