为什么android.opengl.Matrix.translateM()产生意外结果?

问题描述 投票:0回答:2

sourcesandroid.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);

实际上乘以缩放比例:(

java android matrix opengl-es-2.0 matrix-transform
2个回答
3
投票

OpenGL是主要列,缩放,旋转和平移的正确顺序实际上是Translation * Rotation * Scaling。在D3D和任何行主要矩阵库中,Scale * Rotate * Translate是正确的。使用列大矩阵时,您必须从右到左考虑问题。

或者,您可以在乘法之前转置每个矩阵-不过,通常遵循列大矩阵乘法的规范顺序通常更简单。请注意,这也适用于Position * Model * View * Projection(D3D /行优先),在GL(列主)中,正确的顺序是Projection * View * Model * Position


0
投票

translateM 模拟mX 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 `(对于一个数组中的许多矩阵)。许多编程工作可能会陷入混乱,但是为此,可能有必要依次进入每个层的顶部,否则复杂性太令人困惑。我感到困惑,因此,如果这里有任何错误,请指出来!
© www.soinside.com 2019 - 2024. All rights reserved.