unity--------------------四元数的旋转与原理
四元数介绍
旋转,应该是三种坐标变换——缩放、旋转和平移,中最复杂的一种了。大家应该都听过,有一种旋转的表示方法叫四元数。按照我们的习惯,我们更加熟悉的是另外两种旋转的表示方法——矩阵旋转和欧拉旋转。矩阵旋转使用了一个4*4大小的矩阵来表示绕任意轴旋转的变换矩阵,而欧拉选择则是按照一定的坐标轴顺序(例如先x、再y、最后z)、每个轴旋转一定角度来变换坐标或向量,它实际上是一系列坐标轴旋转的组合。
那么,四元数又是什么呢?简单来说,四元数本质上是一种高阶复数(听不懂了吧。。。),是一个四维空间,相对于复数的二维空间。我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即x = a + bi,i是虚数单位,如果你还记得的话应该知道i^2 = -1。而四元数其实和我们学到的这种是类似的,不同的是,它的虚部包含了三个虚数单位,i、j、k,即一个四元数可以表示为x = a + bi + cj + dk。那么,它和旋转为什么会有关系呢?
在Unity里,tranform组件有一个变量名为rotation,它的类型就是四元数。很多初学者会直接取rotation的x、y、z,认为它们分别对应了Transform面板里R的各个分量。当然很快我们就会发现这是完全不对的。实际上,四元数的x、y、z和R的那三个值从直观上来讲没什么关系,当然会存在一个表达式可以转换,在后面会讲。
大家应该和我一样都有很多疑问,既然已经存在了这两种旋转表示方式,为什么还要使用四元数这种听起来很难懂的东西呢?我们先要了解这三种旋转方式的优缺点:
- 矩阵旋转
- 优点:
- 旋转轴可以是任意向量;
- 缺点:
- 旋转其实只需要知道一个向量+一个角度,一共4个值的信息,但矩阵法却使用了16个元素;
- 而且在做乘法操作时也会增加计算量,造成了空间和时间上的一些浪费;
- 欧拉旋转
- 优点:
- 很容易理解,形象直观;
- 表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;
- 缺点:
- 四元数旋转
- 优点:
- 可以避免万向节锁现象;
- 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
- 可以提供平滑插值;
- 缺点:
- 比欧拉旋转稍微复杂了一点点,因为多了一个维度;
- 理解更困难,不直观;
四元数和欧拉角
基础知识
N(q)=1,即q−1=q∗。右边表达式包含了四元数乘法。相关的定义如下:
- 四元数乘法:q1q2=(v1→×v2→+w1v2→+w2v1→,w1w2−v1→⋅v2→)
- 共轭四元数:q∗=(−v⃗ ,w)
- 四元数的模:N(q) = √(x^2 + y^2 + z^2 +w^2),即四元数到原点的距离
- 四元数的逆:q−1=q∗N(q)
- 用于旋转的四元数,每个分量的范围都在(-1,1);
- 每一次旋转实际上需要两个四元数的参与,即q和q*;
- 所有用于旋转的四元数都是单位四元数,即它们的模是1;
- 实际上,在Unity里即便你不知道上述公式和变换也丝毫不妨碍我们使用四元数,但是有一点要提醒你,除非你对四元数非常了解,那么不要直接对它们进行赋值。
- 如果你不想知道原理,只想在Unity里找到对应的函数来进行四元数变换,那么你可以使用这两个函数:Quaternion.Euler和Quaternion.eulerAngles。它们基本可以满足绝大多数的四元数旋转变换。
和其他类型的转换
y = sin(Y/2)cos(Z/2)cos(X/2)+cos(Y/2)sin(Z/2)sin(X/2)
z = cos(Y/2)sin(Z/2)cos(X/2)-sin(Y/2)cos(Z/2)sin(X/2)
w = cos(Y/2)cos(Z/2)cos(X/2)-sin(Y/2)sin(Z/2)sin(X/2)
q = ((x, y, z), w)
四元数的插值
四元数的创建
- Vector3 newVector = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.LookRotation(someDirection) * someVector;
又例如,如果你想要组合旋转,比如让人物的脑袋向下看或者旋转身体,两种方法其实都可以,但一旦这些旋转不是以世界坐标轴为旋转轴,比如人物扭动脖子向下看等,那么四元数是一个更合适的选择。Unity还提供了transform.forward, transform.right and transform.up 这些非常有用的轴,这些轴可以和Quaternion.AngleAxis组合起来,来创建非常有用的旋转组合。例如,下面的代码让物体执行低头的动作:
- transform.rotation = Quaternion.AngleAxis(degrees, transform.right) * transform.rotation;
补充:欧拉旋转
欧拉旋转是怎么运作的
- 绕坐标系E下的Z轴旋转α,绕坐标系E下的Y轴旋转β,绕坐标系E下的X轴旋转r,即进行一次旋转时不一起旋转当前坐标系;
- 绕坐标系E下的Z轴旋转α,绕坐标系E在绕Z轴旋转α后的新坐标系E'下的Y轴旋转β,绕坐标系E'在绕Y轴旋转β后的新坐标系E''下的X轴旋转r, 即在旋转时,把坐标系一起转动;
- transform.Rotate(new Vector3(0, 30, 90));
原模型的方向和执行结果如下:
- // First case
- transform.Rotate(new Vector3(0, 30, 0));
- transform.Rotate(new Vector3(0, 0, 90));
- // Second case
- // transform.Rotate(new Vector3(0, 0, 90));
- // transform.Rotate(new Vector3(0, 30, 0));
两种情况的结果分别是:
数学模型
万向节锁
- transform.Rotate(new Vector3(0, 0, 40));
- transform.Rotate(new Vector3(0, 90, 0));
- transform.Rotate(new Vector3(80, 0, 0));
我们只需要固定中间一句代码,即使Y轴的旋转角度始终为90°,那么你会发现无论你怎么调整第一句和最后一句中的X或Z值,它会像一个钟表的表针一样总是在同一个平面上运动。
数学解释
- 顶
- 71
- 踩
- 7
- 41楼 qq7140777762017-08-23 20:30发表 [回复]

- 厉害,我是个渣渣,学习学习,哎
- 40楼 qq_318077112017-08-12 14:55发表 [回复]

- 欧拉角到四元数的转换 sin 和cos不是正弦和余弦吗 那是求角度的正余弦值 你上面用sinY/2 是啥意思呀?X Y Z是代表轴向 你要正弦一个轴向?
- 39楼 Cozak2017-06-10 11:00发表 [回复]

- 博主您好,您在万向节锁一节开头给出的文章中有一句话“静态欧拉角不存在万向节锁问题”,对此本人有以下疑问
根据那篇文章中对“静态欧拉角”的定义:“即绕世界坐标系三个轴的旋转,由于物体旋转过程中坐标轴保持静止,所以称为静态“
如果设x-y-z是参考系坐标(不随模型转动)而X-Y-Z是模型坐标系(跟随模型转动),模型顶点坐标始终在参考系坐标系下,那么静态欧拉角就是定义在x-y-z上的旋转
按照xyz顺规,旋转矩阵为R=R_x(α)R_y(β)R_z(γ),此时如果β=±90°,那么α和γ取任何值模型也只是在同一个水平面转动,即出现万向节锁
按照zxz顺规,旋转矩阵为R=R_z(α)R_x(β)R_z(γ),此时如果β=0°,那么同样会出现万向节锁而英文Wiki中关于“静态欧拉角”(根据定义描述)是写作“extrinsic rotations”,然而并没有说不存在万向节锁问题
翻过去Google也没有找到任何相关信息(除了没有任何来源说明的中文Wiki)希望学识渊博的博主能指一下方向,O(∩_∩)O谢谢
unity--------------------四元数的旋转与原理的更多相关文章
- Unity四元数和旋转
四元数介绍 旋转,应该是三种坐标变换——缩放.旋转和平移,中最复杂的一种了.大家应该都听过,有一种旋转的表示方法叫四元数.按照我们的习惯,我们更加熟悉的是另外两种旋转的表示方法——矩阵旋转和欧拉旋转. ...
- 【转】Unity四元数和向量相乘作用及其运算规则
作用:四元数和向量相乘表示这个向量按照这个四元数进行旋转之后得到的新的向量. 比如:向量vector3(0,0,10),绕着Y轴旋转90度,得到新的向量是vector3(10,0,0). 在unity ...
- 深入浅出!从语义角度分析隐藏在Unity协程背后的原理
Unity的协程使用起来比较方便,但是由于其封装和隐藏了太多细节,使其看起来比较神秘.比如协程是否是真正的异步执行?协程与线程到底是什么关系?本文将从语义角度来分析隐藏在协程背后的原理,并使用C++来 ...
- 四元数和旋转(Quaternion & rotation)
四元数和旋转(Quaternion & rotation) 本篇文章主要讲述3D空间中的旋转和四元数之间的关系.其中会涉及到矩阵.向量运算,旋转矩阵,四元数,旋转的四元数表示,四元数表示的旋转 ...
- Unity复杂的旋转-欧拉角和四元数
一.欧拉角欧拉角最容易表示,用三个变量X,Y,Z可以直观的表示绕着某个轴的旋转角度. 在Unity里就是Transform组件的Rotation里的X Y Z三个变量代表了欧拉角 二.四元数四元数相比 ...
- Unity四元数小问题整理
1.Unity中,四元数不能保存超过360度的旋转,所以如此大范围的旋转不能直接两个四元数做插值(当你用0度和721度的四元数做插值,它只会转1度,而不会转两圈). 2.要把旋转设置成某个方向,用Lo ...
- 关于Unity四元数相乘先后顺序的问题
在unity中四元数和向量相乘在unity中可以变换旋转.四元数和四元数相乘类似矩阵与矩阵相乘的效果. 矩阵相乘的顺序不可互换,只有特殊条件矩阵才可互换.四元数相乘类似,今天就因为这个问题掉进坑里了, ...
- Unity脚本-Rotate旋转相关知识点
1,Transform旋转 transform.Rotate(X, Y, Z);//分别绕X,Y,Z轴旋转,可写为绕某个轴旋转,栗子transform.Rotate(0, 90, 0); tr ...
- unity 欧拉旋转
欧拉旋转 在文章开头关于欧拉旋转的细节没有解释的太清楚,而又有不少人询问相关问题,我尽量把自己的理解写到这里,如有不对还望指出. 欧拉旋转是怎么运作的 欧拉旋转是我们最容易理解的一 ...
随机推荐
- Lua string.gsub (s, pattern, repl [, n])
lua的string函数导出在string module中.在lua5.1,同时也作为string类型的成员方法,因此,我们既可以写成string.gsub (s,……), 也可以s:gsub(). ...
- 【驱动】linux设备驱动·字符设备驱动开发
Preface 前面对linux设备驱动的相应知识点进行了总结,现在进入实践阶段! <linux设备驱动入门篇>:http://infohacker.blog.51cto.com/6751 ...
- windows开通https服务
一.申请ssl证书 建议1个免费的ssl证书申请网站,已测试,可用 1.注册https://login.wosign.com/reg.html?rf=buy 2.邮箱验证登录后访问https://bu ...
- git命令--git checkout 之 撤销提交到暂存区的更改
SYJ@WIN-95I6OG3AT1N /D/gitlab/ihr-kafka-produce (master) $ git status [由于工作区文件被修改了,所以显示为红色] On branc ...
- ZendStudio在kali下无法启动
错误如下 # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0 ...
- IE11 不能正常方法网页
由于将IE11升级到了 11 之前的网站无法正常使用, 如果是开发人员碰到之问题,使用了微软的asp.net 控件,那么将服务器的.net framework 升级到 4.5 http://www.m ...
- Android ViewPage的使用(一)
ViewPage是一个简单的页面切换组件,左右滑动的话,有效果,和ListView一样 也需要配合适配器(PagerAdapter)来使用. 先来个效果图吧 先随便创建3个view页面,用于放到 Vi ...
- vi/vim 中如何在每行行首或行尾插入指定字符串
行首 :%s/^/your_word/ 行尾 :%s/$/your_word/ 按键操作: 注释:ctrl+v 进入列编辑模式,向下或向上移动光标,把需要注释的行的开头标记起来,然后按大写的I,再插入 ...
- 火狐FireFox看视频不能全屏显示的问题
问题:最大化/全屏时显示有问题,不能全屏显示,只能看到左上角一部分画面. 解决办法:在画面右键弹出的菜单中选择[设置]——勾选[启用硬件加速].
- [TestLink]testlink安装
转自:http://www.51testing.com/html/25/465025-3711140.html bitnami参考:https://bitnami.com/stack/testlink ...