四元數-Quaternion

<p>
回顧一下四元數中的屬性和方法。
</p>

屬性:

public Vector3 eulerAngles
功能說明 此屬性用來返回或設置Quaternion實例對應的歐拉角
進行賦值的方式通常有兩種:

public Transform A, B;
Quaternion rotations=Quaternion.identity;
Vector3 eulerAngle = Vector3.zero;

第一種是將Quaternion實例賦值給transform的rotation 
rotations.eulerAngles = new Vector3(0.0f, speed * Time.time, 0.0f);
A.rotation = rotations;

第二種是將三維向量代表的歐拉角直接賦值給transform的eulerAngles
eulerAngle = new Vector3(0.0f, speed * Time.time, 0.0f);
B.eulerAngles = eulerAngle;

Quaternion類實例方法:

在Quaternion類中涉及的實例方法有SetFromToRotation方法、SetLookRotation方法和ToAngleAxis方法

SetFromToRotation方法

public void SetFromToRotation(Vector3 fromDirection, Vector3 toDirection);
用于創建一個從fromDirection到toDirection的rotation,同樣也不能夠直接對Transform.rotation直接進行操作,先對四元數進行旋轉,然后將四元數賦值給rotation,例如:

//不可直接使用transform.rotation.SetFromToRotation(v1,v2)方式進行設置
//只能將實例化的Quaternion賦值給transform.rotation。
Quaternion q1 = Quaternion.identity;
q1.SetFromToRotation(v1,v2);
transform.rotation = q1;

首先會把該物體的xyz軸方向和世界坐標的xyz一致(即rotation在世界坐標系中為0,如果是父對象有旋轉的話也不影響),然后旋轉的rotation為:V1指向的方向旋轉到V2指向的方向:

image.png

A為v1,B為V2,如果B向上移動一定距離,那么C也會朝上旋轉;

SetLookRotation方法

基本語法
(1) public void SetLookRotation(Vector3 view);
(2) public void SetLookRotation(Vector3 view, Vector3 up);
用來對一個Quaternion實例的朝向進行設置。例如:

Quaternion q1 = Quaternion.identity;
q1.SetLookRotation(v1); //1.
q1.SetLookRotation(v1, v2); //2.
transform.rotation = q1;

q1.SetLookRotation(v1):transform.right垂直于由Vector3.zero、v1、v1.up構成的平面,transform.forward為v1向量,下圖中A為v1:

image.png

q1.SetLookRotation(v1, v2):
transform.right垂直于由Vector3.zero、v1和v2這3點構成的平面。
v2除了與Vector3.zero和v1構成平面來決定transform.right的方向外,還用來決定transform.up的朝向,因為當transform.forward和transform.right方向確定后, transform.up方向剩下兩種可能,到底選用哪一種便由v2來影響。transform.up方向的選取方式總會使得transform.up的方向和v2方向的夾角小于或等于90度。

image.png

當v1為Vector3.zero時,方法失效,即不要在使用此方法時把v1設置成Vector3.zero。
<pre>
提示
不可以直接使用transform.rotation.SetLookRotation(v1, v2)的方式來使用SetLookRotation方法,否則會不起
作用。應該使用上述代碼所示的方式,首先實例化一個Quaternion,然后對其使用SetLookRotation,最后將其賦給transform.rotation。
</pre>

ToAngleAxis方法

基本語法
public void ToAngleAxis(out float angle, out Vector3 axis);
其中參數angle為旋轉角,參數axis為軸向量。
功能說明 此方法用于將Quaternion實例轉換為角軸表示。
在transform.rotation.ToAngle Axis(out angle, out axis)中,輸出值angle和axis的含義為:要將GameObject對象的rotation從Quaternion.Identity狀態變換到當前狀態,只需要將GameObject對象繞著axis的軸向(指世界坐標系中)旋轉angle角度即可。通常和靜態方法AngleAxis (angle : float, axis : Vector3)聯合使用,使得一個物體的rotation始終和另一個物體的rotation保持一致,例如:

void Update()
    {
        //使用ToAngleAxis獲取A的Rotation的旋轉軸和角度
        A.rotation.ToAngleAxis(out angle, out axis);
        //使用AngleAxis設置B的rotation,使得B的rotation狀態的和A相同
        //當然也可以只使得B與A的axis相同,而angle不同
        //可以在程序運行時修改A的rotation查看B的狀態
        B.rotation = Quaternion.AngleAxis(angle, axis);
    }

運行效果如下,B會隨著A的旋轉保持和A一致:

image.png

Quaternion類靜態方法

在Quaternion類中主要的靜態方法有Angle方法、Dot方法、Euler方法、FromToRotation方法、Inverse方法、Lerp方法、LookRotation方法、RotateTowards方法和Slerp方法:

Angle方法:Quaternion實例間夾角

基本語法 public static float Angle(Quaternion a, Quaternion b);
功能說明 此方法用于返回從參數a到參數b變換的夾角。需要注意的是,返回的夾角不是某個局部坐標軸向變換的夾角,而是GameObject對象從狀態a轉換到狀態b時需要旋轉的最小夾角。

Dot方法:點乘

基本語法 public static float Dot(Quaternion a, Quaternion b);
a●b=|a||b|cos夾角 可以判斷a在b的前方和后方.

Euler方法:歐拉角對應的四元數

基本語法
(1) public static Quaternion Euler(Vector3 euler);
(2) public static Quaternion Euler(float x, float y, float z);
功能說明 此方法用于返回歐拉角Vector3(x,y,z)對應的四元數Quaternion實例。

FromToRotation方法:Quaternion變換

基本語法
public static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);
功能說明 此方法用來創建一個從參數fromDirection到toDirection的Quaternion變換。其功能和實例方法SetFromToRotation (fromDirection : Vector3, toDirection : Vector3)相同:
測試代碼如下:

 void Update()
    {
        //使用實例方法
        //不可直接使用C.rotation.SetFromToRotation(A.position,B.position);
        q1.SetFromToRotation(A.position, B.position);
        C.rotation = q1;
        //使用類方法
        D.rotation = Quaternion.FromToRotation(A.position, B.position);
        //在Scene視圖中繪制直線
        Debug.DrawLine(Vector3.zero, A.position, Color.white);
        Debug.DrawLine(Vector3.zero, B.position, Color.white);
        Debug.DrawLine(C.position, C.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(C.position, C.TransformPoint(Vector3.up * 1.5f), Color.white);
        Debug.DrawLine(D.position, D.position + new Vector3(0.0f, 1.0f, 0.0f),
        Color.white);
        Debug.DrawLine(D.position, D.TransformPoint(Vector3.up * 1.5f), Color.white);
    }
AB夾角.png

C和D的旋轉角度:

旋轉角度.png
Inverse方法:逆向Quaternion值

基本語法
public static Quaternion Inverse(Quaternion rotation);

功能說明 此方法用于返回參數rotation的逆向Quaternion值。例如,設有實例rotation=(x,y,z,w),則Inverse(rotation)=(-x,-y,-z,w)。從效果上說,設rotation.eulerAngles=(a,b,c),則transform.rotation=Inverse(rotation)相當于transform依次繞自身坐標系的z軸、x軸和y軸分別旋轉-c度、-a度和-b度。由于是局部坐標系內的變換,最后transform的歐拉角的各個分量值并不一定等于-a、-b或-c。
示例:
代碼如下:

 public Transform A, B;
    void Start()
    {
        Quaternion q1 = Quaternion.identity;
        Quaternion q2 = Quaternion.identity;
        q1.eulerAngles = new Vector3(0, -90, 0);
        q2 = Quaternion.Inverse(q1);
        A.rotation = q1;
        B.rotation = q2;
    }

運行后的結果如下(Cube藍色為正面):

結果.png
Lerp方法:線性插值

基本語法
public static Quaternion Lerp(Quaternion from, Quaternion to, float t);
功能說明 此方法用于返回從參數from到to的線性插值。當參數t≤0時返回值為from,當參數t≥1時返回值為to。此方法執行速度比Slerp方法快,一般情況下可代替Slerp方法。

示例:
代碼如下:


public Transform A, B, C, D;
float speed = 0.2f;
void Update()
{
C.rotation = Quaternion.Slerp(A.rotation, B.rotation, Time.time * speed);
D.rotation = Quaternion.Lerp(A.rotation, B.rotation, Time.time * speed);

運行時會發現,C和D會漸漸由A的rotation旋轉到B的rotation:

運行結果.png
LookRotation方法:設置Quaternion的朝向(和類實例方法SetLookRotation 類似,可以往上查看實例方法)

基本語法
(1) public static Quaternion LookRotation(Vector3 forward);
(2) public static Quaternion LookRotation(Vector3 forward, Vector3 upwards);

其中參數forward為返回Quaternion的forward朝向。
功能說明 此方法用于返回一個Quaternion實例,使GameObject對象的z軸朝向參數forward方向(使GameObject的forward為參數的向量)。此方法與方法SetLookRotation (view : Vector3, up : Vector3 = Vector3.up)功能相同。

RotateTowards方法:Quaternion插值

基本語法
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
其中參數from為起始Quaternion,參數to為結束Quaternion,參數maxDegreesDelta為每幀最大角度值。

功能說明 此方法用于返回從參數from到to的插值,且返回值的最大角度不超過maxDegreesDelta。此方法功能與方法Slerp相似,只是maxDegreesDelta指的是角度值,不是插值系數。當maxDegreesDelta<0時,將沿著從to到from的方向插值計算。

Quaternion類運算符

在Quaternion類中涉及的運算符運算有兩個Quaternion實例相乘的運算、一個Quaternion實例和一個Vector3相乘的運算。

兩個Quaternion實例相乘的運算

功能說明 此運算符用于返回兩個Quaternion實例相乘后的結果。設A和B均為GameObject對象的一個實例,有如下代碼:
B.rotation *= A.rotation;

代碼每執行一次,B都會繞著B的局部坐標系的z、x、y軸分別旋轉A.eulerAngles.z度、A.eulerAngles.x度和A.eulerAngles.y度,注意它們的旋轉次序一定是先饒z軸再繞x軸最后繞y軸進行相應的旋轉。另外由于是繞著局部坐標系旋轉,故而當繞著其中一個軸旋轉時,很可能會影響其余兩個坐標軸方向的歐拉角(除非其余兩軸的歐拉角都為0才不受影響)。

一個Quaternion實例和一個Vector3相乘的運算

功能說明 此運算符的作用是對參數坐標點point進行rotation變換。例如,設A為Vector3實例,有如下代碼:

transform.position += transform.rotation *A;
則每執行一次代碼,transform對應的對象便會沿著自身坐標系中向量A的方向移動A的模長的距離。transform.rotation與A相乘主要來確定移動的方向和距離。

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

推薦閱讀更多精彩內容