四元数又是什么呢?简单来说,四元数本质上是一种高阶复数(听不懂了吧。。。),是一个四维空间,相对于复数的二维空间。我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即x = a + bi,i是虚数单位,如果你还记得的话应该知道i^2 = -1。而四元数其实和我们学到的这种是类似的,不同的是,它的虚部包含了三个虚数单位,i、j、k,即一个四元数可以表示为x = a + bi + cj + dk。那么,它和旋转为什么会有关系呢?
需要添加如下引用:
System.Configuration
System.Data
System.EnterpriseServices
System.Security
System.XML
using UnityEngine;
using System.Collections;
using System;
using
System.Data;
using System.Data...
四元数又是什么呢?简单来说,四元数本质上是一种高阶复数(听不懂了吧。。。),是一个四维空间,相对于复数的二维空间。我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即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的矩阵做变换,效率不如四元数;
缺点:
之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。这里有个视频可以直观的理解下;
由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
四元数旋转
优点:
可以避免万向节锁现象;
只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
可以提供平滑插值;
缺点:
比欧拉旋转稍微复杂了一点点,因为多了一个维度;
理解更困难,不直观;
首先,单位四元数才能表示旋转,比如一个单位四元数可以写为
表示将一个向量绕(x,y,z)轴旋转 theta/2 度。
只要将一个向量看成四元数,然后乘以这个四元数即可。比如一个向量(w,x,y,z)为(0,1,2,3),
那么利用四元数的乘法,用(0,1,2,3)*q即可
哈密尔顿
为了纪念四元数的发明者哈密尔顿,爱尔兰于1943年11月15日发行了下面这张邮票:
哈密尔顿简直是个天才,哈密尔顿从小到进入大学之前没有进过学校读书,他的教育是靠叔父传授以及自学。他找到了法国数学家克莱罗(Clairaut)写的《代数基础》一书,很快就学会了代数,然后看牛顿写的《数理原理》。在16岁时就读法国著名数学家和天文学家拉普拉斯(Laplace)五册的《天体力学》,他发现拉普拉斯关于力的平行四边形法则的证明的错误.
四元数的概念是由爱尔兰数学家Sir William Rowan Hamilton发明的(1843年,都柏林)。Hamilton当时正和他的妻子前往爱尔兰皇家研究院,当他从Brougham桥通过皇家运河时,他领悟到了一个激动人心的东西,并立刻把它刻在桥的一个石头上:
i2=j2=k2=ijk=−1
i2=j2=k2=ijk=−1
关于哈密尔顿的介绍可以看这篇博客: 邮票上的数学家(10)哈密尔顿(爱尔兰)
四元数旋转推导过程
1.基本概念
(1) 四元数的一般形式如下:q=q0+q1i+q2j+q3kq=q0+q1i+q2j+q3k
(2) 单位四元数:满足四元数的模为1,即q02+q12+q22+q32=1q02+q12+q22+q32=1
(3) 四元数的三角形式:q=cosθ2+u⃗ sinθ2q=cosθ2+u→sinθ2
(4)共轭四元数:q∗=q0−q1i−q2j−q3kq∗=q0−q1i−q2j−q3k
(5) 纯四元数:q=q1i+q2j+q3kq=q1i+q2j+q3k
(6)四元数与空间旋转:
Rq(p)=qpq−1
Rq(p)=qpq−1
其中:
qq:单位四元数
q−1q−1:四元数的逆,对于单位四元数, q∗=q−1q∗=q−1
pp:纯四元数
Rq(p):也是一个纯四元数Rq(p):也是一个纯四元数
2. 欧拉角的万向锁问题
先看一个简单的欧拉旋转,如下图所示:欧拉旋转需要先确定旋转顺序,我们可以定义X-Y-Z的顺序(总共有12种旋转顺序),那么什么是万向锁呢,我们可以用手机在桌子上进行旋转,以手机的正面为xy平面,以手机的厚度的方向作为z轴,我们先绕x转一个角度,然后再绕y轴旋转90度,我们会发现一个问题,当我们再绕z轴旋转一个角度,效果等同于我开始绕x轴旋转另外一个角度,再绕y轴旋转90度就行了.
我们的欧拉旋转只能表示二维空间了,这是解我们的微分方程会出现退化现象,造成我们的微分方程无法解的情况。这样说似乎还是比较模糊,那么我们举一个例子:
如图所示:XwYwZwXwYwZw是世界坐标系,XiYiZiXiYiZi是机体坐标系,我们先绕XiXi轴旋转30∘30∘,再绕YiYi旋转90∘90∘,如下图所示:
此时我们的XwXw和ZiZi在同一直线上,最后我们再绕ZiZi旋转40∘40∘,如下图所示:
我们会发现一个问题,无论我们怎么旋转,我们的坐标都是(30,90,z),也就是绕z轴的旋转角度我们无法衡量的,这也就是我们的万向锁问题。
3. 四元数推导
复数旋转
首先我们看一个复数p=a+bip=a+bi在复平面的表示:
现在我们将它旋转角度θθ,先定义另外一个复数q=cosθ+isinθq=cosθ+isinθ,我们发现,复数的乘法表示了一种旋转:
qp=(acosθ−bsinθ)+i(asinθ+bcosθ)
qp=(acosθ−bsinθ)+i(asinθ+bcosθ)
这个复数恰好就是 pp旋转θθ角度后的值:
三维复数旋转
我们看到了二维复数乘法可以表示旋转,那么三维空间呢。按照举一反三的思想,我们会想到再增加一个虚数作为第三个维度,这个就要涉及到我们的向量的叉乘,如下图所示:
向量叉乘的结果是两个向量构成平面的垂直向量,那么我们定义两个个三维的复数:
z1=a1+b1i+c1jz2=a2+b2i+c2j
z1=a1+b1i+c1jz2=a2+b2i+c2j
其中 i2=j2=−1i2=j2=−1,我们类似的进行复数的乘法,得到:
z1z2=(a1a2−b1b2−c1c2)+(a1b2+a2b1)i+(a1c2+a2c1)j+b1c2ij+b2c1ji
z1z2=(a1a2−b1b2−c1c2)+(a1b2+a2b1)i+(a1c2+a2c1)j+b1c2ij+b2c1ji
我们会发现,如果没有 ij和jiij和ji这两项,我们三维的复数旋转也就没问题,那该如何处理呢?
四元数旋转
哈密尔顿引入四维的四元数:q=q0+q1i+q2j+q3k,其中i2=j2=k2=−1q=q0+q1i+q2j+q3k,其中i2=j2=k2=−1,根据向量的叉乘可以定义下列一些关系:
可以得到下列关系:
ij=−ji=kjk=−kj=iki=−ik=ji2=j2=k2=ijk=−1
ij=−ji=kjk=−kj=iki=−ik=ji2=j2=k2=ijk=−1
为了方便理解,我们将四元数写成向量的形式: q=[s,v⃗ ]q=[s,v→],我们可以理解为 ss为实部,向量v⃗ v→表示的就是三维空间,下面我们看一下四元数的乘法:
qa=[sa,a⃗ ]qb=[sb,b⃗ ]qaqb=[sasb−a⃗ ⋅b⃗ ,sab⃗ +sba⃗ +a⃗ ×b⃗ ]
qa=[sa,a→]qb=[sb,b→]qaqb=[sasb−a→⋅b→,sab→+sba→+a→×b→]
由于我们研究的是三维空间,因此我们可以令 qaqa为一个纯四元数,即 qa=[0,a⃗ ]qa=[0,a→].则可以得到:
qaqb=[−a⃗ ⋅b⃗ ,sba⃗ +a⃗ ×b⃗ ]
qaqb=[−a→⋅b→,sba→+a→×b→]
从上面可以看到,一个普通的四元数是无法将三维空间映射到三维空间的,我们令向量点乘的部分为零,此时,一个纯四元数就可以旋转为另一个纯四元数.为了表现出旋转,这里我们用四元数的三角表示方式: qb=[cosθ,sinθb⃗ ]qb=[cosθ,sinθb→],令 a⃗ ⋅b⃗ =0a→⋅b→=0,则有:
qaqb=[0,a⃗ cosθ+a⃗ ×b⃗ sinθ]
qaqb=[0,a→cosθ+a→×b→sinθ]
我们没有对向量 b⃗ b→做任何限制,下面来用一个例子说明应当对向量 b⃗ b→做什么限制.
令 p=[0,2i],q=[2√2,2√2b⃗ ]p=[0,2i],q=[22,22b→],考虑到 a⃗ ⋅b⃗ =0a→⋅b→=0,令 b⃗ =|b⃗ |kb→=|b→|k,则将 pp旋转45∘45∘后得到:
p′=qp=[0,2–√|b⃗ |i+2–√|b⃗ |j]
p′=qp=[0,2|b→|i+2|b→|j]
旋转之前,纯四元数 pp的模长为|p|=2|p|=2,旋转过后,纯四元数 p′p′的模长 |p′|=2|b⃗ ||p′|=2|b→|,所以我们要给旋转四元数又加上一个约束:四元数 qq的模长为1,即qq是一个单位四元数.
但是上面的旋转是有缺点的,因为其限制了我们的旋转轴和需要被旋转的四元数必须是垂直的(a⃗ ⋅b⃗ =0a→⋅b→=0),而不能达到任意的旋转.这时,聪明的哈密尔顿发现,一个四元数会把一个纯四元数拉到四维空间,但它的共轭又会把这个四维的空间拉回到三维空间.我们以一个简单的例子来说明这个问题:
p=[0,2i],q=[fracsqrt22,fracsqrt66(i+j+k)],则q∗=[fracsqrt22,−fracsqrt66(i+j+k)]
p=[0,2i],q=[fracsqrt22,fracsqrt66(i+j+k)],则q∗=[fracsqrt22,−fracsqrt66(i+j+k)]
旋转之后的四元数 Rq(p)Rq(p):
Rq(p)=[0,2j]
Rq(p)=[0,2j]
这里需要注意的一点是,因为经过两次的旋转,所以旋转的角度是 2θ2θ,这就是为什么我们常常看到的旋转四元数是一下形式:
q=cosθ2+u⃗ sinθ2,其中|u⃗ |=1
q=cosθ2+u→sinθ2,其中|u→|=1
Quaternions – Ken Shoemake
对于一个轴已经固定的轮子来说,只要一元数字来表示旋转,就是旋转的角度;
对于空间的物体,用三元(维)数字(就是三维立体坐标,或者向量)可以描述他旋转的轴(或方向),一元(维)数可以表示旋转的角度
相关问题推荐
第一种方法:通过点击场景文件打开Unity游戏工程找到Unity游戏工程所在的目录,我这里的工程放在在E盘根路径的Unity_workspace文件夹中。注意:unity软件不支持中文路径,所以不要把工程放在中文文件夹下。我们在这里就打开New Unity Project 4工程,进入到Ne...
如果是学习研究的话,当然是体验官方的最新版本。要是项目开发的话,还是要选择长期稳定版本,也就是大版本的LTS。比如2017.4或者是2018.4都是LTS版本,至于后面的小版本可以去看下更新的内容来做选择吧!...
unity3D是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC...
1、Unity3D:如果你需要开发大型游戏,或需要开发3D游戏的,请选这个。2、Cocos2D-x:如果你开发的是中小型游戏,对安装包大小比较在意的,请选这个。3、Andengine、Cocos2D-iPhone:如果你只为开发单平台游戏,又非常在意速度和安装包大小,请选这个。最后。...
首先在场景中调整好你要观看的视角选择摄像机,按下Ctrl+Shift+F或者菜单栏->GameObject->Align with view在不行的话,可以调整摄像机的Position 和 Rotation
将MeshRender组件移除即可:
1.在Asset store里选择一个skybox。 2.从素材库中选择一个人物角色,也可以自己建模或者在其他软件中做好再导进来。 3.想好角色如何运动,然后用自己比较熟悉的语言编写来作展示,这段代码可以实现当你按下键盘上的A/D/S/W的按键时,角色会向前后左右四个方向的...
还是要学好编程基础呀如果你觉得编程很苦难 不一定要从c#开始学 学学js flash as等等 有个梯度就好多了如果要用好unity 不会编程那是不行的 学习的过程中都有个头疼的过程 记住 头越痛 代表你要接受的东西越多 坚持 你的大脑在和知识兼容中:D...
xcel 表的操作少不了要引入第三方库,首先我们需要引入 Excel.dll 和 ICSharpCode.SharpZipLib.dll,这两个类库在网上都能找到;然后我们还需要引入 System.Data.dll,这个类库在 Unity3D 的安装路径下的 Editor\Data\Mono\lib\mono\unity 文件夹下能找到...
需要添加如下引用: System.Configuration System.Data System.EnterpriseServices System.Security System.XML using UnityEngine; using System.Collections; using System; using System.Data; using System.Data...
物理引擎则使用动量、扭矩等用高等数学手段来模拟真实物体,这将得到更真实的效果且使我们的编码更加容易。
不能这样表述,三维通常是立体的空间,二维则是平面的。数学中通常是Oxyz表示空间直角坐标系,Oxy表示表示的是平面直角坐标系,你可以说空间直角坐标系中去掉Z轴可以转换为二维,因为去掉X或Y轴都能转换为二维。...
GameObject.renderer.enabled//是控制一个物体是否在屏幕上渲染或显示 而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的GameObject.Destroy()//表示移除物体或物体上的组件 代表销毁该物体 实际上该物体的内存并没有立即释放,而是等到这...
一:Overlay—覆盖模式类似于手机贴膜,所有UI都会显示在场景中2D,3D物体的上层在同一个Canvas下可以调整Canvas子物体的先后顺序,层级面板中越靠上则先被渲染多个Canvas下可以调整Canvas组件的Sort Order属性调整渲染顺序,数值越小的画布越先被渲染:Camer...
不得不说,Unity3d是个解放生产力的游戏引擎,自带了各种编辑器,可以进行一系列的可视化操作。需要注意的是,unity3d适合FPS游戏,物理游戏等中小型的游戏,并不太适合MMO开发。unity3d难学吗?如何学习unity3d呢?在学习之前又应该了解哪些内容呢?代码写不...
不是人工检查的,如果你的问题里面有敏感关键字,是发不出去的,现在国内所有的网站在发布文章时都要进行检查的,所以你在发之前先检查一下看问题里面是否有违禁词语。