从sources的android.opengl.Matrix.translateM(float[] m, int mOffset, float x, float y, float z)
开始:
/**
* Translates matrix m by x, y, and z in place.
* @param m matrix
* @param mOffset index into m where the matrix starts
* @param x translation factor x
* @param y translation factor y
* @param z translation factor z
*/
public static void translateM(
float[] m, int mOffset,
float x, float y, float z) {
for (int i=0 ; i<4 ; i++) {
int mi = mOffset + i;
m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
}
}
问题是关于此行(或整个for循环):
m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
为什么将转换参数的x,y和z分量与此处的源矩阵分量相乘?这不应该很简单(此行替换了整个for周期):
m[12 + mi] += x;
m[13 + mi] += y;
m[14 + mi] += z;
问题的背景:
我正在OpenGL ES 2.0中进行一些2D游戏。我想要缩放并在其中移动一些对象。当我简单地移动它时:
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, x, y, 0);
一切正常。我在移动之前先进行缩放-此时移动翻译:
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.scaleM(mModelMatrix, 0, xScaleFactor, yScaleFactor, 1);
Matrix.translateM(mModelMatrix, 0, x, y, 0);
实际上乘以缩放比例:(
OpenGL是主要列,缩放,旋转和平移的正确顺序实际上是Translation * Rotation * Scaling
。在D3D和任何行主要矩阵库中,Scale * Rotate * Translate
是正确的。使用列大矩阵时,您必须从右到左考虑问题。
或者,您可以在乘法之前转置每个矩阵-不过,通常遵循列大矩阵乘法的规范顺序通常更简单。请注意,这也适用于Position * Model * View * Projection
(D3D /行优先),在GL(列主)中,正确的顺序是Projection * View * Model * Position
。
translateM
模拟m
X T
的矩阵乘法,其中T
是转换矩阵。
翻译矩阵就像恒等矩阵(对角1),最后一列是x,y,z,1。 (1适用于同类坐标,我将不讨论。)
假设您知道矩阵乘法(第一个操作数的每一行被第二个操作数的每一列成对地加成对,则它利用了转换矩阵的细节并且“就地”执行较少的工作。
它实际上并没有创建转换矩阵T,而是模拟了m X T
的含义,仅计算了可以更改的值(最后一列)。它是“就地”的,因此,如果m
的值不变,则可以将其保留在其中(还有translateM
的版本可写入另一个矩阵)。每个循环迭代将m
的每一行乘以ttanslation矩阵的最后一列(whcn为x,y,z,1
)。代码行应为(其中[[i为m
的行,为T
的列):
m[12+i] = m[0+i]*x + m[4+i]*y + m[8+i]*z + m[12+i]*1f;
但是他们使用位于+=
运算符对其进行了简化;使用mi
作为偏移量;并省略0+
。请记住,它使用
column-major形式的矩阵,这意味着当您逐步遍历数组时,向下移一列,然后再移至下一列,依此类推。因此,从零开始的行i] >,矩阵
m
的列[[j
m[i + 4*j]
。也就是说,向下(到达下一行)为+ 1,向下(到达下一列)为+ 4。 thr next(另一种方法是row-major,您可以在其中一行,向下一行到下一行,等等。对于打印更直观,但对于android.opemgl.Matrix
则不行。)BTW:这里有几层:矩阵乘法,排序的效果,齐次坐标,平移矩阵,乘法排序的效果,列主形式,上述乘法捷径,+=
和mOffset,
mi `(对于一个数组中的许多矩阵)。许多编程工作可能会陷入混乱,但是为此,可能有必要依次进入每个层的顶部,否则复杂性太令人困惑。我感到困惑,因此,如果这里有任何错误,请指出来!