【Unity】Unity 欧拉角、四元数、万向节死锁、四元数转轴角
文章目錄
- 歐拉角(Euler)
- 萬(wàn)向節(jié)
- 歐拉角旋轉(zhuǎn)特性
- 歐拉角優(yōu)點(diǎn)
- 歐拉角缺點(diǎn)
- 方位的表達(dá)方式不唯一
- 萬(wàn)向節(jié)鎖(Gimbal Lock)
- 四元數(shù)(Quaternion)
- 四元數(shù)轉(zhuǎn)軸角
- 四元數(shù)優(yōu)點(diǎn)
- 四元數(shù)缺點(diǎn)
- Quaternion類(lèi)
歐拉角(Euler)
什么是歐拉角?百科上是這樣解釋的:用來(lái)確定定點(diǎn)轉(zhuǎn)動(dòng)剛體位置的3個(gè)一組獨(dú)立角參量,由章動(dòng)角θ、旋進(jìn)角(即進(jìn)動(dòng)角)ψ和自轉(zhuǎn)角φ組成,為歐拉首先提出而得名。
很難理解吧?其實(shí)我們沒(méi)有必要把歐拉角想得太復(fù)雜。
對(duì)于開(kāi)發(fā)者來(lái)說(shuō),歐拉角就是用一個(gè)Vector3變量來(lái)記錄物體沿著x、y、z軸的旋轉(zhuǎn)。注意,雖然這是一個(gè)Vector3變量,但它并不是向量,這個(gè)變量的x、y、z三個(gè)分量是用來(lái)描述旋轉(zhuǎn)的。
歐拉角特點(diǎn):
- 使用3個(gè)角度來(lái)保存方位。
- x 與 z沿自身坐標(biāo)旋轉(zhuǎn),y 沿世界坐標(biāo)旋轉(zhuǎn)。
- API:Vector3 eulerAngle = this.transform.eulerAngles;
萬(wàn)向節(jié)
萬(wàn)向節(jié),也叫平衡環(huán)架(Gimbal),具有樞紐的裝置,使得一物體能以單一軸旋轉(zhuǎn)。由彼此垂直的樞紐軸所組成的一組三只平衡環(huán)架,則可使架在最內(nèi)的環(huán)架的物體維持旋轉(zhuǎn)軸不變。常常應(yīng)用于船上的陀螺儀、羅盤(pán)、飲料杯架等。
在飛行器的航行中,進(jìn)行XYZ三個(gè)方向旋轉(zhuǎn)的旋轉(zhuǎn)有專(zhuān)業(yè)的術(shù)語(yǔ),見(jiàn)下圖:
沿著機(jī)身右方軸(Unity中的+X)進(jìn)行旋轉(zhuǎn),稱(chēng)為pitch,中文叫俯仰。
沿著機(jī)頭上方軸(Unity中的+Y)進(jìn)行旋轉(zhuǎn),稱(chēng)為Yaw,中文叫偏航。
沿著機(jī)頭前方軸(Unity中的+Z)進(jìn)行旋轉(zhuǎn),稱(chēng)為Roll,中文叫桶滾。
歐拉角旋轉(zhuǎn)特性
歐拉角的旋轉(zhuǎn)就是沿著萬(wàn)向節(jié)的軸旋轉(zhuǎn)的。目前人類(lèi)最常用也最容易理解的方式是先沿著X軸旋轉(zhuǎn),再沿著Y軸旋轉(zhuǎn),最后沿著Z軸旋轉(zhuǎn),最后達(dá)到目標(biāo)旋轉(zhuǎn)角度。如下圖所示:
這時(shí)候可能就有人會(huì)有疑問(wèn)了,為什么不能三個(gè)軸同時(shí)旋轉(zhuǎn)呢?
實(shí)際上,如果三個(gè)軸同時(shí)旋轉(zhuǎn),將會(huì)無(wú)法達(dá)到你預(yù)期的旋轉(zhuǎn)效果。為什么呢?因?yàn)槲矬w是一個(gè)整體,當(dāng)某一個(gè)軸進(jìn)行旋轉(zhuǎn)時(shí),其他的軸是跟著物體一起動(dòng)的,如果還是按照原來(lái)的旋轉(zhuǎn)角度旋轉(zhuǎn)則會(huì)隨著其他軸的轉(zhuǎn)動(dòng)形成偏移,如下圖所示:
我們想要的其實(shí)只是讓箭頭指向我們,但三個(gè)軸同時(shí)旋轉(zhuǎn)卻使這個(gè)旋轉(zhuǎn)軌跡劃出了一個(gè)不應(yīng)該有的弧線。
所以我們要了解的是,歐拉旋轉(zhuǎn)是一定要有順序的。這樣的問(wèn)題其實(shí)是無(wú)法避免的,但是我們可以根據(jù)物體的旋轉(zhuǎn)情況對(duì)此進(jìn)行優(yōu)化,這個(gè)優(yōu)化的方法就是給三個(gè)軸指定一個(gè)新的層級(jí)順序。
當(dāng)然這并不是真正的解決了問(wèn)題,只是盡量避免了問(wèn)題而已。歐拉角的問(wèn)題是無(wú)法徹底解決的,
歐拉角優(yōu)點(diǎn)
- 僅使用三個(gè)數(shù)字表達(dá)方位,占用空間小。
- 沿坐標(biāo)軸旋轉(zhuǎn)的單位為角度,符合人類(lèi)思考方式。
- 任意三個(gè)數(shù)字都是合法的,不存在不合法的歐拉角。
歐拉角缺點(diǎn)
方位的表達(dá)方式不唯一
對(duì)于一個(gè)方位,存在多個(gè)歐拉角描述,因此無(wú)法判斷多個(gè)歐拉角代表的唯一是否相同。
例如:
- 角度 0, 5, 0 與角度 0, 365, 0
- 角度 0, -5, 0 與角度 0, 355, 0
- 角度 250, 0, 0 與角度 290, 180, 180
為了保證任意方位都只有獨(dú)一無(wú)二的表示,Unity引擎限制了角度范圍,即沿x軸旋轉(zhuǎn)限制在 -90 ~ 90 之間,沿 y 與 z 軸旋轉(zhuǎn)限制在 0 ~ 360 之間。
萬(wàn)向節(jié)鎖(Gimbal Lock)
當(dāng)物體沿 x 軸旋轉(zhuǎn) ±90°\ \plusmn 90°?±90° ,自身坐標(biāo)系z(mì)軸與世界坐標(biāo)系y軸將重合,此時(shí)再沿y軸或z軸旋轉(zhuǎn)時(shí),將會(huì)失去一個(gè)自由度。
Unity的優(yōu)化方案:在萬(wàn)向節(jié)死鎖的情況下,規(guī)定沿z軸完成繞豎直軸的全部旋轉(zhuǎn),即此時(shí)y軸旋轉(zhuǎn)為0。
關(guān)于萬(wàn)向節(jié)鎖的講解視頻:https://v.youku.com/v_show/id_XNjk1MTkzMTM2.html#paction
在使用歐拉旋轉(zhuǎn)的情況下,萬(wàn)向節(jié)鎖的情況是無(wú)法避免的,為了更好的表示旋轉(zhuǎn),Unity引入了四元數(shù)的概念。
四元數(shù)(Quaternion)
四元數(shù)在3D圖形學(xué)中代表旋轉(zhuǎn),由一個(gè)三維向量 /[x,y,z]/ [x, y, z]/[x,y,z] 和一個(gè)標(biāo)量 /w/ w/w 組成。
旋轉(zhuǎn)軸為 VVV ,旋轉(zhuǎn)弧度為 θ\thetaθ ,若使用四元數(shù)表示,則四個(gè)分量為:
x=Sin(θ/2)?V.xy=Sin(θ/2)?V.yz=Sin(θ/2)?V.zw=Cos(θ/2)x = Sin(\theta / 2) * V.x \\ y = Sin(\theta / 2) * V.y \\ z = Sin(\theta / 2) * V.z \\ w = Cos(\theta / 2)x=Sin(θ/2)?V.xy=Sin(θ/2)?V.yz=Sin(θ/2)?V.zw=Cos(θ/2)
四個(gè)分量的值都在 -1 到 1 之間。
幾何應(yīng)用:四元數(shù)與向量相乘,可以實(shí)現(xiàn)向量的旋轉(zhuǎn)。
代碼:
// 獲取四元數(shù) Quaternion qt = this.transform.rotation;// 使用四元數(shù)做旋轉(zhuǎn) this.transform.rotation = Quaternion.Euler(0, 50, 0);// 或者調(diào)用Rotation方法實(shí)現(xiàn)旋轉(zhuǎn) this.transform.Rotation(0, 50, 0);四元數(shù)旋轉(zhuǎn)角度相加需要用 * 乘法,而不是加法。
四元數(shù)轉(zhuǎn)軸角
Transform 中的 rotation 使用的是四元數(shù),有時(shí)我們需要獲取 Transform 沿某一個(gè)軸旋轉(zhuǎn)的角度,此時(shí)可以用下面的代碼進(jìn)行計(jì)算:
Quaternion q = transform.rotation;// 計(jì)算X軸旋轉(zhuǎn)角度 float angleX = 0; float siny_cosp1 = 2 * (q.w * q.x + q.z * q.y); float cosy_cosp1 = 1 - 2 * (q.y * q.y + q.x * q.x); float radian1 = Mathf.Atan2(siny_cosp1, cosy_cosp1); // 求出弧度 angleX = radian1 * Mathf.Rad2Deg; // 轉(zhuǎn)化角度 Debug.Log("=============" + angleX);// 計(jì)算Z軸旋轉(zhuǎn)角度 float angleZ = 0; float siny_cosp2 = 2 * (q.w * q.z + q.x * q.y); float cosy_cosp2 = 1 -2 * (q.y * q.y + q.z * q.z); float radian2 = Mathf.Atan2(siny_cosp2, cosy_cosp2); // 求出弧度 angleZ = radian2 * Mathf.Rad2Deg; // 轉(zhuǎn)化角度 Debug.Log("=============" + angleZ);上述方法適用于物體只在一個(gè)軸上做了旋轉(zhuǎn)的情況,Y軸的計(jì)算方法以此類(lèi)推。
四元數(shù)優(yōu)點(diǎn)
避免萬(wàn)向節(jié)死鎖,完全沿自身軸(而不是全局軸)旋轉(zhuǎn)。
四元數(shù)缺點(diǎn)
難于使用,且存在不合法的數(shù)值。
Quaternion類(lèi)
Unity中提供了Quaternion類(lèi)來(lái)處理四元數(shù)相關(guān)操作,該類(lèi)的使用方法可以參考我的另外一篇文章:【Unity】Unity常用類(lèi):向量Vector3、四元數(shù)Quaternion
本文萬(wàn)向節(jié)部分內(nèi)容參考了塞北煙云大神的文章,地址如下:https://www.jianshu.com/p/9f45e91a2391
更多內(nèi)容請(qǐng)查看總目錄【Unity】Unity學(xué)習(xí)筆記目錄整理
總結(jié)
以上是生活随笔為你收集整理的【Unity】Unity 欧拉角、四元数、万向节死锁、四元数转轴角的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 网络测试仪的用法
- 下一篇: 小学文化学导数——斜率