Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么android.opengl.Matrix.translateM()会产生意外的结果?_Java_Android_Matrix_Opengl Es 2.0_Matrix Transform - Fatal编程技术网

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

Java 为什么android.opengl.Matrix.translateM()会产生意外的结果?,java,android,matrix,opengl-es-2.0,matrix-transform,Java,Android,Matrix,Opengl Es 2.0,Matrix Transform,从android.opengl.Matrix.translateM(float[]m,int mOffset,float x,float y,float z)的 为什么平移参数的x、y和z分量在此处与源矩阵分量相乘?这不是很简单吗(这一行代替了整个for循环): 问题背景: 我正在用OpenGLES2.0做一些2d游戏。我不想在那里缩放和移动一些物体。我只是简单地移动它: Matrix.setIdentityM(mModelMatrix, 0); Matrix.translateM(mMode

从android.opengl.Matrix.translateM(float[]m,int mOffset,float x,float y,float z)的

为什么平移参数的x、y和z分量在此处与源矩阵分量相乘?这不是很简单吗(这一行代替了整个for循环):


问题背景

我正在用OpenGLES2.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
都是正确的。使用列主矩阵时,必须从右到左考虑问题

或者,您可以在乘法之前转置每个矩阵-但通常只遵循列主矩阵乘法的规范顺序更简单。请注意,这也适用于GL(列主矩阵)中的
Position*Model*View*Projection
(D3D/行主矩阵)等正确的顺序是
投影*视图*模型*位置
translateM
模拟
m
X
T
,其中
T
是一个转换矩阵

平移矩阵类似于单位矩阵(对角线1),最后一列为x,y,z,1表示平移。(1表示同质坐标,我将不讨论)

假设您知道矩阵乘法(其中第一个操作数的每一行由第二个操作数的每一列按对进行互乘),则利用转换矩阵的细节可以走捷径。
T

m[12+i] = m[0+i]*x + m[4+i]*y + m[8+i]*z + m[12+i]*1f;
它实际上并不创建转换矩阵
t
,而是模拟乘法
mxt
。大多数值不会改变(因为这部分像一个单位矩阵),所以它只需要计算确实改变的值(包括
t
的最后一列)

每一次循环迭代都是将一行
m
乘以转换矩阵的最后一列(即
x,y,z,1
)。代码行是(i是
m
的行,而
T
的列):

但是他们使用
+=
操作符简化它;使用
mi
作为偏移量;省略
0+

不改变的元素可以留在那里,因为这个版本的
translateM
已经“就位”

请记住,它使用主列形式的矩阵,带有索引:

0  4  8  12
1  5  9  13
2  6  10 14
3  7  11 15
在遍历数组时,向下遍历一列中的每个元素,并在其末尾遍历下一列,以此类推。因此,第i行和第j列中的元素位于
m[i+4*j]
。也就是说,向下遍历为+1,向下遍历为+4。thr next(另一种方式是行主键,在这里您可以穿过一行,向下到下一行等。打印时更直观,但不是
android.opengl.Matrix
使用的。)


你的
scaleM
然后
translateM
相当于
sxt
(缩放矩阵
S
,平移矩阵
T
)。效果是从右到左(即向后),首先是平移,然后是缩放。因此,平移也会被缩放

正如公认的答案所说,做
translateM
然后
scaleM
(即
T x S
)具有缩放然后翻译的效果(因此翻译不会缩放)

考虑这一点的一种方法是,这个矩阵最终将乘以一个列向量
v
(txs)xv
。从不同的角度开始,用
sxv=v'
缩放
v
,然后用
txv'
转换结果,我们可以将它们组合为
tx(sxv)
。缩放必须放在第一位似乎很自然。也许令人惊讶的是,因为矩阵乘法是关联的,它与
(txs)xv
相同。如果忽略最后一个
xv
(在GPU上完成),我们就得到了
txs
,意思是“缩放,然后转换”.首先完成最靠近右侧的矩阵

顺便说一句,矩阵乘法的关联性就像java字符串串接,求值顺序无关紧要,其中
(a+b)+c=a+(b+c)
(虽然操作数的顺序很重要,例如
a+b+c!=c+b+a
)。这意味着我们可以先选择适合我们的部分


顺便说一句:这里有几个层次:矩阵乘法、排序效果、齐次坐标、平移矩阵、乘法排序效果、列主形式、上面的乘法捷径、
+=
mOffset、
mi`(对于一个数组中的多个矩阵)


很多编程都可以理解,但对于这一点,最好是依次进入每一层的顶部。

我不确定,这个问题应该在这里问还是在后面问?
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.scaleM(mModelMatrix, 0, xScaleFactor, yScaleFactor, 1);
Matrix.translateM(mModelMatrix, 0, x, y, 0);
m[12+i] = m[0+i]*x + m[4+i]*y + m[8+i]*z + m[12+i]*1f;
0  4  8  12
1  5  9  13
2  6  10 14
3  7  11 15