學習筆記3

Unity中的歐拉角和四元數

筆記主要參考以下的博文

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

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


Unity中的歐拉角

順規

在經典力學里,時常用zxz順規來設定歐拉角;照著第二個轉動軸的軸名,簡稱為x順規。另外,還有別種歐拉角組。合法的歐拉角組中,唯一的限制是,任何兩個連續的旋轉,必須繞著不同的轉動軸旋轉。因此,一共有12種順規。

Unity的歐拉角定義

Unity文檔中Transform.eulerAngles的定義,本身是一個Vector3,就是一個三維矢量, 分別含有xyz三個參數。

xyz代表了三個角度,它們定義了一組有序的旋轉,即圍繞z軸旋轉z度,然后圍繞x軸旋轉x度,然后圍繞y軸旋轉y度。你應該只去讀取或者直接設置這些數值,不要增加它們,因為當角度超過360度將會失敗。應該使用Transform.Rotate去替代執行旋轉操作。

在上述文檔中定義了在Unity中歐拉旋轉的順規,即先圍繞z軸旋轉,后繞x軸,最后繞y軸。

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

歐拉旋轉的軸

Unity中的Transform文檔有有這樣一個函數

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

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

Space.Self 局部坐標系,意味著本次歐拉旋轉以物體當前的局部坐標朝向為基礎出發執行旋轉。

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

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

比如我們可以指定一組歐拉旋轉(90,60,30),通過前述的順規我們知道,先繞Z軸旋轉30度,再繞X軸旋轉90度,再繞Y軸旋轉60度,雖然有這樣的順序,但是Z旋轉后相對X軸、Y軸,都是執行本組歐拉旋轉前的那個軸向,它沒有發生變動,所以我稱它為“當前軸”

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

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

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

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

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

總結

Unity中的歐拉旋轉是按照Z、X、Y順規執行的旋轉,一組歐拉旋轉過程中,相對的軸向不會發生變化。 Transform.Rotate(new Vector3(90,60,30)),它代表執行了一組歐拉旋轉,它相對的是旋轉前的局部坐標朝向。正是這種順規和軸向的定義,導致了萬向節死鎖的自然形成。

Unity中的四元數

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

那么在Unity里如何利用四元數進行旋轉呢?

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

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

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

一些常用的函數:

Quaternion.LookRotation? ?前方、上方標注矢量法創建四元數

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

Quaternion.Euler??歐拉角表示創建四元數

Quaternion.Slerp??球面插值

Quaternion.FromToRotation??A向到B向相對旋轉表示法創建四元數

Quaternion.identity? 為單位四元數,即默認的無旋轉狀態

Quaternion 是一個結構體,本身成員變量相對簡單,可以作為函數參數高效傳遞。

Unity的方向

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

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

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

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

確定方向的方法

1.歐拉角表示法

Unity中的歐拉旋轉方向為固定的zxy順規。

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

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

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

3.?繞軸旋轉界定法

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

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

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

利用幾種表示方法在Untiy中創建四元數

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 歐拉角,返回當前四元數所對應的歐拉角

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

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

identity 單位四元數,也就是默認的無旋轉狀態,此時與世界坐標相同,前方指向+Z,上方指向+Y

成員函數

靜態函數

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

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

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

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

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

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

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

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

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

10.static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)??構建一個四元數,表示從一個四元數from(的前方)向著另外一個四元數(的前方)旋轉,但不能超出指定的角度,也就是如果兩個前方矢量夾角超過指定角度,則旋轉到達指定角度時就停止,若是夾角本身不足的話,則結果直接為目標四元數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)??乘法運算符重載,當表示兩個連續的旋轉時,可以使用lhs * rhs的形式得出連續旋轉的結果,lhs為左值,rhs為右值。注意左值是先進行的旋轉,疊加右值旋轉。用法示例:lhs = lhs * rhs;

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

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

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

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

Unity中四元數的使用

Unity 如何使用四元數_百度經驗

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容