# Transformações geométricas 2D e 3D

Translação, escala e rotação em coordenadas homogéneas, composição e câmara.

Página: https://resumos.rgo.pt/cadeiras/cg/transformacoes-geometricas/

Mover um objeto na cena é multiplicar os seus vértices por uma matriz. Rodar a câmara é multiplicar por outra. As **transformações geométricas** são o vocabulário com que se diz onde está cada coisa e para onde olha a câmara. Se dominares a composição de matrizes, metade dos exercícios da cadeira passam a ser multiplicações que já sabes fazer.

## Coordenadas homogéneas

A translação não é linear: somar $(t_x, t_y)$ a um ponto não se escreve como produto por uma matriz $2 \times 2$. A solução é acrescentar uma coordenada e trabalhar em **coordenadas homogéneas**: o ponto 2D $(x, y)$ passa a $(x, y, 1)$ e o ponto 3D $(x, y, z)$ passa a $(x, y, z, 1)$. Com esta coordenada extra, translação, escala e rotação escrevem-se todas como produtos por matrizes, e compor transformações é multiplicar matrizes. No fim divide-se pela última coordenada para voltar ao espaço original. Revê o [produto de matrizes](https://resumos.rgo.pt/cadeiras/alga/matrizes/) se a multiplicação já não sair automática, porque a ordem vai importar.

As três transformações básicas em 2D, aplicadas a vetores coluna, são:

$$
T(t_x, t_y) = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix}, \qquad S(s_x, s_y) = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}, \qquad R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}.
$$

Em 3D as matrizes são $4 \times 4$ com a mesma estrutura: a translação ocupa a última coluna, a escala a diagonal e a rotação um bloco $3 \times 3$. Rotações em 3D fazem-se eixo a eixo, e cada eixo tem a sua matriz.

[Vídeo: Linear transformations and matrices, Essence of linear algebra](https://www.youtube.com/watch?v=kYB8IZa5AuE)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=kYB8IZa5AuE)

## A ordem muda o resultado

Com vetores coluna, a matriz da direita aplica-se primeiro: em $M = T \cdot R \cdot S$, o ponto sofre primeiro a escala $S$, depois a rotação $R$ e por fim a translação $T$. Trocar a ordem dá outro movimento. Esta é a armadilha clássica: “rodar e depois mover” não é “mover e depois rodar”.

Toma o ponto $P = (1, 0, 0)$, a escala uniforme $S$ de fator 2, a rotação $R$ de $90°$ sobre $z$ e a translação $T$ de $(1, 0, 0)$:

$$
S = \begin{bmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}, \quad R = \begin{bmatrix} 0 & -1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}, \quad T = \begin{bmatrix} 1 & 0 & 0 & 1 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}.
$$

Com $M = T \cdot R \cdot S$, o ponto escala primeiro para $(2, 0, 0)$, roda para $(0, 2, 0)$ e translada para $(1, 2, 0)$. Podes confirmar multiplicando a matriz composta:

$$
M = T \cdot R \cdot S = \begin{bmatrix} 0 & -2 & 0 & 1 \\ 2 & 0 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}, \qquad M \cdot \begin{bmatrix} 1 \\ 0 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 1 \\ 2 \\ 0 \\ 1 \end{bmatrix}.
$$

Com a ordem trocada, $M' = S \cdot R \cdot T$, o ponto translada primeiro para $(2, 0, 0)$, roda para $(0, 2, 0)$ e escala para $(0, 4, 0)$. Mesmo ingredientes, destino diferente. Quando o enunciado disser “roda o objeto sobre si próprio e depois coloca-o na posição”, a rotação fica à direita e a translação à esquerda.

O desenho mostra o caminho do ponto nas duas ordens: partilham o troço até $R$ e só o destino final difere. Segue as setas e confirma cada paragem com as contas acima.

![Caminho do ponto P nas duas ordens: de P a S a R, depois a seta verde chega a T da ordem T R S e a seta vermelha chega a T da ordem S R T.](https://resumos.rgo.pt/cadeiras/cg/transformacoes-geometricas/figura-1.svg)

Corre as duas ordens e confirma os destinos. Muda o ângulo para $180$ e prevê o resultado antes de carregares em Executar.

```javascript
const S = [[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,1]];
const R = [[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]];
const T = [[1,0,0,1],[0,1,0,0],[0,0,1,0],[0,0,0,1]];
const mul = (A, B) => A.map(row => B[0].map((_, j) => row.reduce((s, v, k) => s + v * B[k][j], 0)));
const apply = (M, p) => M.map(row => row.reduce((s, v, k) => s + v * p[k], 0));
const M = mul(T, mul(R, S));
console.log("T·R·S em (1,0,0):", apply(M, [1, 0, 0, 1]).slice(0, 3));
const Mp = mul(S, mul(R, T));
console.log("S·R·T em (1,0,0):", apply(Mp, [1, 0, 0, 1]).slice(0, 3));
```

[Vídeo: Matrix multiplication as composition, Essence of linear algebra](https://www.youtube.com/watch?v=XkY2DOUCWMU)

A miniatura vem do YouTube. O vídeo só carrega quando clicas. [Abrir no YouTube](https://www.youtube.com/watch?v=XkY2DOUCWMU)

## De que lado se multiplica

Nem todos os sistemas escrevem os vetores da mesma maneira, e o lado da matriz muda com isso. Compara as duas convenções antes de copiares uma fórmula dos slides para o código.

Vetor coluna à direita da matriz, como nesta página e no OpenGL clássico. A matriz da direita aplica-se primeiro: em $M = T \cdot R \cdot S$, a escala $S$ age antes da rotação $R$. A translação ocupa a última coluna.

Vetor linha à esquerda da matriz, como em alguns motores e no DirectX. Tudo se transpõe: a matriz da esquerda aplica-se primeiro, por isso a mesma sequência escreve-se $M = S \cdot R \cdot T$, e a translação ocupa a última linha. O movimento final é o mesmo se transpuseres matrizes e vetores em conjunto.

## Instancing e câmara

A composição também serve para reutilizar geometria: defines um modelo uma vez e desenhas várias cópias com matrizes de modelação diferentes. A isto chama-se **instancing**, e é como se enche uma cena de árvores ou cadeiras sem duplicar vértices.

A **transformação de vista** é a mesma ideia ao contrário: em vez de mover a câmara pelo mundo, move-se o mundo para a frente da câmara com a matriz inversa do seu posicionamento. Uma câmara na posição $C$ a olhar para o ponto $A$ constrói-se com uma base ortonormal (direita, cima, frente) que roda o mundo, seguida da translação por $-C$. Rotações, projeções e composição enquanto aplicações lineares estão explicadas nas [aplicações lineares](https://resumos.rgo.pt/cadeiras/alga/aplicacoes-lineares/).

A convenção antes da conta

Antes de multiplicares, confirma três coisas: vetores coluna ou linha (muda o lado da matriz), ângulos em graus ou radianos e se a rotação é sobre o eixo certo. Nove em cada dez exercícios errados falham aqui, não na multiplicação.

## Para saber mais

*   [Transformações em OpenGL](https://learnopengl.com/Getting-started/Transformations): matrizes de modelação, vista e projeção com código que podes correr e alterar.
