學習筆記3

Unity中的歐拉角和四元數(shù)

筆記主要參考以下的博文

??Unity中的歐拉旋轉 - Andrew的游戲世界 - CSDN博客

【Unity編程】Unity中關于四元數(shù)的API詳解 - Andrew的游戲世界 - CSDN博客


Unity中的歐拉角

順規(guī)

在經典力學里,時常用zxz順規(guī)來設定歐拉角;照著第二個轉動軸的軸名其弊,簡稱為x順規(guī)慕爬。另外,還有別種歐拉角組茵典。合法的歐拉角組中湘换,唯一的限制是,任何兩個連續(xù)的旋轉统阿,必須繞著不同的轉動軸旋轉彩倚。因此,一共有12種順規(guī)扶平。

Unity的歐拉角定義

Unity文檔中Transform.eulerAngles的定義帆离,本身是一個Vector3,就是一個三維矢量结澄, 分別含有xyz三個參數(shù)哥谷。

xyz代表了三個角度,它們定義了一組有序的旋轉麻献,即圍繞z軸旋轉z度们妥,然后圍繞x軸旋轉x度,然后圍繞y軸旋轉y度勉吻。你應該只去讀取或者直接設置這些數(shù)值监婶,不要增加它們,因為當角度超過360度將會失敗餐曼。應該使用Transform.Rotate去替代執(zhí)行旋轉操作压储。

在上述文檔中定義了在Unity中歐拉旋轉的順規(guī),即先圍繞z軸旋轉源譬,后繞x軸集惋,最后繞y軸。

Unity內部使用四元數(shù)去執(zhí)行旋轉踩娘,不會存儲歐拉角的累計值刮刑,因此它說超過360度會失敗是可以理解的喉祭,它用四元數(shù)執(zhí)行完運算之后,會更新最后對應的歐拉角數(shù)值雷绢,而這個結果歐拉角只是代表了等值的旋轉變化結果泛烙,卻無法代表中間過程,由于歐拉角旋轉Z軸361度與1度有一樣的結果翘紊,它便最后只存儲了1度蔽氨,以便于我們觀察和使用。

歐拉旋轉的軸

Unity中的Transform文檔有有這樣一個函數(shù)

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

這個函數(shù)提供了一個可選的相對空間坐標系參數(shù):

Space.Self 局部坐標系帆疟,意味著本次歐拉旋轉以物體當前的局部坐標朝向為基礎出發(fā)執(zhí)行旋轉鹉究。

Space.World 世界坐標系,意味著本次歐拉旋轉以物體當前的世界坐標朝向為基礎出發(fā)執(zhí)行旋轉踪宠。

最重要的倒不是它有可選的世界坐標系自赔,一般而言,常用的旋轉都是相對當前局部坐標系執(zhí)行的柳琢。并且在本次歐拉旋轉過程中绍妨,它的相對軸是始終不變的。

比如我們可以指定一組歐拉旋轉(90,60,30)柬脸,通過前述的順規(guī)我們知道他去,先繞Z軸旋轉30度,再繞X軸旋轉90度肖粮,再繞Y軸旋轉60度孤页,雖然有這樣的順序,但是Z旋轉后相對X軸涩馆、Y軸行施,都是執(zhí)行本組歐拉旋轉前的那個軸向,它沒有發(fā)生變動魂那,所以我稱它為“當前軸”蛾号。

而什么情況下是相對軸不變的呢?舉個例子涯雅,指定(90,60,30)這組歐拉旋轉鲜结,執(zhí)行Transform.Rotate(new Vector3(90,60,30))? ? 是執(zhí)行了一次歐拉旋轉,在這過程中它的相對軸保持不變活逆,但如果是這樣的旋轉方式:

Transform.Rotate(new Vector3(0,0,30))精刷;

Transform.Rotate(newVector3(90,0,0));

Transform.Rotate(new Vector3(0,60,0))蔗候;

這就是執(zhí)行了三次歐拉旋轉怒允,在執(zhí)行后兩次時其相對軸都會發(fā)生變化,顯然結果不是我們需要的(90,60,30)的歐拉角旋轉锈遥。

總結

Unity中的歐拉旋轉是按照Z纫事、X勘畔、Y順規(guī)執(zhí)行的旋轉,一組歐拉旋轉過程中丽惶,相對的軸向不會發(fā)生變化炫七。 Transform.Rotate(new Vector3(90,60,30)),它代表執(zhí)行了一組歐拉旋轉钾唬,它相對的是旋轉前的局部坐標朝向万哪。正是這種順規(guī)和軸向的定義,導致了萬向節(jié)死鎖的自然形成抡秆。

Unity中的四元數(shù)

四元數(shù)實際上和矩陣類似壤圃,不同的只是它的表示方式以及運算方式。

那么在Unity里如何利用四元數(shù)進行旋轉呢琅轧?

首先是創(chuàng)建四元數(shù),Unity里提供了非常多的方式來創(chuàng)建一個四元數(shù)踊挠。例Quaternion.AngleAxis(float angle, Vector3 axis)乍桂,它可以返回一個繞軸線axis旋轉angle角度的四元數(shù)變換。我們可以一個Vector3和它進行左乘效床,就將得到旋轉后的Vector3睹酌。在Unity里只需要用一個“ * ”操作符就可以進行四元數(shù)對向量的變換操作,相當于我們上述講到的p′=qpq?1操作剩檀。如果我們想要進行多個旋轉變換憋沿,只需要左乘其他四元數(shù)變換即可,例如

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

Unity中提供了關于四元數(shù)旋轉的API沪猴,即Quarternion類辐啄。Quaternion(四元數(shù))用于計算Unity旋轉。它們計算緊湊高效运嗜,不受萬向節(jié)鎖的困擾壶辜,并且可以很方便快速地進行球面插值。 Unity內部使用四元數(shù)來表示所有的旋轉担租。四元數(shù)是基于復數(shù)的砸民,因而理解起來難度很大,好在我們并不需要去給出參數(shù)的值奋救,而是只需要獲取和使用現(xiàn)有的旋轉(例如來自“Transform”)岭参,或者用四元數(shù)來構造新的旋轉(例如,在兩次旋轉之間平滑插入)即可尝艘。

一些常用的函數(shù):

Quaternion.LookRotation? ?前方演侯、上方標注矢量法創(chuàng)建四元數(shù)

Quaternion.Angle? ??計算兩個四元數(shù)前方矢量之間的夾角度數(shù)

Quaternion.Euler??歐拉角表示創(chuàng)建四元數(shù)

Quaternion.Slerp??球面插值

Quaternion.FromToRotation??A向到B向相對旋轉表示法創(chuàng)建四元數(shù)

Quaternion.identity? 為單位四元數(shù),即默認的無旋轉狀態(tài)

Quaternion 是一個結構體利耍,本身成員變量相對簡單蚌本,可以作為函數(shù)參數(shù)高效傳遞盔粹。

Unity的方向

Unity中使用左手坐標系,假如把世界坐標系跟東南西北進行結合起來看程癌,大致如下圖所示:

+x? ? ? ? ?東(右)????????????????????+y? ? ? ? ?上? ? ? ? ? ? ? ? +z? ? ? ? ? ? 前(北)

-x? ? ? ? ? 西(左)????????????????????-y? ? ? ? ? 下? ? ? ? ? ? ? ? -z? ? ? ? ? ? ?后(南)

以自己身體為例舷嗡,你站立在地面上,面朝北方嵌莉,此時就是默認方向进萄,也就是Unity中的方向就是面向+Z軸方向,那么此時+X軸在東方锐峭,+Y軸對應正上方中鼠。此時對應的歐拉角是(0,0,0),此時對應的前方矢量是(0,0,1),上方矢量是(0,1,0)沿癞。這里的上下左右的概念與Vector3類援雇、Transform類中的相應的方向函數(shù)也是相對應的。

確定方向的方法

1.歐拉角表示法

Unity中的歐拉旋轉方向為固定的zxy順規(guī)椎扬。

2.前方惫搏、上方標定矢量法

根據(jù)對局部坐標軸的描述, 構造對應的代表旋轉程度的四元數(shù)。

指的是從默認方向到LookRotation參數(shù)的變化量蚕涤。例如? ?Quaternionq2 = Quaternion.LookRotation(Vector3.down ,Vector3.forward); 是指從Unity默認方向到這個的變化量,按照左手坐標系,繞x轉90,從Z+到Y-筐赔。

3.?繞軸旋轉界定法

使物體沿某一指定的軸向旋轉一定的角度。這個方法也可以確定一個相對旋轉揖铜,它以從默認方向(此時前方+Z茴丰,上方+Y)出發(fā),沿著指定的軸向進行指定角度的旋轉天吓。旋轉后的前方和上方是確定的贿肩,所以可以確定朝向。

4.A向到B向相對旋轉表示法

從A向到B向的相對旋轉失仁,這種表示了一個旋轉的相對變化尸曼。比如A為(0,1,0),B為(0,0,1)萄焦,也就是相對旋轉量代表原來的上方被旋轉到了前方控轿,這樣的一個四元數(shù)也可以用歐拉角表示成(90,0,0),也就是沿著+X軸旋轉了90度拂封。

利用幾種表示方法在Untiy中創(chuàng)建四元數(shù)

Quaternion q1=Quaternion.Euler(90, 0, 0);? ? ?//方法1—歐拉角表示

Quaternion q2 = Quaternion.LookRotation(Vector3.down ,Vector3.forward);? //方法2—前方上方標注矢量法

Quaternion q3 = Quaternion.AngleAxis(90,Vector3.right);? //方法3—繞軸旋轉界定法?

Quaternion q4 = Quaternion.FromToRotation(Vector3.up, Vector3.forward);? ?// 方法4—A向到B向相對旋轉表示法

成員變量

eulerAngles 歐拉角茬射,返回當前四元數(shù)所對應的歐拉角

this[int] 可以使用類似數(shù)組和下標的形式從四元數(shù)中獲取四個四元數(shù)參數(shù)

四元數(shù)的具體參數(shù)x,y,z,w分量一般不手動設置,易出錯冒签。

identity 單位四元數(shù)在抛,也就是默認的無旋轉狀態(tài),此時與世界坐標相同萧恕,前方指向+Z刚梭,上方指向+Y

成員函數(shù)

靜態(tài)函數(shù)

1.static float Angle(Quaternion a, Quaternion b)? ?計算兩個四元數(shù)前方矢量之間的夾角度數(shù)

2.static Quaternion AngleAxis(float angle, Vector3 axis)? ?構建一個四元數(shù)肠阱,它表示沿著一個軸旋轉固定角度,即上述表示法3

3.static float Dot(Quaternion a, Quaternion b)? ?計算兩個四元數(shù)之間的點積朴读,返回一個標量屹徘,這個函數(shù)一般用不到

4.static Quaternion Euler(float x, float y, float z)? 構建一個四元數(shù),用歐拉角度表示

5.static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection)??構建一個四元數(shù)衅金,它表示從指向fromDirection方向到指向toDirection方向的相對旋轉量噪伊,見上述表示法4

6.static Quaternion Inverse(Quaternion rotation)??構建一個四元數(shù),它是指定的四元數(shù)的逆氮唯,也就是逆向旋轉鉴吹,比如原四元數(shù)表示相對+X軸旋轉了90度,那么此函數(shù)結果就是相對+X軸旋轉了-90度

7.static Quaternion Lerp(Quaternion a, Quaternion b, float t)? ? 構建一個四元數(shù)惩琉,表示從四元數(shù)a到b的球面插值豆励,所謂的插值也就是中間旋轉量,從a作為起點瞒渠,此時對應t為0肆糕,到b為終點,此時對應t為1在孝。當t取0-1之間的小數(shù)時,就代表了中間的插值結果淮摔。這個方法與Slerp相同私沮,計算速度快,但是精度低和橙,如果相對旋轉變化量很小仔燕,則效果不理想

8.static Quaternion LerpUnclamped(Quaternion a, Quaternion b, float t)??與Lerp相同,區(qū)別是魔招,Lerp的t值會被鉗制在[0,1]之間晰搀,而此方法則不會,t允許超出計算

9.static Quaternion LookRotation(Vector3 forward, Vector3 upwards = Vector3.up)??構建一個四元數(shù)办斑,使用前方上方矢量確定朝向外恕,也就是上述表示法2

10.static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)??構建一個四元數(shù),表示從一個四元數(shù)from(的前方)向著另外一個四元數(shù)(的前方)旋轉乡翅,但不能超出指定的角度鳞疲,也就是如果兩個前方矢量夾角超過指定角度,則旋轉到達指定角度時就停止蠕蚜,若是夾角本身不足的話尚洽,則結果直接為目標四元數(shù)to,與上述表示法4的意思很接近

11.static Quaternion Slerp(Quaternion a, Quaternion b, float t)??球面插值靶累,與Lerp功能相同腺毫,t值也被鉗制癣疟,計算精度高,但是速度相對較慢

12.static Quaternion SlerpUnclamped(Quaternion a, Quaternion b, float t)??與Slerp功能相同潮酒,只是t值不被鉗制睛挚,允許超出計算

13.static Quaternion operator * (Quaternion lhs, Quaternion rhs)??乘法運算符重載,當表示兩個連續(xù)的旋轉時澈灼,可以使用lhs * rhs的形式得出連續(xù)旋轉的結果,lhs為左值竞川,rhs為右值。注意左值是先進行的旋轉叁熔,疊加右值旋轉委乌。用法示例:lhs = lhs * rhs;

14.static Vector3 operator *(Quaternion rotation, Vector3 point)??乘法運算符重載,表示對一個矢量point施加旋轉rotation荣回,得出旋轉后的結果矢量遭贸。用法示例:Vector3 result=rotation * point

對于一些方法的詳細描述可以參考

Unity中的四元數(shù)類詳解【詳解】 - qq_36684665的博客 - CSDN博客

Unity3D入門篇——Quaternion類 - u014086857的專欄 - CSDN博客

Unity中四元數(shù)的使用

Unity 如何使用四元數(shù)_百度經驗

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市心软,隨后出現(xiàn)的幾起案子壕吹,更是在濱河造成了極大的恐慌,老刑警劉巖删铃,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耳贬,死亡現(xiàn)場離奇詭異,居然都是意外死亡猎唁,警方通過查閱死者的電腦和手機咒劲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诫隅,“玉大人腐魂,你說我怎么就攤上這事≈鹞常” “怎么了蛔屹?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長豁生。 經常有香客問我兔毒,道長,這世上最難降的妖魔是什么甸箱? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任眼刃,我火速辦了婚禮,結果婚禮上摇肌,老公的妹妹穿的比我還像新娘擂红。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布昵骤。 她就那樣靜靜地躺著树碱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪变秦。 梳的紋絲不亂的頭發(fā)上成榜,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音蹦玫,去河邊找鬼赎婚。 笑死,一個胖子當著我的面吹牛樱溉,可吹牛的內容都是我干的挣输。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼福贞,長吁一口氣:“原來是場噩夢啊……” “哼撩嚼!你這毒婦竟也來了?” 一聲冷哼從身側響起挖帘,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤完丽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拇舀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逻族,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年骄崩,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓷耙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡刁赖,死狀恐怖,靈堂內的尸體忽然破棺而出长搀,到底是詐尸還是另有隱情宇弛,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布源请,位于F島的核電站枪芒,受9級特大地震影響,放射性物質發(fā)生泄漏谁尸。R本人自食惡果不足惜舅踪,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望良蛮。 院中可真熱鬧抽碌,春花似錦、人聲如沸决瞳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痴颊,卻和暖如春赏迟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蠢棱。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工锌杀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泻仙。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓糕再,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饰豺。 傳聞我的和親對象是個殘疾皇子亿鲜,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容