在开发Android OpenGL
应用时,发现Matrix
似乎不是按照代码中出现的次序应用的,而是反过来的。
比如说,我想构造这样一个Matrix
,先旋转一个角度,再平移宽高的一半,最后缩放以归一化。那么应当先出现缩放的代码,在出现平移的代码,最后进行旋转:
float[] vMatrix = new float[16];
Matrix.setIdentityM(vMatrix , 0);
Matrix.scaleM(vMatrix, 0, 2.0f / H, 2.0f / W, 1);
Matrix.translateM(vMatrix, 0, -H / 2, -W / 2, 0);
Matrix.rotateM(vMatrix, 0, ang, 0, 0, 1);
与直觉有很大不同。
查看rotateM
实现:
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);
}
}
public static native void multiplyMM(float[] result, int resultOffset,
float[] lhs, int lhsOffset,
float[] rhs, int rhsOffset);
查看multiplyMM
的注释:
Multiplies two 4x4 matrices together and stores the result in a third 4x4
matrix. In matrix notation:result = lhs x rhs
. Due to the way
matrix multiplication works, theresult
matrix will have the same
effect as first multiplying by therhs
matrix, then multiplying by
thelhs
matrix. This is the opposite of what you might expect.
将两个4x4的矩阵相乘,结果存储在第三个4x4的矩阵中。用矩阵符号描述就是:
result = lhs x rhs
。由于矩阵乘法的特性,结果矩阵的效果等同于先乘以rhs
矩阵,然后乘以lhs
矩阵。这与你可能的预期相反。
旋转操作中,sTemp
对应形参rhs
,它放在右边,先起作用。
实际上,这是由于新出现的矩阵是放在当前矩阵的右侧进行相乘所导致的。