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文档中的矩阵。