Android:Matrix - > preconcat和postconcat有什么不同?

znq*_*znq 45 android matrix

我正在使用Matrix来缩放和旋转位图.现在我想知道preconcat和postconcat之间有什么区别,或者更确切地说是以下两者之间的区别:

从我能想到的到目前为止,setRotate总是覆盖整个矩阵,而使用preRotate和postRotate我可以对矩阵应用多个更改(例如缩放+旋转).但是,使用postRotate或preRotate不会对我使用它们的情况造成任何不同的结果.

Che*_*ter 131

您的问题的答案并非真正针对Android; 这是一个图形和数学问题.在这个答案中有很多理论 - 你已经被警告了!如果您对问题的表面答案,请跳到底部.此外,因为这是一个冗长的长篇大论,我可能会有一两个错误的错误.如果是这样的话我会提前道歉.

在计算机图形学中,我们可以将像素(或3D,顶点)表示为矢量.如果您的屏幕是640x480,这里是屏幕中间点的2D矢量(原谅我的伪劣标记):

[320]
[240]
[  1]
Run Code Online (Sandbox Code Playgroud)

我将解释为什么1后来很重要.转换通常使用矩阵表示,因为将它们链接在一起非常简单(并且非常有效),就像您提到的那样.要将上面的点缩放1.5倍,可以乘以以下矩阵:

[1.5   0   0]
[  0 1.5   0]
[  0   0   1]
Run Code Online (Sandbox Code Playgroud)

你会得到这个新观点:

[480]
[360]
[  1]
Run Code Online (Sandbox Code Playgroud)

它代表原始点,相对于屏幕一角(0,0)缩放1.5.这很重要:始终根据原点进行缩放.如果您想要将其他点作为中心进行缩放(例如精灵的中间),则需要将缩放比例"换行"到原点的转换中.这是将原始点转换为原点的矩阵:

[1  0  -320]
[0  1  -240]
[0  0     1]
Run Code Online (Sandbox Code Playgroud)

产量:

[320*1 + 1*-320]   [0]
[240*1 + 1*-240] = [0]
[     1*1      ]   [1]
Run Code Online (Sandbox Code Playgroud)

您将识别上面的标识矩阵,其中位移坐标位于右上角.这就是为什么1("同质坐标")是必要的:为这些坐标腾出空间,从而可以使用乘法进行平移.否则它必须通过矩阵加法来表示,这对人类来说更直观,但会使图形卡比现在更加复杂.

现在,矩阵乘法通常不是可交换的,因此当"添加"变换时(通过乘以矩阵),您需要指定是左对乘还是右乘.它的不同之处在于你的变换的顺序是什么.通过右对乘你的矩阵(使用preRotate())你指出旋转步骤应该你刚才要求的所有其他变换之前发生.这可能是你想要的,但通常不是.

通常,这无关紧要.例如,如果你只有一个变换,它永远不会重要:)有时,你的变换可以以任何顺序发生,具有相同的效果,例如缩放和旋转 - 我的线性代数生锈,但我相信在这种情况下矩阵乘法实际上是可交换的,因为比例矩阵是对称的,也就是说,它在对角线上反射自身.但实际上,只要想一想:如果我将一些图片顺时针旋转10度然后将其缩放到200%,它看起来就像我先缩放它然后旋转它一样.

如果你正在进行一些奇怪的复合变换,你会发现一个差异.我的建议是坚持下去postRotate().

  • 喜欢简洁而深入的解释!+1。 (2认同)

chi*_*ong 6

我昨天回答了这个问题\xef\xbc\x8c,但今天我感觉有些不对,所以我在这里更正答案:

\n\n
matrix:  float[] values ={1.2f,0.5f,30,0.5f,1.2f,30,0,0,1};\n\n//as we all know, the basic value in matrix,means no transformation added\nmatrix2:  float[] values2 ={1f,0,0,0,1f,0,0,0,1};\n\nLet's say our matrix values are the values above.\n
Run Code Online (Sandbox Code Playgroud)\n\n

1\xe3\x80\x81 当我们进行如下转换时:

\n\n
matrix.preTranslate(-50, -50);\n\nis equals to do sequence transformation to matrix2 above like below:\n\nmatrix2.postTranslate(-50, -50);\nmatrix2.postSkew(0.5f/1.2f,0.5f/1.2f);// note here\nmatrix2.postScale(1.2f, 1.2f);\nmatrix2.postTranslate(30, 30);\n
Run Code Online (Sandbox Code Playgroud)\n\n

2\xe3\x80\x81 当我们进行如下转换时:

\n\n
matrix.preRotate(50);\n\nis equals to do sequence transformation to matrix2 like below:\n\nmatrix2.postRotate(50);\nmatrix2.postSkew(0.5f/1.2f,0.5f/1.2f);\nmatrix2.postScale(1.2f, 1.2f);\nmatrix2.postTranslate(30, 30);\n
Run Code Online (Sandbox Code Playgroud)\n\n

3\xe3\x80\x81 当我们进行如下转换时:

\n\n
matrix.preScale(1.3f,1.3f);\n\nis equals to do sequence transformation to matrix2 like below:\n\nmatrix2.postScale(1.3f,1.3f);\nmatrix2.postSkew(0.5f/1.2f,0.5f/1.2f);\nmatrix2.postScale(1.2f, 1.2f);\nmatrix2.postTranslate(30, 30);\n
Run Code Online (Sandbox Code Playgroud)\n\n

4\xe3\x80\x81 当我们进行如下转换时:

\n\n
 matrix.preSkew(0.4f,0.4f);\n
Run Code Online (Sandbox Code Playgroud)\n\n

等于对matrix2进行序列变换,如下所示:

\n\n
 matrix2.postSkew(0.4f,0.4f);\n matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);\n matrix2.postScale(1.2f, 1.2f);\n matrix2.postTranslate(30, 30);\n
Run Code Online (Sandbox Code Playgroud)\n