OpenGL 入门基础教程 —— 矩阵的变换

来源:互联网 发布:mac 3d动画制作软件 编辑:程序博客网 时间:2024/05/16 16:23

基础知识介绍:

1:齐次坐标(Homogeneous coordinates)

我们仍然把三维顶点视为三元组(x,y,z)。现在引入一个新的分量w,得到向量(x,y,z,w)。请先记住以下两点(稍后我们会给出解释):

——若w==1,则向量(x, y, z, 1)为空间中的点。
——若w==0,则向量(x, y, z, 0)为方向。


二者有什么区别呢?对于旋转,这点区别倒无所谓。当您旋转点和方向时,结果是一样的。但对于平移(将点沿着某个方向移动)情况就不同了。”平移一个方向”是毫无意义的。

齐次坐标使得我们可以用同一个公式对点和方向作运算。0为方向1为点


2:变换矩阵(Transformation matrices)

三维图形学中我们只用到4x4矩阵,它能对顶点(x,y,z,w)作变换。这一变换是用矩阵左乘顶点来实现的:

矩阵x顶点(记住顺序!!矩阵左乘顶点,顶点用列向量表示)= 变换后的顶点




这看上去复杂,实则不然。左手指着a,右手指着x,得到ax。 左手移向右边一个数b,右手移向下一个数y,得到by。依次类推,得到cz、dw。最后求和ax + by + cz + dw,就得到了新的x!每一行都这么算下去,就得到了新的(x, y, z, w)向量。


平移矩阵(Translation matrices)

平移矩阵是最简单的变换矩阵。平移矩阵是这样的:



其中,X、Y、Z是点的位移增量

例如,若想把向量(10, 10, 10, 1)沿X轴方向平移10个单位,可得:



(算算看!一定得亲手算!!)

这样就得到了齐次向量(20,10,10,1)!记住,末尾的1表示这是一个点,而不是方向。经过变换计算后,点仍然是点,这倒是挺合情合理的。

下面来看看,对一个代表Z轴负方向的向量作上述平移变换会得到什么结果:



还是原来的(0,0,-1,0)方向,这也很合理,恰好印证了前面的结论:”平移一个方向是毫无意义的”。

C++中的glm代码

#include <glm/gtx/transform.hpp> // after <glm/glm.hpp>glm::mat4 myMatrix = glm::translate(10.0f, 0.0f, 0.0f); // 平移变换矩阵,对角线上皆为1,只需要X,Y,Z三个分量即可glm::vec4 myVector(10.0f, 10.0f, 10.0f, 0.0f);          // 需平移向量glm::vec4 transformedVector = myMatrix * myVector;      // 结果


单位矩阵(Identity matrix)

单位矩阵很特殊,它什么也不做。单位矩阵的身份和自然数”1”一样基础而重要,因此在这里要特别提及一下。


C++表示单位矩阵:

glm::mat4 myIdentityMatrix = glm::mat4(1.0);


缩放矩阵(Scaling matrices)

缩放矩阵也很简单:


例如把一个向量(点或方向皆可)沿各方向放大2倍:



w还是没变。您也许会问:”缩放一个向量”有什么用?嗯,大多数情况下是没什么用,所以一般不会去缩放向量;但在某些特殊情况下它就派上用场了。(顺便说一下,单位矩阵只是缩放矩阵的一个特例,其(X, Y, Z) = (1, 1, 1)。单位矩阵同时也是旋转矩阵的一个特例,其(X, Y, Z)=(0, 0, 0))。


C++ 表示缩放矩阵:

glm::mat4 myScalingMatrix = glm::scale(2.0f, 2.0f ,2.0f);


旋转矩阵(Rotation matrices)

旋转矩阵(Rotation matrix)是在乘以一个向量的时候改变向量的方向但不改变大小的效果的矩阵

具体生成方法:http://blog.sina.com.cn/s/blog_a401a1ea0101eip1.html


用C++表示:

glm::vec3 myRotationAxis( ??, ??, ??);glm::rotate( angle_in_degrees, myRotationAxis );


累计变换:

前面已经学习了如何旋转、平移和缩放向量。把这些矩阵相乘就能将它们组合起来,例如:

TransformedVector = TranslationMatrix * RotationMatrix * ScaleMatrix * OriginalVector;

!!!注意!!!这行代码首先执行缩放,接着旋转,最后才是平移。这就是矩阵乘法的工作方式。

变换的顺序不同,得出的结果也不同。您不妨亲自尝试一下:

向前一步(小心别磕着爱机)然后左转;
左转,然后向前一步
实际上,上述顺序正是你在变换游戏角色或者其他物体时所需的:先缩放;再调整方向;最后平移。例如,假设有个船的模型(为简化,略去旋转):

错误做法:
按(10, 0, 0)平移船体。船体中心目前距离原点10个单位。
将船体放大2倍。以原点为参照,每个坐标都变成原来的2倍,就出问题了。最后您得到的是一艘放大的船,但其中心位于2*10=20。这并非您预期的结果。


正确做法:
将船体放大2倍,得到一艘中心位于原点的大船。
平移船体。船大小不变,移动距离也正确。


变换的顺序也是影响的关键,矩阵论学的好,这一点就不用担心了~