为了更强大的功能和灵活性,我们有时需要直接操作矩阵。在OpenGL中4x4的矩阵用包含16个浮点数值的一维数组来表示,而不是用二维的4x4的数组来表示。OpenGL之所以这么做,因为使用一维数组更高效。当然OpenGL也支持二维数组的表示方式。而且要特别注意的是在矩阵中是使用列主序遍历数组的,即按列逐个遍历数组中的元素。

事实上,这个矩阵里的16个值代表着空间中的一个特定的位置和三个轴的朝向(相对于视点坐标系)。前3列是方向向量分别代表着3个轴的朝向(绝大多数情况下,这3个向量是正交的),第四列用于平移变换、glTranslate函数就是把数值填到这一列中。这个4x4的矩阵相当于一个坐标系统的位置和方向,如果把一个顶点(用列向量的形式)与这个矩阵相乘,得到的结果是一个变换到该坐标系统的新顶点。这意味着空间中的任意一个点和方向,能够用唯一的4x4的矩阵表示。如果你把物体中的所有顶点都乘以这个矩阵,那么你就是把整个物体变换到空间中指定的位置和朝向(我的理解是可以用这个矩阵所代表的坐标系统来表示你的整个物体)。

PS:注意最后一行的元素除了最后一个为1之外,其余为0。
?
你可以使用下面的两个函数来加载你的列主序的矩阵到投影矩阵,模型视图矩阵或者纹理矩阵栈中。
glLoadMatrixf(GLfloat* m);
glLoadMatrixd(GLdouble* m);
绝大多数的OpenGL的实现是使用单精度的浮点数来计算管道中的数据的。使用双精度的形式会带来一定的性能开销。
下面的代码相当于调用glLoadIdentity函数。
// 加载单位矩阵
GLfloat m[] = { 1.0f, 0.0f, 0.0f, 0.0f,? ? ? // X 列
0.0f, 1.0f, 0.0f, 0.0f,? ? ? // Y 列
0.0f, 0.0f, 1.0f, 0.0f,? ? ? // Z 列
0.0f, 0.0f, 0.0f, 1.0f };? ? // 平移列
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(m);
相对应的OpenGL还提供了加载行主序的矩阵的两个函数
void glLoadTransposeMatrixf(GLfloat *m);
void glLoadTransposeMatrixd(GLdouble *m);
?
一个高级的例子:
transformationMatrix[12] = 0.0f;
transformationMatrix[13] = 0.0f;
transformationMatrix[14] = -2.5f;
这三个是执行平移变换.相当于glTranslatef(0.0f, 0.0f, –2.5f); m3dRotationMatrix44函数如下
最终的效果如下:

手动执行变换在碰撞检测,平截头体剔除,以及一些特效算法中会用到。
?
在场景中移动的物体成为角色,就像舞台剧上的演员一样。角色有他们自己的变换,不仅仅是相对于世界坐标系(视点坐标系)的变换,也可以相对于其他角色坐标系的变换。每个角色都有自己的参考帧和自己的坐标系(物体坐标系)。在物体坐标系和世界坐标系之间的转换是非常有用的。
?
一个简单灵活的表示角色的方式是用一个包含一个空间中的位置,一个指向前面的向量以及一个指向上面的向量(第三个向量可以通过计算得到)。使用这些量就可以唯一地标识空间中一个特定的位置和方向。
?
使用这样的一个参考帧来表示一个物体的位置和方向是非常有用的。我们可以使用这些数据直接创建一个4x4的变换矩阵。其中向上的向量代表y列向量,向前的向量代表z列向量,位置则代表移动列向量。这样只缺少了x向量。因为我们知道这3个轴是互相垂直的,因此可以有由y和z向量的叉乘来计算x列向量。
?
参考《3D数学基础_图形与游戏开发》
?
欧拉角的基本思想是讲角位移分解为三个互相垂直轴的三个旋转组成的序列。
以下都是使用左手法则。“heading-pitch-bank” heading为绕y轴的旋转量,绕惯性坐标系y轴的旋转。向右旋转为正。pitch为绕x轴的旋转量。物体坐标系的x轴,不是原惯性坐标系的x轴。向下旋转为正方向。bank为绕z轴的旋转量。物体坐标系的z轴。逆时针为正方向。
PS:当我们说的旋转顺序是"heading-pitch-bank”时,是指从惯性坐标系到物体坐标系。如果从物体坐标系变换到惯性坐标系,旋转的顺序就是相反的
?
?
![Image[1] Image[1]](../../upload/2015_02/150225141272414.png)
?
?
?
?
基本问题
?
解决方法:讲heading和bank限制在+180到-180之间,pitch限制在+90到-90之间。这种现象,角度为+-90的第二次旋转将使得第一次和第三次旋转的旋转轴相同,称作万向锁。为了消除限制欧拉角的这种别名现象,规定万向锁情况下由heading完成绕竖直轴的全部旋转。

?
?

?
OpenGL中并不真正存在照相机变换。相机作为一个隐喻,帮助我们理解如何管理3D环境中的视点。照相机可以想象为一种物体,在空间中具有某个位置和特定方向。
应用照相机变换,我们要使用照相机的角色变换并进行反转。这样当我们把相机向后移时就相当于向前移动整个场景。向左旋转相机则相当于向右旋转整个场景。
glu库中包含了一个函数用于创建相机变换,它使用的数据与上面定义的帧结构数据相同。
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz);
这个函数接受一个观察点的位置,一个在观察点正前方的一个点,以及向上的方向向量。
渲染一个指定的场景如下图:
