四元數(shù)系列:
四元數(shù)-基本概念
四元數(shù)-旋轉(zhuǎn)
四元數(shù)應(yīng)用-轉(zhuǎn)矩陣Slerp插值與萬向節(jié)
四元數(shù)應(yīng)用-旋轉(zhuǎn)混合順序無關(guān)
—————————————————————————————————————————
今天,我們來談?wù)勔恍╆P(guān)于四元數(shù)的例子。與前兩篇文章相比,它們可能有點(diǎn)分散,這是對前兩章的補(bǔ)充說明。具體來說,我們將討論三個問題。第一個是四元數(shù)和矩陣的轉(zhuǎn)換,第二個是四元數(shù)的插入值。最后,我們來談?wù)勅f向節(jié)鎖的問題。話不多說,開始談話。
1.四元數(shù)矩陣形式目前,大多數(shù)底層的圖形API,空間坐標(biāo)的轉(zhuǎn)換仍然基于矩陣。因此,當(dāng)我們使用四元數(shù)來操作旋轉(zhuǎn)時,最終傳輸給頂點(diǎn)著色器的數(shù)據(jù)應(yīng)以矩陣的形式進(jìn)行。然而,從應(yīng)用層的角度來看,我們可以通過滿足以下公式來實(shí)現(xiàn)轉(zhuǎn)換。
我相信大多數(shù)人對背誦公式并不滿意。推導(dǎo)公式的主要方法有兩種。其中一個是從代數(shù)的角度解決問題。直率地說,這是一個硬算。我們在四元數(shù)和旋轉(zhuǎn)(2)中提到了一個公式:
我們可以找到三個矩陣,然后添加上述轉(zhuǎn)換公式。這里沒有推導(dǎo),感興趣的人可以自己計(jì)算。以下是一種更靈性的證明方法。當(dāng)給出以下兩個四元數(shù)時:
如下圖所示:
可以說,兩個四元數(shù)相乘轉(zhuǎn)換為矩陣L右乘四元數(shù)q。發(fā)散思維,把這種行為寫成矩陣R左乘四元數(shù)q,具體形式如下圖所示:
最體看L和R括號中的四元下標(biāo)非常重要,因?yàn)樗脑环辖粨Q規(guī)律,括號中的下標(biāo)實(shí)際上是不同的我們必須注意這個地方?;A(chǔ)知識完成后,直接應(yīng)用于下面。根據(jù)旋轉(zhuǎn)公式和上述定義,我們很容易得到以下公式:
然后將L和R在上述矩陣中,我們可以得到:
證畢!
2.四元數(shù)的Slerp插值事實(shí)上,插值問題一直是圖形學(xué)中的一個經(jīng)典問題。一般來說,線性插值可以滿足大多數(shù)情況,但對于旋轉(zhuǎn),線性插值肯定不好。讓我們下圖:
很明顯,左圖(線插)比右圖(球插)差。從動畫的角度來看,為了保證每幀的旋轉(zhuǎn)均勻變化,線性插值得到的旋轉(zhuǎn)結(jié)果必須不均勻,主要考慮旋轉(zhuǎn)角度。然后我們從代數(shù)的角度來思考。如果兩個單位的四元數(shù)之間的插值,如左圖的線性插值,則得到的四元數(shù)不得為單位的四元數(shù)。我們希望旋轉(zhuǎn)插值不會改變長度,因此顯然右圖的球面(Slerp)插值更合理。
四元數(shù)球面插值證明很多,Wiki上面有非常詳細(xì)的證據(jù)和實(shí)現(xiàn)Code。事實(shí)上,主要思想是施密特正交。首先,根據(jù) 和 解算兩個正 交四元,然后通過加權(quán)計(jì)算最終 。下圖可以很好地解釋這件事。
下面主要討論的是這個問題。上圖給出了一種球面插值公式,暫時稱為加法形式。由于四元旋轉(zhuǎn)是相乘的,我們的上述公式也可以寫成:
鑒于刨根問底的精神,先說四元數(shù)的差異。(Difference),這更容易理解,類似于矩陣,A與B的差異可以理解為先旋轉(zhuǎn)A,然后旋轉(zhuǎn)B,得到A和B兩者之間的差值,表示為 。然后,如果我們?nèi)倍差或直接說差乘以t因子,我們將引用四元數(shù)和旋轉(zhuǎn)(1)中提到的四元數(shù)指數(shù)形式。對于 ,我們來看看 和 具體情況如下:
最后我們令 以及 ,根據(jù)以下公式重新審視球面插值:
可見,兩種表現(xiàn)形式可以相互轉(zhuǎn)化。
三、萬向節(jié)死鎖事實(shí)上,這個問題不能算作四元的應(yīng)用。在萬向節(jié)鎖的早期階段,它被用來處理旋轉(zhuǎn)過程中機(jī)械臂缺乏自由度的問題。由于當(dāng)時機(jī)械臂的關(guān)節(jié)是單自由的,在模擬人體的一些球形關(guān)節(jié)(自由度為3的關(guān)節(jié))時,將使用三組正交機(jī)械關(guān)節(jié)進(jìn)行模擬。
如圖所示,當(dāng)關(guān)節(jié)2旋轉(zhuǎn)90時,機(jī)械關(guān)節(jié)1-3共同模擬手腕活動°之后關(guān)節(jié)1和關(guān)節(jié)3會重疊,所以旋轉(zhuǎn)關(guān)節(jié)1和旋轉(zhuǎn)關(guān)節(jié)3只會沿著 旋轉(zhuǎn)軸,這就是萬向節(jié)鎖。值得一提的是,當(dāng)你旋轉(zhuǎn)關(guān)節(jié)1、關(guān)節(jié)2和關(guān)節(jié)3時,當(dāng)你旋轉(zhuǎn)關(guān)節(jié)3時,無論如何旋轉(zhuǎn)都不會影響關(guān)節(jié)2和關(guān)節(jié)1,所以只有關(guān)節(jié)2旋轉(zhuǎn)90°萬向節(jié)鎖會產(chǎn)生。
當(dāng)早期的計(jì)算機(jī)動畫移動機(jī)器人時,最簡單的方法是直接模擬歐拉角的旋轉(zhuǎn)。這導(dǎo)致了通用鎖。那么如何理解計(jì)算機(jī)動畫中的這個問題呢?畢竟,動畫中沒有機(jī)械關(guān)節(jié)。
假設(shè)三個歐拉角的旋轉(zhuǎn)順序如下
當(dāng) 的時候, 和 它將重疊,如右圖,從而產(chǎn)生萬向節(jié)鎖。
因此,為了避免這個問題,圖形旋轉(zhuǎn)開始使用軸角,因?yàn)檩S角可以說三個歐拉角等同于繞特定軸旋轉(zhuǎn)的角度。OpenGL有個函數(shù)glRotate實(shí)現(xiàn)函數(shù)的方法是使用軸角。當(dāng)然,并不是說軸角沒有萬向鎖。當(dāng)三個正交軸角按一定順序旋轉(zhuǎn)時,仍然會產(chǎn)生萬向鎖,但這種情況很難發(fā)生。
所以軸角解決了這個問題,為什么要用四元數(shù)?
4.總結(jié)四元數(shù)最后點(diǎn)一個問題,呼應(yīng)前面的文章,具體說說四元數(shù)的好處:
解決萬向節(jié)鎖(Gimbal Lock)問題。(不要用四元數(shù)模擬歐拉角?。┲恍璐鎯?個浮點(diǎn),比矩陣輕。例如,矩陣至少需要9個float表示旋轉(zhuǎn)信息,即使加上旋轉(zhuǎn)縮放,也會比矩陣少存2-6個float,對于在PC游戲的開發(fā)可能并不明顯,畢竟,現(xiàn)在內(nèi)存很大,但在家用機(jī)器(尤其是上一代)中,內(nèi)存相對較緊是相當(dāng)有利的。無論是求逆、串聯(lián)等操作,四元數(shù)都比矩陣更高效。例如,逆轉(zhuǎn)相當(dāng)于逆轉(zhuǎn)。即使是正交矩陣,轉(zhuǎn)移的操作成本也遠(yuǎn)高于逆轉(zhuǎn)。此外,在大多數(shù)情況下,由于縮放,逆轉(zhuǎn)操作將更加復(fù)雜。然而,使用四元數(shù)需要考慮轉(zhuǎn)換四元數(shù)和矩陣的成本,但綜合考慮,四元數(shù)的運(yùn)行成本相對較低。基本上四元數(shù)在我這里就結(jié)束了,以后會有人請人 @Obsver Anonym 請期待更新一篇具體應(yīng)用的文章!