假如有一个三角形,它的三个顶点是在虚拟空间中的,如果需要对这个三角形进行旋转,缩放,平移的操作,需要用到model矩阵操作,model矩阵只对当前的这个三角形操作,不会影响其他物体。在对一个物体进行矩阵操作之前,需要将这个矩阵做单位化操作。
(1)矩阵的平移
private final float[] modelMatrix = new float[16]; //获得一个model矩阵
Matrix.setIdentityM(modelMatrix, 0); //利用android自带的Matrix单位化矩阵
Matrix.translateM(modelMatrix, 0, 0, -1.2f, 0); //将物体向Y轴移动-1.2个单位
(2)矩阵的旋转:当使用model矩阵旋转物体时,可以绕着X,Y,Z轴旋转,
Matrix.rotateM(modelMatrix, 0, rotateAngle, 1f, 0f, 0f);//绕着X轴旋转rotateAngle
Matrix.rotateM(modelMatrix, 0, rotateAngle, 0, 1f, 0f);//绕着Y轴旋转rotateAngle
Matrix.rotateM(modelMatrix, 0, rotateAngle, 0f, 0f, 1f);//绕着Z轴旋转rotateAngle
(2.1)但是如果要使得物体围绕着某一个点旋转,那该怎么办呢?答案是矩阵的复合操作。
比如一个物体有一个顶点(1.1f, -1.2f, 0),我想要这个物体围绕这个顶点旋转。
1.将物体移动到原点的位置,也就是虚拟空间的原点。Matrix.translateM(modelMatrix, 0, -1.1f, 1.2f, 0);
2.旋转该物体。Matrix.rotateM(modelMatrix, 0, rotateAngle, 1f, 0f, 0f);
3.将物体移动到(1.1f, -1.2f, 0)。Matrix.translateM(modelMatrix, 0, 1.1f, -1.2f, 0);
思路基本上这么个思路,但是这里有一个很容易掉进去的陷阱,矩阵操作的顺序。如果按照刚才的1,2,3的步骤,得不到想要的结果。因为这个和矩阵相乘有关系,放在最前面的矩阵最后被乘,最后面的矩阵最先被乘。这个数学关系有兴趣的朋友可以参考《[游戏编程数学和物理基础].(斯达乐)》这本书的6.4章节,那里讲的比较精彩。所以正确的代码顺序应该是:
Matrix.translateM(modelMatrix, 0, 1.1f, -1.2f, 0);
Matrix.rotateM(modelMatrix, 0, rotateAngle, 1f, 0f, 0f);
Matrix.translateM(modelMatrix, 0, -1.1f, 1.2f, 0);
这样就使得一个物体围绕着(1.1f, -1.2f, 0)这个点,在x=1.1f这个X轴上旋转。
(3)接着来说说缩放,缩放是相对于虚拟空间的原点的。
Matrix.scaleM(modelMatrix, 0, 30f, 30f, 1);
上面的代码让物体沿着X轴和Y轴放大了30倍,但是并不是沿着物体自己的中心点缩放的。
(3.1)让物体以一个指定的点作为缩放的中心点。这个其实也是矩阵的复合操作,步骤跟旋转的复合操作比较类似,可以参考上面的讲解。
视图矩阵:将虚拟空间中的所有的物体都做缩放,旋转,移动的操作。视图矩阵和model矩阵的不同点在于model矩阵作用于一个物体上,视图矩阵作用于空间中所有的物体上。
private float[] viewMatrix = new float[16];
Matrix.setLookAtM(viewMatrix, 0,
0f, 0f, 1f, //眼睛的位置
0f, 0f, -1f, //眼睛看的方向
0f, 1f, 0f //视线的法线
); //获得一个视图矩阵
Matrix.translateM(viewMatrix, 0, 0, 0, -2); //将空间中所有的物体向Z轴方向平移-2个单位。
最后,我来讲讲透视矩阵。在2D的屏幕上面显示3D的图形效果,靠的就是这么个矩阵。使用了投影矩阵以后会产生一个视锥体,通俗点说就是远处的东西看到的更多一些,但是比较小;近处的东西看到的少一些,但是比较大。透视投影的一个最重要的任务就是计算出W的值,用这个值为后一步的透视除法做准备。
float fov = 120;// 基于Y轴的视野
float aspect = ((float) width / (float) height);//屏幕的宽高比
float near = 0.1f; //近平面
float far = 200f; //远平面
Matrix.perspectiveM(projectionMatrix, 0, fov, aspect, near, far);//产生透视投影矩阵
在透视投影之后,顶点如何变化,我会在下一篇文章中做讲解。