gluLookAt矩陣推導
最近需要自己手動算camera view矩陣,但是推導的結果跟OpenGL官方文件不一樣,又因為我的瀏覽器沒法完美看MathML,所以我一直以為OpenGL的官方文件http://www.opengl.org/sdk/docs/man/xhtml/gluLookAt.xml錯了,今天才發現原來最終結果是一樣的,困擾了我好久的一個問題終於解決了。
這裡我準備從基變換的角度來推導這個矩陣。首先考慮2D的簡單情況。現在的問題是,將空間從規範基(canonical basis)轉換到照相機的基。
規範基是{(1, 0)^T, (0, 1)^T}, 照相機的基是{u, v},對於任意一個向量(s, t)^T,它的座標在規範基下是(s, t)^T,也就是
(s, t)^T = s * (1, 0)^T + t * (0, 1)^T
如果可以將(0, 1)和(1, 0)用{u, v}表示,那麼我們也可以求得(s, t)^T在另一組基下的座標。
假設
(1, 0)^T = a * u + b * v
(0, 1)^T = c * u + d * v
那麼帶入上面的式子
(s, t)^T = s * (au + bv) + t * (cu + dv) = (as + ct) * u + (bs + dt) * v
座標是(as + ct, bs + dt)^T, 也可以寫成
(a c * (s
b d) t)
也就是說只要對原空間座標(s, t)做一個矩陣變換就可以得到新的座標。
我們將兩組基之間的轉換寫成矩陣的形式
(1 0 = (u v) (a c
0 1) b d)
那麼
(a c = (u v)^-1
b d)
令
M = (u v 0
0 0 1)^-1
那麼,從規範基轉換到任意一組基(u, v),只需要一個變換矩陣M(任意兩組基之間的轉換可以修改上述推導得到)。
由於照相機空間的原點也不在原來空間的原點,我們還需要做一個平移。假設照相機的位置在p, 那麼
M_view = M * translationMatrix(-p)
這樣我們先將將照相機放在原點,然後再進行基的轉換。
可以驗證,
M_view = (u v p
0 0 1)^-1
實際上,當{u, v}是一組正交基時,M是一個轉動(rotation) 矩陣,即可得到
(u v 0 = (u v 0
0 0 1)^-1 0 0 1)^T
這樣
M_view = (u v 0 * (I -p
0 0 1)^T 0 1)
這個推導可以拓展到三維空間中,因此
M_view = (u v w 0 * (I -p
0 0 0 1)^T 0 1)
也就是在gluLookAt文件中的矩陣。