四元數可以表示三度空間的旋轉狀態,那你知道複數也可以表示二度空間的旋轉狀態嗎?
用四元數表示三度空間的旋轉狀態有很多好處。
其中一個最棒的點在於他不像用角度來內插,它並不會出現從359度轉到0度時,變成在繞遠路的狀況。
四元數內插走的永遠是兩個狀態間「最近」的旋轉。
因為太贊了,所以遊戲引擎通常都是用四元數來表示旋轉的。
於是我就在想,既然三度空間的旋轉有這麼方便的東西可以用,那二度空間呢?
結果…就找到了這個神奇的東西。
懶人包就是「複數可以表示二度空間的旋轉狀態」
說實在,我看過這東西後,覺得這根本就是自找麻煩。
因為二度空間的旋轉也就兩個方向,大不了用個判斷一下角度就知道該轉哪邊了。
就算退個一百步,用內建好的四元數也行啊,因為二維旋轉畢竟也是三維旋轉的一種。
但我覺得是一個很有趣的想法,而且它的原理跟四元數有異曲同工之妙,感覺了解它就有助於瞭解四元數。
這個方法的原理,是用複數平面上的單位向量來表示二度空間的旋轉狀態。
複數平面上,單位圓上的值都可以用這個形式表示:
$$z = e^{i\theta}$$
我的理解是,假如用在圓上0度的地方點一個紅點,那麼旋轉後這個點就會落在單位圓上的某處。
而且任一旋轉狀態下都恰好對應到該點在圓上一個可能的位置。
我猜這應該就是這個方法的出發點。
實作的方法,是先把角度轉代進上式,得到單位複數。
起始角度和終止角度各會給我們一個單位複數。
在兩個複數間做內插,再把內插值歸一化,就得到另一個單位複數。
這個方法相當於在起點跟終點所連成的圓弧間做內插,所以走的當然會是近的路。(應該吧)
不過要注意,直接用線性內插的話,旋轉速度非等速。(這點跟四元數內插非常類似!)
因此如果想要得到等速旋轉的話,還必須乘上一個權重才行。
至於權重怎麼算我就懶得看了,反正…誰會用這個鬼方法做2D旋轉啊。
等到我哪天去看四元數時再想辦法一起搞懂吧。
不過看完這篇後,我心裡還浮出了另一個疑問:
「為什麼用角度就可能會繞遠路,但用複數就可以?」
角度跟複數有甚麼本質上的區別,導致它們有這個差異?
於是我便開始了漫長的思考。
解釋1
角度的定義是從x軸開始逆時鐘旋轉的夾角。
可以比喻成「兩個旋轉狀態的差」。
打個比方,0度跟359度內插,其實變成是「逆時鐘轉0度」跟「逆時鐘轉359度」作內插。
因此才會出現看似繞遠路的行為。
而複數不一樣,它本身就是「旋轉狀態」。
因此它的內插就會是狀態的內插,會得到最近的結果。
解釋2
另一個解釋跟複數平面上的log的branch cut有關。
我們雖然可以用複數代表旋轉狀態,但最後如果要還原成角度,我們就得取log。
以剛才的式子來說:
$$z = e^{i\theta}$$
則
$$\theta = -i * log(z)$$
可是注意,這裡是沒辦法完全還原$\theta$的,因為複數平面的log並沒有辦法對應到所有可能的角度。
由於單位圓上的一個點有無數個角度對應到它 (一個角度加360度仍會對到同一點)
因此我們在取log時必須規定角度的範圍,例如-180~180度。
於是這邊就出現了一個尷尬的斷點。
這兩個解釋其實意思差不多:「角度是旋轉狀態的失真表示法」
嘛,或許真的是這樣也說不定。看來複數才是真正適合表示2D旋轉的載體?
不過就算這樣,下次做2D遊戲時處理旋轉時,我想我還是會選擇用角度加if判斷來實作吧…