<p>The mistake was in the multiplication order during the composition of the matrices.</p>

<p>Since the OP was working with column vectors the correct order for transformations should have been <span class="math-container">$TRSA∗v$</span>. The OP did the other way around, <span class="math-container">$ASRT*v$</span> thus the incorrect results.</p>

<p>Also there need to be another <span class="math-container">$A^{\prime}$</span> matrix added which negates the  translation done by  <span class="math-container">$A$</span>. The first <span class="math-container">$A$</span> matrix should have <span class="math-container">$-u, -v$</span> to translate <span class="math-container">$u,v$</span> to origin. The <span class="math-container">$A^{\prime}$</span> matrix should have <span class="math-container">$u, v$</span> to translate back.</p>

<p>Hence the correct composition should be, <span class="math-container">$TA^{\prime}RSA*v$</span> or <span class="math-container">$A^{\prime}TRSA*v$</span> depending on whether the translation is intended around <span class="math-container">$u,v$</span> or the origin.</p>

CC BY-SA 4.0
2019-02-05T08:43:51.127Z
2019-02-05T09:45:52.040Z
2019-02-05T09:45:52.040Z
gallickgunner
<p>Now I know this isn't the way this is normally done so please bear with me. I am doing this this way so I know I have a solid conceptual understanding of everything that goes beyond example code.</p>

<p>I am trying to create a simple 2D game with sprites that and rotate, move, scale etc.</p>

<p>I thus constructed the following matrices </p>

<p><strong>Transform</strong></p>

<p>I want the sprites center to move from the origin by (<code>x</code>, <code>y</code>) units</p>

<p><span class="math-container">$$T = \begin{bmatrix} 
1 &amp; 0 &amp; x \\
0 &amp; 1 &amp; y \\
0 &amp; 0 &amp; 1
\end{bmatrix}$$</span></p>

<p><strong>Rotation</strong></p>

<p>I want the matrix to rotate by <code>d</code> radians so I create the following variables where <code>s = sin(d)</code> and <code>c = cos(d)</code></p>

<p><span class="math-container">$$R = \begin{bmatrix} 
c &amp; -s &amp; 0 \\
s &amp; c &amp; 0 \\
0 &amp; 0 &amp; 1
\end{bmatrix}$$</span></p>

<p><strong>Scale</strong></p>

<p>I want the rectangular sprite to occupy a horizontal units and b vertical units so I generated the following matrix</p>

<p><span class="math-container">$$S= \begin{bmatrix} 
a &amp; 0 &amp; 0 \\
0 &amp; b &amp; 0 \\
0 &amp; 0 &amp; 1
\end{bmatrix} $$</span></p>

<p><strong>Center</strong></p>

<p>And finally I want the sprite to do all of these transformations with its center of movement being at (<code>u</code>, <code>v</code>) therefore I will plan to have to use a matrix sort of like this (you'll see why later) </p>

<p><span class="math-container">$$A = \begin{bmatrix} 
1 &amp; 0 &amp; -u \\
0 &amp; 1 &amp; -v \\
0 &amp; 0 &amp; 1
\end{bmatrix}$$</span></p>

<p>Now the plan is to stream in the points (0, 0) (0, 1) (1, 1) and (1, 0) into my vertex shader and then use <strong>a single</strong> matrix to translate the points to where they need to go.</p>

<p>So I assumed that I could combine all these matrices as follows based on code examples etc. </p>

<p><span class="math-container">$$A * S * R * T$$</span></p>

<p>So I pulled these matrixes into Symbolab and got the following result</p>

<p><a href="https://i.sstatic.net/KN4Jz.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/KN4Jz.png" alt="Picture of symbolab result"></a></p>

<p>Great! So time to pass it in. Now Metal uses SIMD but I need my engine to be completely cross platform so instead I read the SIMD alignment guides and tried to match them with this struct: </p>

<pre><code>struct float3x3 {
    float columns[3][4];

    float3x3() {
        for (int i = 0; i &lt; 3; i++) {
            for (int j = 0; j &lt; 4; j++) {
                rows[i][j] = 0;
            }
        }
    }
} __attribute__ ((aligned(16))) ;
</code></pre>

<p>Which means inside of my CPU code I can create the matrix like this (based on the symbolab result)</p>

<pre><code>float3x3 matrix;
matrix.columns[0][0] = a * c;
matrix.columns[1][0] = -a * s;
matrix.columns[2][0] = a * c * x - a * s * y + u;
matrix.columns[0][1] = s * b;
matrix.columns[1][1] = b * c;
matrix.columns[2][1] = b * s * x + b * c * y + v;
matrix.columns[2][2] = 1;
</code></pre>

<p>And pass it in like this </p>

<pre><code>[encoder setVertexBytes:&amp;matrix length:sizeof(simd_float3x3) atIndex:2];
</code></pre>

<p>And then finally I can pass it into my vertex shader which looks like this</p>

<pre><code>vertex ColorInOut tex_plain_vert(uint vid [[vertex_id]],
                                 constant matrix_float3x3* worldMatrix [[buffer(3)]],
                                 constant matrix_float3x3* localMatrix [[buffer(2)]]) {
    float2 coords[] = {float2(0, 0),
        float2(1.0, 0),
        float2(0, 1.0),
        float2(1.0, 1.0)};

    const float2 texc[] = {float2(0.0, 1.0),
        float2(1.0, 1.0),
        float2(0.0, 0.0),
        float2(1.0, 0.0)};

    const int lu[] = {0, 1, 2, 2, 1, 3};

    ColorInOut out;
    out.texCoord = texc[lu[vid]];
    float3 padded = float3(coords[lu[vid]], 1.0);
    matrix_float3x3 w = *worldMatrix;
    matrix_float3x3 l = *localMatrix;
    float3 res = w * l * padded;
    out.position = float4(res.x, res.y, 0.0 , 1.0);
    return out;
}
</code></pre>

<p>However this doesnt work. Depending on how I have messed with things the square is either wildly off screen or doesn't translate to the (<code>x</code>, <code>y</code>) at all.</p>

<p>And yes my world matrix is VERY thoroughly tested and you will see in a bit that it is wrong even without that value.</p>

<p>So I pulled it into the vertex debugger and got the following information with the following variables</p>

<pre><code>x = 0
y = 50
s = 0
c = 1
a = 120
b = 120
u = 0.5
v = 0.5
</code></pre>

<p><a href="https://i.sstatic.net/LM4g5.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/LM4g5.png" alt="Vertex debugger"></a></p>

<p>p2 is where you can really see the error with those settings <code>0,0</code> should have translated to <code>-60,-10</code> and <code>1, 0</code> should have translated to <code>60, -60</code>. None of these huge numbers and it is my inclination to think that it is mostly the 3rd column of the matrix at fault.</p>

<p>My inclination based on seeing these results is that the matrix I am passing in is wrong. But I dont know another way to do that math.</p>

<p>I have also tried tweaking things like switching rows and columns changing multiplication order to no avial. The closest I have gotten was something that rotated and scaled but did not move and one that moved but had sheering effects.</p>

<p>There are a lot of places in this process that I could have gone wrong (initial matrices, matrix multiplication\order, matrix struct, vertex shader, etc) and I would really appreciate your help finding it as I have spent awhile on this now.</p>

CC BY-SA 4.0
2019-02-03T11:43:25.747Z
Giving a quick look I see a few problems. You are missing the negative signs ($-u,-v$) in the matrix $A$ during matrix composition. Also since you want to do transformations around the point $u,v$. You correctly move $u,v$ to origin by doing $-u,-v$ but you forgot to move back to the origin since $x,y$ are translating from origin to $x,y$ not from $u,v$ to $x,y$. So in your matrix composition before the last matrix $T$ you need to add another matrix which scales from $u,v$ to origin.
gallickgunner
CC BY-SA 4.0
2019-02-03T19:41:28.883Z
@gallickgunner you are completely right. I am just now confused where the scale matrix should go or if maybe I need to make a new A matrix that considers the scale? Nonetheless with this implemented I still have the result of a rectangle that is either not moving or off screen depending on whether I pass in the transpose or not.
J.Doe
CC BY-SA 4.0
2019-02-03T21:36:37.843Z
Ok I assume the vector you are multiplying with is a column vector since you do `l * p` i.e. the vector comes afterwards. Then shouldn't the above composition be backwards since thinking about it in components, you should have $TRSA * v$. I don't know if that's what you meant when you said you had tried changing the order of multiplications, though.  Also try breaking your composite matrix in components, maybe first check each of your matrices separately to see if the individual operations are working perfectly, then start composing them 1 by 1.
gallickgunner
CC BY-SA 4.0
2019-02-05T08:40:27.357Z
Np. Adding this as an answer to make it clear the question was solved.
gallickgunner
<transformations><matrix><2d><2d-graphics>
My 2D translation matrix causes the box to be off screen when it shouldnt be
J.Doe
# My 2D translation matrix causes the box to be off screen when it shouldnt be

(Asked by: username_0 on 2019-02-03)

Now I know this isn't the way this is normally done so please bear with me. I am doing this this way so I know I have a solid conceptual understanding of everything that goes beyond example code.

I am trying to create a simple 2D game with sprites that and rotate, move, scale etc.

I thus constructed the following matrices

**Transform**

I want the sprites center to move from the origin by (`x`, `y`) units

$$T = \begin{bmatrix}
1 & 0 & x \\
0 & 1 & y \\
0 & 0 & 1
\end{bmatrix}$$

**Rotation**

I want the matrix to rotate by `d` radians so I create the following variables where `s = sin(d)` and `c = cos(d)`

$$R = \begin{bmatrix}
c & -s & 0 \\
s & c & 0 \\
0 & 0 & 1
\end{bmatrix}$$

**Scale**

I want the rectangular sprite to occupy a horizontal units and b vertical units so I generated the following matrix

$$S= \begin{bmatrix}
a & 0 & 0 \\
0 & b & 0 \\
0 & 0 & 1
\end{bmatrix} $$

**Center**

And finally I want the sprite to do all of these transformations with its center of movement being at (`u`, `v`) therefore I will plan to have to use a matrix sort of like this (you'll see why later)

$$A = \begin{bmatrix}
1 & 0 & -u \\
0 & 1 & -v \\
0 & 0 & 1
\end{bmatrix}$$

Now the plan is to stream in the points (0, 0) (0, 1) (1, 1) and (1, 0) into my vertex shader and then use **a single** matrix to translate the points to where they need to go.

So I assumed that I could combine all these matrices as follows based on code examples etc.

$$A \* S \* R \* T$$

So I pulled these matrixes into Symbolab and got the following result

[![Picture of symbolab result](https://i.sstatic.net/KN4Jz.png)](https://i.sstatic.net/KN4Jz.png)

Great! So time to pass it in. Now Metal uses SIMD but I need my engine to be completely cross platform so instead I read the SIMD alignment guides and tried to match them with this struct:

```
struct float3x3 {
    float columns[3][4];

    float3x3() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                rows[i][j] = 0;
            }
        }
    }
} __attribute__ ((aligned(16))) ;

```

Which means inside of my CPU code I can create the matrix like this (based on the symbolab result)

```
float3x3 matrix;
matrix.columns[0][0] = a * c;
matrix.columns[1][0] = -a * s;
matrix.columns[2][0] = a * c * x - a * s * y + u;
matrix.columns[0][1] = s * b;
matrix.columns[1][1] = b * c;
matrix.columns[2][1] = b * s * x + b * c * y + v;
matrix.columns[2][2] = 1;

```

And pass it in like this

```
[encoder setVertexBytes:&matrix length:sizeof(simd_float3x3) atIndex:2];

```

And then finally I can pass it into my vertex shader which looks like this

```
vertex ColorInOut tex_plain_vert(uint vid [[vertex_id]],
                                 constant matrix_float3x3* worldMatrix [[buffer(3)]],
                                 constant matrix_float3x3* localMatrix [[buffer(2)]]) {
    float2 coords[] = {float2(0, 0),
        float2(1.0, 0),
        float2(0, 1.0),
        float2(1.0, 1.0)};

    const float2 texc[] = {float2(0.0, 1.0),
        float2(1.0, 1.0),
        float2(0.0, 0.0),
        float2(1.0, 0.0)};

    const int lu[] = {0, 1, 2, 2, 1, 3};

    ColorInOut out;
    out.texCoord = texc[lu[vid]];
    float3 padded = float3(coords[lu[vid]], 1.0);
    matrix_float3x3 w = *worldMatrix;
    matrix_float3x3 l = *localMatrix;
    float3 res = w * l * padded;
    out.position = float4(res.x, res.y, 0.0 , 1.0);
    return out;
}

```

However this doesnt work. Depending on how I have messed with things the square is either wildly off screen or doesn't translate to the (`x`, `y`) at all.

And yes my world matrix is VERY thoroughly tested and you will see in a bit that it is wrong even without that value.

So I pulled it into the vertex debugger and got the following information with the following variables

```
x = 0
y = 50
s = 0
c = 1
a = 120
b = 120
u = 0.5
v = 0.5

```

[![Vertex debugger](https://i.sstatic.net/LM4g5.png)](https://i.sstatic.net/LM4g5.png)

p2 is where you can really see the error with those settings `0,0` should have translated to `-60,-10` and `1, 0` should have translated to `60, -60`. None of these huge numbers and it is my inclination to think that it is mostly the 3rd column of the matrix at fault.

My inclination based on seeing these results is that the matrix I am passing in is wrong. But I dont know another way to do that math.

I have also tried tweaking things like switching rows and columns changing multiplication order to no avial. The closest I have gotten was something that rotated and scaled but did not move and one that moved but had sheering effects.

There are a lot of places in this process that I could have gone wrong (initial matrices, matrix multiplication\order, matrix struct, vertex shader, etc) and I would really appreciate your help finding it as I have spent awhile on this now.

**Tags:** transformations, matrix, 2d, 2d-graphics

> **Comments:**
> **username_1**: Giving a quick look I see a few problems. You are missing the negative signs ($-u,-v$) in the matrix $A$ during matrix composition. Also since you want to do transformations around the point $u,v$. You correctly move $u,v$ to origin by doing $-u,-v$ but you forgot to move back to the origin since $x,y$ are translating from origin to $x,y$ not from $u,v$ to $x,y$. So in your matrix composition before the last matrix $T$ you need to add another matrix which scales from $u,v$ to origin.  
> **username_0**: @username_1 you are completely right. I am just now confused where the scale matrix should go or if maybe I need to make a new A matrix that considers the scale? Nonetheless with this implemented I still have the result of a rectangle that is either not moving or off screen depending on whether I pass in the transpose or not.  
> **username_1**: Ok I assume the vector you are multiplying with is a column vector since you do `l * p` i.e. the vector comes afterwards. Then shouldn't the above composition be backwards since thinking about it in components, you should have $TRSA * v$. I don't know if that's what you meant when you said you had tried changing the order of multiplications, though.  Also try breaking your composite matrix in components, maybe first check each of your matrices separately to see if the individual operations are working perfectly, then start composing them 1 by 1.  
> **username_1**: Np. Adding this as an answer to make it clear the question was solved.  

---

## 1 answers

### Answer by username_1 on 2019-02-05. Score: 2 | Accepted answer

The mistake was in the multiplication order during the composition of the matrices.

Since the OP was working with column vectors the correct order for transformations should have been $TRSA∗v$. The OP did the other way around, $ASRT\*v$ thus the incorrect results.

Also there need to be another $A^{\prime}$ matrix added which negates the translation done by $A$. The first $A$ matrix should have $-u, -v$ to translate $u,v$ to origin. The $A^{\prime}$ matrix should have $u, v$ to translate back.

Hence the correct composition should be, $TA^{\prime}RSA\*v$ or $A^{\prime}TRSA\*v$ depending on whether the translation is intended around $u,v$ or the origin.


---

