四元數(shù)的理解(簡(jiǎn)單說就是旋轉(zhuǎn)軸加旋轉(zhuǎn)角)

四元數(shù)介紹

旋轉(zhuǎn)辅辩,應(yīng)該是三種坐標(biāo)變換——縮放炒事、旋轉(zhuǎn)和平移臀栈,中最復(fù)雜的一種了。大家應(yīng)該都聽過挠乳,有一種旋轉(zhuǎn)的表示方法叫四元數(shù)权薯。按照我們的習(xí)慣,我們更加熟悉的是另外兩種旋轉(zhuǎn)的表示方法——矩陣旋轉(zhuǎn)和歐拉旋轉(zhuǎn)睡扬。矩陣旋轉(zhuǎn)使用了一個(gè)4*4大小的矩陣來表示繞任意軸旋轉(zhuǎn)的變換矩陣盟蚣,而歐拉選擇則是按照一定的坐標(biāo)軸順序(例如先x、再y卖怜、最后z)屎开、每個(gè)軸旋轉(zhuǎn)一定角度來變換坐標(biāo)或向量,它實(shí)際上是一系列坐標(biāo)軸旋轉(zhuǎn)的組合马靠。

那么奄抽,四元數(shù)又是什么呢?簡(jiǎn)單來說甩鳄,四元數(shù)本質(zhì)上是一種高階復(fù)數(shù)(聽不懂了吧逞度。。妙啃。)档泽,是一個(gè)四維空間,相對(duì)于復(fù)數(shù)的二維空間。我們高中的時(shí)候應(yīng)該都學(xué)過復(fù)數(shù)馆匿,一個(gè)復(fù)數(shù)由實(shí)部和虛部組成抑胎,即x = a + bi,i是虛數(shù)單位甜熔,如果你還記得的話應(yīng)該知道i^2 = -1圆恤。而四元數(shù)其實(shí)和我們學(xué)到的這種是類似的,不同的是腔稀,它的虛部包含了三個(gè)虛數(shù)單位盆昙,i、j焊虏、k淡喜,即一個(gè)四元數(shù)可以表示為x = a + bi + cj + dk。那么诵闭,它和旋轉(zhuǎn)為什么會(huì)有關(guān)系呢炼团?

在Unity里,tranform組件有一個(gè)變量名為rotation疏尿,它的類型就是四元數(shù)瘟芝。很多初學(xué)者會(huì)直接取rotation的x、y褥琐、z锌俱,認(rèn)為它們分別對(duì)應(yīng)了Transform面板里R的各個(gè)分量。當(dāng)然很快我們就會(huì)發(fā)現(xiàn)這是完全不對(duì)的敌呈。實(shí)際上贸宏,四元數(shù)的x、y磕洪、z和R的那三個(gè)值從直觀上來講沒什么關(guān)系吭练,當(dāng)然會(huì)存在一個(gè)表達(dá)式可以轉(zhuǎn)換,在后面會(huì)講析显。

大家應(yīng)該和我一樣都有很多疑問鲫咽,既然已經(jīng)存在了這兩種旋轉(zhuǎn)表示方式,為什么還要使用四元數(shù)這種聽起來很難懂的東西呢叫榕?我們先要了解這三種旋轉(zhuǎn)方式的優(yōu)缺點(diǎn):

  • 矩陣旋轉(zhuǎn)

  • 優(yōu)點(diǎn):

  • 旋轉(zhuǎn)軸可以是任意向量浑侥;

  • 缺點(diǎn):

  • 旋轉(zhuǎn)其實(shí)只需要知道一個(gè)向量+一個(gè)角度,一共4個(gè)值的信息晰绎,但矩陣法卻使用了16個(gè)元素;

  • 而且在做乘法操作時(shí)也會(huì)增加計(jì)算量括丁,造成了空間和時(shí)間上的一些浪費(fèi)荞下;

  • 歐拉旋轉(zhuǎn)

  • 優(yōu)點(diǎn):

  • 很容易理解,形象直觀;

  • 表示更方便尖昏,只需要3個(gè)值(分別對(duì)應(yīng)x仰税、y、z軸的旋轉(zhuǎn)角度)抽诉;但按我的理解陨簇,它還是轉(zhuǎn)換到了3個(gè)3*3的矩陣做變換,效率不如四元數(shù)迹淌;

  • 缺點(diǎn):

  • 之前提到過這種方法是要按照一個(gè)固定的坐標(biāo)軸的順序旋轉(zhuǎn)的河绽,因此不同的順序會(huì)造成不同的結(jié)果;

  • 會(huì)造成萬向節(jié)鎖(Gimbal Lock)的現(xiàn)象唉窃。這種現(xiàn)象的發(fā)生就是由于上述固定坐標(biāo)軸旋轉(zhuǎn)順序造成的耙饰。理論上,歐拉旋轉(zhuǎn)可以靠這種順序讓一個(gè)物體指到任何一個(gè)想要的方向纹份,但如果在旋轉(zhuǎn)中不幸讓某些坐標(biāo)軸重合了就會(huì)發(fā)生萬向節(jié)鎖苟跪,這時(shí)就會(huì)丟失一個(gè)方向上的旋轉(zhuǎn)能力,也就是說在這種狀態(tài)下我們無論怎么旋轉(zhuǎn)(當(dāng)然還是要原先的順序)都不可能得到某些想要的旋轉(zhuǎn)效果蔓涧,除非我們打破原先的旋轉(zhuǎn)順序或者同時(shí)旋轉(zhuǎn)3個(gè)坐標(biāo)軸件已。這里有個(gè)視頻可以直觀的理解下;

  • 由于萬向節(jié)鎖的存在元暴,歐拉旋轉(zhuǎn)無法實(shí)現(xiàn)球面平滑插值篷扩;

  • 四元數(shù)旋轉(zhuǎn)

  • 優(yōu)點(diǎn):

  • 可以避免萬向節(jié)鎖現(xiàn)象;

  • 只需要一個(gè)4維的四元數(shù)就可以執(zhí)行繞任意過原點(diǎn)的向量的旋轉(zhuǎn)昨寞,方便快捷瞻惋,在某些實(shí)現(xiàn)下比旋轉(zhuǎn)矩陣效率更高;

  • 可以提供平滑插值援岩;

  • 缺點(diǎn):

  • 比歐拉旋轉(zhuǎn)稍微復(fù)雜了一點(diǎn)點(diǎn)歼狼,因?yàn)槎嗔艘粋€(gè)維度;

  • 理解更困難享怀,不直觀羽峰;

四元數(shù)和歐拉角

基礎(chǔ)知識(shí)

前面說過,一個(gè)四元數(shù)可以表示為q = w + xi + yj + zk添瓷,現(xiàn)在就來回答這樣一個(gè)簡(jiǎn)單的式子是怎么和三維旋轉(zhuǎn)結(jié)合在一起的梅屉。為了方便,我們下面使用q = ((x, y, z)鳞贷,w) = (v, w)坯汤,其中v是向量,w是實(shí)數(shù)搀愧,這樣的式子來表示一個(gè)四元數(shù)惰聂。

我們先來看問題的答案疆偿。我們可以使用一個(gè)四元數(shù)q=((x,y,z)sinθ2, cosθ2) 來執(zhí)行一個(gè)旋轉(zhuǎn)。具體來說搓幌,如果我們想要把空間的一個(gè)點(diǎn)P繞著單位向量軸u = (x, y, z)表示的旋轉(zhuǎn)軸旋轉(zhuǎn)θ角度杆故,我們首先把點(diǎn)P擴(kuò)展到四元數(shù)空間,即四元數(shù)p = (P, 0)溉愁。那么处铛,旋轉(zhuǎn)后新的點(diǎn)對(duì)應(yīng)的四元數(shù)(當(dāng)然這個(gè)計(jì)算而得的四元數(shù)的實(shí)部為0,虛部系數(shù)就是新的坐標(biāo))為:

p′=qpq?1

其中拐揭,q=(cosθ2, (x,y,z)sinθ2) 撤蟆,q?1=q?N(q),由于u是單位向量投队,因此 N(q)=1枫疆,即q?1=q?。右邊表達(dá)式包含了四元數(shù)乘法敷鸦。相關(guān)的定義如下:

  • 四元數(shù)乘法:q1q2=(v1→×v2→+w1v2→+w2v1→,w1w2?v1→?v2→)

  • 共軛四元數(shù):q?=(?v? ,w)

  • 四元數(shù)的模:N(q) = √(x^2 + y^2 + z^2 +w^2)息楔,即四元數(shù)到原點(diǎn)的距離

  • 四元數(shù)的逆:q?1=q?N(q)

它的證明這里不再贅述,有興趣的可以參見這篇文章扒披。主要思想是構(gòu)建了一個(gè)輔助向量k值依,它是將p繞旋轉(zhuǎn)軸旋轉(zhuǎn)θ/2得到的。證明過程嘗試證明wk?=kv?碟案,以此證明w與v愿险、k在同一平面內(nèi),且與v夾角為θ价说。

我們舉個(gè)最簡(jiǎn)單的例子:把點(diǎn)P(1, 0, 1)繞旋轉(zhuǎn)軸u = (0, 1, 0)旋轉(zhuǎn)90°辆亏,求旋轉(zhuǎn)后的頂點(diǎn)坐標(biāo)。首先將P擴(kuò)充到四元數(shù)鳖目,即p = (P, 0)扮叨。而q = (u*sin45°, cos45°)。求p′=qpq?1的值领迈。建議大家一定要在紙上計(jì)算一邊彻磁,這樣才能加深印象,連筆都懶得動(dòng)的人還是不要往下看了狸捅。最后的結(jié)果p` = ((1, 0, -1), 0)衷蜓,即旋轉(zhuǎn)后的頂點(diǎn)位置是(1, 0, -1)。

如果想要得到復(fù)合旋轉(zhuǎn)尘喝,只需類似復(fù)合矩陣那樣左乘新的四元數(shù)磁浇,再進(jìn)行運(yùn)算即可。

我們來總結(jié)下四元數(shù)旋轉(zhuǎn)的幾個(gè)需要注意的地方:

  • 用于旋轉(zhuǎn)的四元數(shù)朽褪,每個(gè)分量的范圍都在(-1扯夭,1)鳍贾;
  • 每一次旋轉(zhuǎn)實(shí)際上需要兩個(gè)四元數(shù)的參與鞍匾,即q和q*交洗;
  • 所有用于旋轉(zhuǎn)的四元數(shù)都是單位四元數(shù),即它們的模是1橡淑;

下面是幾點(diǎn)建議:

  • 實(shí)際上构拳,在Unity里即便你不知道上述公式和變換也絲毫不妨礙我們使用四元數(shù),但是有一點(diǎn)要提醒你梁棠,除非你對(duì)四元數(shù)非常了解置森,那么不要直接對(duì)它們進(jìn)行賦值。
  • 如果你不想知道原理符糊,只想在Unity里找到對(duì)應(yīng)的函數(shù)來進(jìn)行四元數(shù)變換凫海,那么你可以使用這兩個(gè)函數(shù):Quaternion.EulerQuaternion.eulerAngles。它們基本可以滿足絕大多數(shù)的四元數(shù)旋轉(zhuǎn)變換男娄。

和其他類型的轉(zhuǎn)換

首先是軸角到四元數(shù):

給定一個(gè)單位長(zhǎng)度的旋轉(zhuǎn)軸(x, y, z)和一個(gè)角度θ行贪。對(duì)應(yīng)的四元數(shù)為:

q=((x,y,z)sinθ2, cosθ2)

這個(gè)公式的推導(dǎo)過程上面已經(jīng)給出。

歐拉角到四元數(shù):

給定一個(gè)歐拉旋轉(zhuǎn)(X, Y, Z)(即分別繞x軸模闲、y軸和z軸旋轉(zhuǎn)X建瘫、Y、Z度)尸折,則對(duì)應(yīng)的四元數(shù)為:

x = sin(Y/2)sin(Z/2)cos(X/2)+cos(Y/2)cos(Z/2)sin(X/2)
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)

它的證明過程可以依靠軸角到四元數(shù)的公式進(jìn)行推導(dǎo)啰脚。

其他參考鏈接:

  1. Euler to Quaternion
  2. Quaternion To Euler
  3. AngleAxis to Quaternion
  4. Quaternion to AngleAxis

四元數(shù)的插值

這里的插值指的是球面線性插值。

設(shè)t是一個(gè)在0到1之間的變量实夹。我們想要基于t求Q1到Q2之間插值后四元數(shù)Q橄浓。它的公式是:

Q3 = (sin((1-t)A)/sin(A))Q1 + (sin((tA)/sin(A))Q2)

Q = Q3/|Q3|,即單位化

四元數(shù)的創(chuàng)建

在了解了上述知識(shí)后亮航,我們就不需要那么懼怕四元數(shù)了荸实,實(shí)際上它和矩陣類似,不同的只是它的表示方式以及運(yùn)算方式塞赂。那么在Unity里如何利用四元數(shù)進(jìn)行旋轉(zhuǎn)呢泪勒?Unity里提供了非常多的方式來創(chuàng)建一個(gè)四元數(shù)。例如Quaternion.AngleAxis(float angle, Vector3 axis)宴猾,它可以返回一個(gè)繞軸線axis旋轉(zhuǎn)angle角度的四元數(shù)變換圆存。我們可以一個(gè)Vector3和它進(jìn)行左乘,就將得到旋轉(zhuǎn)后的Vector3仇哆。在Unity里只需要用一個(gè)“ * ”操作符就可以進(jìn)行四元數(shù)對(duì)向量的變換操作沦辙,相當(dāng)于我們上述講到的p′=qpq?1操作。如果我們想要進(jìn)行多個(gè)旋轉(zhuǎn)變換讹剔,只需要左乘其他四元數(shù)變換即可油讯。例如下面這樣:

Vector3 newVector = Quaternion.AngleAxis(90, Vector3.up) * Quaternion.LookRotation(someDirection) * someVector;

盡管歐拉角更容易我們理解详民,但四元數(shù)比歐拉角要強(qiáng)大很多。Unity提供了這兩種方式供我們選擇陌兑,我們可以選擇最合適的變換沈跨。

例如,如果我們需要對(duì)旋轉(zhuǎn)進(jìn)行插值兔综,我們可以首先使用Quaternion.eulerAngles來得到歐拉角度饿凛,然后使用Mathf.Clamp對(duì)其進(jìn)行插值運(yùn)算。

最后更新Quaternion.eulerAngles或者使用Quaternion.Euler(yourAngles)來創(chuàng)建一個(gè)新的四元數(shù)软驰。

又例如涧窒,如果你想要組合旋轉(zhuǎn),比如讓人物的腦袋向下看或者旋轉(zhuǎn)身體锭亏,兩種方法其實(shí)都可以纠吴,但一旦這些旋轉(zhuǎn)不是以世界坐標(biāo)軸為旋轉(zhuǎn)軸,比如人物扭動(dòng)脖子向下看等慧瘤,那么四元數(shù)是一個(gè)更合適的選擇戴已。Unity還提供了transform.forward, transform.right and transform.up 這些非常有用的軸,這些軸可以和Quaternion.AngleAxis組合起來碑隆,來創(chuàng)建非常有用的旋轉(zhuǎn)組合恭陡。例如,下面的代碼讓物體執(zhí)行低頭的動(dòng)作:

transform.rotation = Quaternion.AngleAxis(degrees, transform.right) * transform.rotation;

關(guān)于Quaternion的其他函數(shù)上煤,后面再補(bǔ)充吧休玩,原理類似~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市劫狠,隨后出現(xiàn)的幾起案子拴疤,更是在濱河造成了極大的恐慌,老刑警劉巖独泞,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呐矾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡懦砂,警方通過查閱死者的電腦和手機(jī)蜒犯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荞膘,“玉大人罚随,你說我怎么就攤上這事卡儒∪啵” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵霜幼,是天一觀的道長(zhǎng)屠升。 經(jīng)常有香客問我潮改,道長(zhǎng)狭郑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任汇在,我火速辦了婚禮翰萨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘趾疚。我一直安慰自己缨历,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布糙麦。 她就那樣靜靜地躺著,像睡著了一般丛肮。 火紅的嫁衣襯著肌膚如雪赡磅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天宝与,我揣著相機(jī)與錄音焚廊,去河邊找鬼。 笑死习劫,一個(gè)胖子當(dāng)著我的面吹牛咆瘟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播诽里,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼袒餐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了谤狡?” 一聲冷哼從身側(cè)響起灸眼,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墓懂,沒想到半個(gè)月后焰宣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捕仔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年匕积,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片榜跌。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闪唆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斜做,到底是詐尸還是另有隱情苞氮,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布瓤逼,位于F島的核電站笼吟,受9級(jí)特大地震影響库物,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贷帮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一戚揭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撵枢,春花似錦民晒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沃但,卻和暖如春磁滚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背宵晚。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工垂攘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人淤刃。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓晒他,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逸贾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陨仅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 原文地址:http://www.3dgep.com/understanding-quaternios/ 轉(zhuǎn)自文章:...
    徐大徐閱讀 5,416評(píng)論 1 9
  • 歐拉旋轉(zhuǎn)、四元數(shù)耕陷、矩陣旋轉(zhuǎn)之間的差異 除了歐拉旋轉(zhuǎn)以外掂名,還有兩種表示旋轉(zhuǎn)的方式:矩陣旋轉(zhuǎn)和四元數(shù)旋轉(zhuǎn)。接下來我們比...
    AndrewFan閱讀 2,529評(píng)論 0 3
  • 四元數(shù)介紹:【Unity技巧】四元數(shù)(Quaternion)和旋轉(zhuǎn) - CSDN博客 Quaternion類 Qu...
    向前ing_閱讀 3,083評(píng)論 0 1
  • 歐拉角和四元數(shù) 筆記主要摘自下列博文和回答中 如何通俗地解釋歐拉角哟沫?之后為何要引入四元數(shù)饺蔑? - 知乎 【Unity...
    一只浩閱讀 1,080評(píng)論 0 0
  • 二維旋轉(zhuǎn)矩陣(2D Rotation Matrix) 在歐幾里得坐標(biāo)系下,二維的旋轉(zhuǎn)矩陣可以用一個(gè)旋轉(zhuǎn)角 $\th...
    yfwz100閱讀 5,476評(píng)論 1 2