4.2Android Matrix的使用
[TOC]
Matrix
特点:实际变换和执行顺序相反
Android实际执行的变换和调用Matrix相反
Matrix.setIdentityM(modelMatrix2, 0);
Matrix.translateM(modelMatrix2, 0, 0.5f, 1.0f, -1.5f);
Matrix.rotateM(modelMatrix2, 0, angle, 0.0f, 1.0f, 0.0f);
Matrix.scaleM(modelMatrix2, 0, 1.5f, 1.5f, 1.5f);
在顶点坐标上先左乘缩放矩阵,再左乘旋转矩阵,然后再左乘平移矩阵,跟代码调用的顺序正好相反。
以scaleM和translateM进行推导
float[] matrix = new float[]{
1f, 5f, 9f, 13f,
2f, 6f, 10f, 14f,
3f, 7f, 11f, 15f,
4f, 8f, 12f, 16f,
};
float[] result = new float[16];
scaleM
Matrix.scaleM(result,0, matrix, 0,2,1, 1 );
Matrix.scaleM(matrix,0,2,1, 1);
结果:
2f, 10f, 18f, 26f,
2f, 6f, 10f, 14f,
3f, 7f, 11f, 15f,
4f, 8f, 12f, 16f,
为什么第一行都乘以2了???
记住!OpenGL的Matrix都是列主序列
我们之前推导的缩放矩阵

假设原矩阵

和scale矩阵相乘,

可以看到列向量分别乘以了scale的factor,但是别忘了是列主顺序,所以对应的结果是第一行乘以了2.
为什么不能右乘?因为矩阵乘法不满足交换律。
假设之前有变换矩阵M0,那么直接作用在原顶点坐标P(x,y,z,w),则有M0*P
此时我们调用scaleM方法,
Matrix.scaleM(M0,0,sx,sy,sz);
得到的M1矩阵,那么M1 = M0*S
作用于顶点向量 M1 * P = M0 * S * P = M0 * (S * P)
此时相当于先执行 scale再执行之前的变换。
translateM
平移
public static void translateM (float[] m,
int mOffset,
float x,
float y,
float z)
public static void translateM (float[] tm,
int tmOffset,
float[] m,
int mOffset,
float x,
float y,
float z)
//等价
Matrix.translateM(result,0, matrix, 0,1,1, 1 );
Matrix.translateM(matrix,0,1,1, 1 );
/**结果是
1f, 5f, 9f, 13f,
2f, 6f, 10f, 14f,
3f, 7f, 11f, 15f,
10f, 26f, 42f, 58f,
*/


可以看到作用在最后列向量上,对应于列主序列的最后一行。
Android Matrix的操作
https://www.learnopengles.com/understanding-opengls-matrices/
类似于glm,Android在Java层提供了对矩阵的操作。Matrix是一个工具类,操作OpenGL ES的float类型的矩阵、向量。
矩阵和向量是column-major的格式。
m[offset + 0] m[offset + 4] m[offset + 8] m[offset + 12]
m[offset + 1] m[offset + 5] m[offset + 9] m[offset + 13]
m[offset + 2] m[offset + 6] m[offset + 10] m[offset + 14]
m[offset + 3] m[offset + 7] m[offset + 11] m[offset + 15]
v[offset + 0]
v[offset + 1]
v[offset + 2]
v[offset + 3]
模型矩阵
rotateM
public static void rotateM (float[] m,
int mOffset,
float a,
float x,
float y,
float z)
public static void rotateM (float[] rm,
int rmOffset,
float[] m,
int mOffset,
float a,
float x,
float y,
float z)
和 setRotateM区别是作用于之前的上一个矩阵。
public static void rotateM(float[] rm, int rmOffset,
float[] m, int mOffset,
float a, float x, float y, float z) {
synchronized(sTemp) {
setRotateM(sTemp, 0, a, x, y, z);
multiplyMM(rm, rmOffset, m, mOffset, sTemp, 0);
}
}
scaleM
public static void scaleM (float[] m,
int mOffset,
float x,
float y,
float z)
public static void scaleM (float[] sm,
int smOffset,
float[] m,
int mOffset,
float x,
float y,
float z)
setRotateEulerM
public static void setRotateEulerM (float[] rm,
int rmOffset,
float x,
float y,
float z)
欧拉角转成旋转矩阵。
setRotateM
public static void setRotateM (float[] rm,
int rmOffset,
float a,
float x,
float y,
float z)
创建一个矩阵,围绕锚点 x,y,z 旋转 a 角度
translateM
平移
观察矩阵
setLookAtM
public static void setLookAtM (float[] rm,
int rmOffset,
float eyeX,
float eyeY,
float eyeZ,
float centerX,
float centerY,
float centerZ,
float upX,
float upY,
float upZ)
//TODO
创建一个viewing transformation
an eye point, a center of view, and an up vector.
投影矩阵
frustumM
public static void frustumM (float[] m,
int offset,
float left,
float right,
float bottom,
float top,
float near,
float far)
Defines a projection matrix in terms of six clip planes.
//TODO
orthoM
public static void orthoM (float[] m,
int mOffset,
float left,
float right,
float bottom,
float top,
float near,
float far)
//TODO
Computes an orthographic projection matrix.
perspectiveM
public static void perspectiveM (float[] m,
int offset,
float fovy,
float aspect,
float zNear,
float zFar)
//TODO
Defines a projection matrix in terms of a field of view angle, an aspect ratio, and z clip planes.
其他矩阵操作
invertM
public static boolean invertM (float[] mInv,
int mInvOffset,
float[] m,
int mOffset)
求逆矩阵
length
public static float length (float x,
float y,
float z)
求向量长度,针对(0,0,0)为原点
multiplyMM
public static void multiplyMM (float[] result,
int resultOffset,
float[] lhs,
int lhsOffset,
float[] rhs,
int rhsOffset)
4*4矩阵相乘
//TODO
multiplyMV
4 * 4矩阵和4 * 1向量相乘
setIdentityM
public static void setIdentityM (float[] sm,
int smOffset)
将sm变为单位矩阵,注意数组越界
public static void setIdentityM(float[] sm, int smOffset) {
for (int i=0 ; i<16 ; i++) {
sm[smOffset + i] = 0;
}
for(int i = 0; i < 16; i += 5) {
sm[smOffset + i] = 1.0f;
}
}
transposeM
转置矩阵
public static void transposeM (float[] mTrans,
int mTransOffset,
float[] m,
int mOffset)