opengl的MVP矩阵变换

假如有一个三角形,它的三个顶点是在虚拟空间中的,如果需要对这个三角形进行旋转,缩放,平移的操作,需要用到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)但是如果要使得物体围绕着某一个点旋转,那该怎么办呢?答案是矩阵的复合操作。

扫描二维码关注公众号,回复: 18763 查看本文章

比如一个物体有一个顶点(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);//产生透视投影矩阵

在透视投影之后,顶点如何变化,我会在下一篇文章中做讲解。

猜你喜欢

转载自my.oschina.net/u/1273706/blog/828690