安卓:矩阵 ->preconcat 和 postconcat 有什么区别? [英] Android: Matrix -> what is the different between preconcat and postconcat?

查看:54
本文介绍了安卓:矩阵 ->preconcat 和 postconcat 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Matrix to scale and rotate Bitmaps. Now I'm wondering what the difference between preconcat & postconcat is, or more precisely the difference between:

据我目前所知,setRotate 总是覆盖整个矩阵,而使用 preRotate 和 postRotate 我可以对矩阵应用多个更改(例如缩放 + 旋转).但是,对于我使用它们的情况,使用 postRotate 或 preRotate 并没有导致任何不同的结果.

From what I could figure out so far setRotate always overwrites the whole matrix, while with preRotate and postRotate I can apply multiple changes to a matrix (e.g. scaling + rotation). However, either using postRotate or preRotate didn't cause any different results for the cases I used them.

推荐答案

您的问题的答案并不是真正针对 Android;这是一道图形和数学题.这个答案中有很多理论——你已经被警告过!对于您的问题的肤浅答案,请跳到底部.另外,因为这是一篇冗长的长篇大论,我可能会有一两个错字,让事情不清楚.如果是这样,我提前道歉.

The answer to your question isn't really specific to Android; it's a graphics and math question. There's lots of theory in this answer--you've been warned! For a superficial answer to your question, skip to the bottom. Also, because this is such a long-winded tirade, I might have a typo or two making things unclear. I apologize in advance if that's the case.

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

In computer graphics, we can represent pixels (or in 3D, vertices) as vectors. If your screen is 640x480, here's a 2D vector for the point in the middle of your screen (forgive my shoddy markup):

[320]
[240]
[  1]

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

I'll explain why the 1 is important later. Transformations are often represented using matrices because it's then very simple (and very efficient) to chain them together, like you mentioned. To scale the point above by a factor of 1.5, you can left-multiply it by the following matrix:

[1.5   0   0]
[  0 1.5   0]
[  0   0   1]

你会得到这个新观点:

[480]
[360]
[  1]

代表原始点,相对于屏幕角 (0, 0) 缩放 1.5.这很重要:缩放总是相对于原点进行的.如果您想以某个其他点为中心(例如精灵的中间)进行缩放,则需要在与原点之间的平移中包裹"比例.这是将我们的原始点转换为原点的矩阵:

Which represents the original point, scaled by 1.5 relative to the corner of your screen (0, 0). This is important: scaling is always done with respect to the origin. If you want to scale with some other point as your center (such as the middle of a sprite), you need to "wrap" the scale in translations to and from the origin. Here's the matrix to translate our original point to the origin:

[1  0  -320]
[0  1  -240]
[0  0     1]

产生的结果:

[320*1 + 1*-320]   [0]
[240*1 + 1*-240] = [0]
[     1*1      ]   [1]

您将把上面的内容识别为 身份 矩阵,其位移坐标位于上-右上角.这就是为什么 1(齐次坐标")是必要的:为这些坐标腾出空间,从而可以使用乘法进行转换.否则就必须用矩阵加法来表示,这对人类来说更直观,但会使显卡比现有的更复杂.

You'll recognize the above as the identity matrix with the displacement coordinates slapped in the upper-right corner. That's why the 1 (the "homogenous coordinate") is necessary: to make room for these coordinates, thus making it possible to translate using multiplication. Otherwise it would have to be represented by matrix addition, which is more intuitive to humans, but would make graphics cards even more complicated than they already are.

现在,矩阵乘法通常不是可交换的,所以当添加"一个转换(通过乘以你的矩阵)你需要指定你是左乘还是右乘.它的区别在于您的转换链接的顺序.通过右乘您的矩阵(使用 preRotate()),您表明旋转步骤应该在 before您刚刚要求的所有其他转换.这可能是您想要的,但通常不是.

Now, matrix multiplication generally isn't commutative, so when "adding" a transformation (by multiplying your matrix) you need to specify whether you're left-multiplying or right-multiplying. The difference it makes is what order your transformations are chained in. By right-multiplying your matrix (using preRotate()) you're indicating that the rotation step should happen before all the other transformations that you've just asked for. This might be what you want, but it usually isn't.

通常,这无关紧要.例如,如果您只有一个转换,则这无关紧要 :) 有时,您的转换可以按任意顺序发生并产生相同的效果,例如缩放和旋转——我的线性代数很生疏,但我相信在这种情况下矩阵乘法实际上是可交换的,因为尺度矩阵是对称,也就是说,它在对角线上镜像自己.但实际上,想想看:如果我将某张图片顺时针旋转 10 度,然后将其缩放到 200%,看起来就像我先缩放然后旋转一样.

Often, it doesn't matter. If you only have one transformation, for example, it never matters :) Sometimes, your transformations can happen in either order with the same effect, such as scaling and rotation--my linear algebra is rusty, but I believe that in this case the matrix multiplication actually is commutative because the scale matrix is symmetric, that is, it mirrors itself across the diagonal. But really, just think about it: If I rotate some picture 10 degrees clockwise and then scale it to 200%, it looks the same as if I scaled it first, then rotated it.

如果您正在执行一些更奇怪的复合转换,您会开始注意到差异.我的建议是坚持使用 postRotate().

If you were doing some weirder compound transformations, you'd begin to notice a discrepancy. My advice is to stick with postRotate().

这篇关于安卓:矩阵 ->preconcat 和 postconcat 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆