Using absolute coordinates in 2D affine transformation matrix

666 Views Asked by At

In my 2D animation program I have a sprite which transformation is described by a 2D affine transformation matrix (SVGMatrix):

$$ \begin{bmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \\ \end{bmatrix} $$

I'm trying to figure out how to set this sprite position to given screen coordinates:

$$ \begin{bmatrix} x \\ y \\ 1 \\ \end{bmatrix} $$

The sprite position is the position of sprite's pivot point, which is defined by sprite's transformation matrix.

For example, if a sprite of 64 x 64 pixels in size has this transformation matrix:

$$ \begin{bmatrix} 2 & 0 & 32 \\ 0 & 2 & 32 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

...The sprite's pivot point is in its center, and the sprite is scaled x2.

The operation I look for, set_position(x, y), should change sprite's transformation matrix in such way, so that the center (pivot point) of this sprite will be at $(x, y)$.

(Unfortunately, I'm quite rusty on the topic and googling does not yield anything satisfactory. However, I feel that this is an embarassingly basic question...)

Say, I want the sprite to appear at $(300, 200)$:

set_position(300, 200)

For a sprite with identity transformation matrix —not scaled, rotated, inverted or skewed, pivot at $(0, 0)$:

$$ \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

...The result would be:

$$ \begin{bmatrix} 1 & 0 & 300 \\ 0 & 1 & 200 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

If the sprite was scaled:

$$ \begin{bmatrix} 2 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

...The result should take that in account:

$$ \begin{bmatrix} 2 & 0 & 150 \\ 0 & 2 & 100 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

Same thing for rotation, inversion and skew/shear.

That is, for a sprite of 64 x 64 pixels in size, this operation (in pseudocode) would move the sprite's pivot to its center and will rotate around the pivot by 90 degrees:

translate(32, 32)
rotate(π/2)

The corresponding matrix for the sprite:

$$ \begin{bmatrix} 0 & 1 & 32 \\ -1 & 0 & 32 \\ 0 & 0 & 1 \\ \end{bmatrix} $$

Now, my set_position(300, 200) operation should change the sprite's transformation matrix so that the sprite's center (i.e. the pivot) would be at specified coordinates, $(300, 200)$.

Calculating expected set_position() result in this case will require some trigonometry, I guess, since sprite's coordinate system was rotated beforehand.

Looks like I'm missing something. Any clues on how to approach this?

1

There are 1 best solutions below

0
On

Looks like this really is an embarrassingly simple question.

Effectively, I need the translation to the given screen coordinates to happen before sprite's own transformation.

So, I need to multiply translation matrix for the coordinates that I need the by sprite's translation matrix, not vice-versa.

$$ \begin{bmatrix} 0 & 0 & x \\ 0 & 0 & y \\ 0 & 0 & 1 \\ \end{bmatrix} \times \begin{bmatrix} a & c & e \\ b & d & f \\ 0 & 0 & 1 \\ \end{bmatrix} $$

Doh.