void gluLookAt (
GLdouble eyeX,
GLdouble eyeY,
GLdouble eyeZ,
GLdouble centerX,
GLdouble centerY,
GLdouble centerZ,
Gldouble upX,
GLdouble upY,
GLdouble upZ
);
这个函数可以生成 view 矩阵,作用相当于更换了基底。
opengl 默认基底 原点在视口中心,x 轴向右,y 向上,z 向屏幕外,相机处于原点,向 z 轴负半轴看去。
如果想要换一个角度看世界,就需要坐标变换。把基底变换到新的位置,让 z 轴的负半轴指向相机所看的方向。
声明一下,矩阵以列的方式看,顶点,向量都看成列矩阵(只有一列的矩阵)。
基底,可以看成是矩阵的列向量。比如基底分别为 \(vx,vy,vz\) 坐标为 \(v_0(x_0,y_0,z_0)\) 的点可以表示为:
理解为 用坐标分量对基底进行线性组合。
设 \(I\) 为单位矩阵 则默认基底下坐标对应的值就是 \(Iv\) 。
现在如果想要换一套坐标,变成用矩阵 \(M\) 的列向量作为基底,并且还要使得最终计算出的点是向量空间中的同一个点则:
把右边 \({M^{ - 1}}v\) 看成整体,它意味着,若要换 \(M\) 为基底,所有坐标都要左乘 \({M^{-1}}\)
gluLookAt 对基底做了两个变换。它先旋转了基底,使其 z 负半轴指向 center - eye ,然后位移到 eye 。
这相当于新的基底为 :
理解为,将 \(I\) 按列(即基底)切开,每列做了 \(TR\) 变换后再合起来。
所以坐标变换需要的矩阵就是 \((TR)^{-1}\) 即 \(R^{-1}T^{-1}\)
先通过规范化与叉乘,得到旋转后的基底。注意 :
所以第三行添上负号。这就是 opengl 文档中的 \(M\)。
而 \(T\) 是位移矩阵,所以 \(T^{-1}\) 就是反方向位移。
这就是 opengl 文档中的 glTranslated(-eyex, -eyey, -eyez) 。
合起来就是 \(R^{-1}T^{-1}\) 。
(ps: opengl 文档 s = f x up' 缺少规范化)