我正在使用Matrix缩放和旋转位图。现在我想知道preconcat和amp;之间有什么区别? postconcat是,或更准确地说是:
之间的区别从我到目前为止可以看出,setRotate总是覆盖整个矩阵,而使用preRotate和postRotate我可以对矩阵应用多个更改(例如缩放+旋转)。但是,使用postRotate或preRotate对我使用它们的情况没有任何不同的结果。
答案 0 :(得分:129)
您的问题的答案并非真正针对Android;这是一个图形和数学问题。在这个答案中有很多理论 - 你已经被警告了!如果您对问题的表面答案,请跳到底部。此外,因为这是一个冗长的长篇大论,我可能会有一两个错误的错误。如果是这样,我会提前道歉。
在计算机图形学中,我们可以将像素(或3D,顶点)表示为矢量。如果您的屏幕是640x480,这里是屏幕中间点的2D矢量(原谅我的伪劣标记):
[320]
[240]
[ 1]
我会解释为什么1后来很重要。转换通常使用matrices来表示,因为将它们链接在一起非常简单(并且非常有效),就像您提到的那样。要将上面的点缩放1.5倍,您可以通过以下矩阵left-multiply:
[1.5 0 0]
[ 0 1.5 0]
[ 0 0 1]
你会得到这个新观点:
[480]
[360]
[ 1]
代表原始点,相对于屏幕一角(0,0)缩放1.5。这很重要:始终根据原点进行缩放。如果您想要将其他点作为中心进行缩放(例如精灵的中间),则需要将缩放比例“换行”到原点的转换中。这是将原始点转换为原点的矩阵:
[1 0 -320]
[0 1 -240]
[0 0 1]
哪个收益率:
[320*1 + 1*-320] [0]
[240*1 + 1*-240] = [0]
[ 1*1 ] [1]
您将识别上面的identity矩阵,其中位移坐标位于右上角。这就是为什么1(“同质坐标”)是必要的:为这些坐标腾出空间,从而可以使用乘法进行平移。否则它必须用矩阵加法来表示,这对人类来说更直观,但会使图形卡比现在更加复杂。
现在,矩阵乘法通常为isn't commutative,因此在“添加”变换时(通过乘以矩阵),您需要指定是左对乘还是右乘。它的不同之处在于你的变换的顺序是什么。通过右乘你的矩阵(使用preRotate()
)你指出旋转步骤应该发生之前所有其他变换你刚刚要求的。这可能是你想要的,但通常不是。
通常,没关系。例如,如果你只有一个变换,它永远不会重要:)有时,你的变换可以以任何顺序发生,具有相同的效果,例如缩放和旋转 - 我的线性代数生锈,但我相信在这种情况下矩阵乘法实际上是可交换的,因为比例矩阵是symmetric,也就是说,它在对角线上反射自身。但实际上,只要想一想:如果我将一些图片顺时针旋转10度然后将其缩放到200%,它看起来就像我先缩放它然后旋转它一样。
如果你正在做一些更奇怪的化合物转换,你会发现一个差异。我的建议是坚持postRotate()
。
答案 1 :(得分:4)
我昨天回答了这个问题,但今天我觉得有些不对劲,所以我在这里纠正了答案:
matrix: float[] values ={1.2f,0.5f,30,0.5f,1.2f,30,0,0,1};
//as we all know, the basic value in matrix,means no transformation added
matrix2: float[] values2 ={1f,0,0,0,1f,0,0,0,1};
Let's say our matrix values are the values above.
1,当我们进行如下转换时:
matrix.preTranslate(-50, -50);
is equals to do sequence transformation to matrix2 above like below:
matrix2.postTranslate(-50, -50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);// note here
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
2,当我们进行如下转换时:
matrix.preRotate(50);
is equals to do sequence transformation to matrix2 like below:
matrix2.postRotate(50);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
3,当我们进行如下转换时:
matrix.preScale(1.3f,1.3f);
is equals to do sequence transformation to matrix2 like below:
matrix2.postScale(1.3f,1.3f);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);
4,当我们进行如下转换时:
matrix.preSkew(0.4f,0.4f);
等于对矩阵进行序列转换,如下所示:
matrix2.postSkew(0.4f,0.4f);
matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);
matrix2.postScale(1.2f, 1.2f);
matrix2.postTranslate(30, 30);