cover_photo

等泡麵學四元數

四元數介紹與使用說明書

在這篇文章中你會學到

四元數是什麼 將你想要的旋轉轉換成四元數 怎麼使用四元數對一個點/向量進行旋轉

前言

這篇文章是一篇國外文章的粗略翻譯加上一些不專業註解,希望大家在等待泡麵的同時可以快速學會使用這個工具,克服這個多數人心中的數學惡夢

How to Rotate a vertex by a quaternion in glsl

為什麼我們需要四元數?

一句話解釋四元數

一個四元數可以被視為繞任意軸的旋轉

原文

A quaternion can be seen as a object that holds a rotation around any axis

影片互動示意解說

那為什麼這個工具這麼神,讓你願意犧牲等泡麵追劇的時間來學習呢? 因為平常如果我們不使用四元數,還要進行物體的旋轉,我們會需要使用矩陣來進行旋轉(以下附上公式),而使用矩陣你除了需要記憶下面這些sin跟cos的位置以外,你還需要關心你使用矩陣的順序,也就是說你先對x軸在對y軸的旋轉不一定會等於先進行y軸在對x軸的旋轉,使用起來其實有一定程度的不方便,再加上各個3D引擎使用的旋轉順序不盡相同

四元數介紹 (1).webp

這時候拯救你睡眠時間跟追劇時間的救星出現了,不要看四元數外表醜陋,其實他內心很可愛,好東西怎麼可以不拿來用呢?

以下開始介紹我們今天的主角"四元數"

四元數本人

  1. 長相

四元數是由實數與虛數兩個部分組成的複數(complex numbers) s 代表實數部分 v代表虛數部分

q = [s,v]
q = [s + xi + yj + zk]

在3D軟體編程中我們通常使用以下格式,而其中的 w=s[x,y,z]=v

q = [x, y, z, w]
  1. 那我們要怎麼使用四元數對一個向量/點進行旋轉呢?

其實也很簡單你只需要下面這個公式就可以了

p1 = q P0 q^-1

p1 : 旋轉過的點/向量 p0 : 選轉前的點/向量 q : 四元數 q^-1 : 四元數的倒數

等等先不要走,我知道這個還不夠簡單,光是要能夠執行上面的公式你還需要知道四件事:

怎麼將繞任意軸旋轉變成四元數 怎麼將點/向量變成四元數 怎麼取得四元數的倒數 怎麼對兩個四元數相乘 p.s-1 以下出現的四元數都是預設使用單位四元數,也就是正規化(大小為一)的四元數

p.s-2 以下解說過程只關心實現過程,不關心原理以及證明過程

step1 將繞任意軸旋轉變成四元數

在這個步驟你需要兩個資訊

選轉軸是誰 選轉幾度

//known info : angle and axis
half_angle = angle/2
q.x = axis.x * sin(half_angle)
q.y = axis.y * sin(half_angle)
q.z = axis.z * sin(half_angle)
q.w = cos(half_angle);

step2 將點/向量轉換成四元數

q.x = position.x
q.y = position.y
q.z = position.z
q.w = 0

step3 取得四元數的倒數

q = [x, y, z, w]
norm = |q| = sqrt(q.x^2 + q.y^2 + q.z^2 + q.w^2)
q^-1 = [-x, -y, -z, w]/ norm
q^-1 = [-x/norm, -y/norm, -z/norm, w/norm]

but !!如果我們的四元數是單位四元數那就可以直接變成

q^-1 = q* = [-x, -y, -z, w]

step4 四元數相乘

首先 四元數是可以相乘的

q = q1 * q2

但 四元數並不滿足交換率也就是說

q1 * q2 != q2 * q1

他們乘起來的結果就是 :

q.x = (q1.w * q2.x) + (q1.x * q2.w) + (q1.y * q2.z) - (q1.z * q2.y)
q.y = (q1.w * q2.y) - (q1.x * q2.z) + (q1.y * q2.w) + (q1.z * q2.x)
q.z = (q1.w * q2.z) + (q1.x * q2.y) - (q1.y * q2.x) + (q1.z * q2.w)
q.w = (q1.w * q2.w) - (q1.x * q2.x) - (q1.y * q2.y) - (q1.z * q2.z)

其實你並不需要真的把上面的結果記起來,大部分的使用情境下都有現成的函式庫或者模組可以幫你做完運算,你只需要知道你這次旋轉要圍繞哪個軸,並且旋轉多少度,在按照上面的步驟依序運算就可以得到你要的答案了

p.s. 會長這麼醜是因為四元數的定義

i^2 = j^2 = k^2 = -1
ij = -ji = k
jk = -kj = i
ki = -ik = j

放上一張紀念圖 四元數介紹.gif

現在~泡麵應該好了,趕快回去吃吧~ 四元數介紹 (2).webp