Até agora discutimos elementos básicos da programação geométrica como pontos, vetores e suas operações, sistemas de coordenadas e como alterar a representação de pontos e vetores de um sistema para outro. Nessa aula vamos passar a discutir como mapear pontos de um lugar para outro. Por exemplo, suponha que você queira desenhar uma animação de uma bola girando. Como você definiria a função que mapeia cada ponto da bola para sua posição rotacionada por um determinado ângulo?
Consideraremos uma classe de transformações limitada, mas interessante, chamada de transformações afins. Estas incluem (entre outras) as seguintes transformações do espaço: translações, rotações, escalas uniformes e não uniformes (esticando os eixos por algum fator de escala constante), reflexões (invertendo objetos em torno de uma linha) e cisalhamento (que deforma quadrados em paralelogramos). Essas transformações estão ilustradas na Figura Fig. 11.1.
Fig. 11.1 Exemplos de transformações afim.¶
Todas essas transformações da Figura Fig. 11.1 têm várias coisas em comum. Por exemplo, todos elas mapeiam linhas para linhas. Observe que algumas (translação, rotação e reflexão) preservam os comprimentos dos segmentos de linha e os ângulos entre os segmentos. Outras (como a escala uniforme) preservam os ângulos, mas não os comprimentos. Outras (como cisalhamento e escala não uniforme) não preservam ângulos nem comprimentos.
Todas as transformações listadas acima preservam combinações afins. Na verdade, esta é a definição de uma transformação afim. Por exemplo, dada qualquer transformação
De forma mais intuitiva, se
Vamos nos concentrar no espaço 3D. Como consequência da invariância das relações afins temos que para:
,
então:
.
Nesse caso
Vimos na aula anterior que a representação homogênea de coordenadas de
.
Nessa representação as colunas da matriz correspondem às imagens dos elementos do sistema sob
Se você achou tudo isso um pouco abstrato, no restante dessa aula vamos fornecer alguns exemplos concretos. Em vez de considerar isso no contexto de transformações bidimensionais, vamos considerá-lo no cenário mais geral de transformações tridimensionais. Os casos bidimensionais podem ser derivadas simplesmente ignorando as linhas e colunas para as coordenadas z.
Traslação por um vetor
Observe que, como os vetores não têm posição no espaço, os vetores livres não são alterados por translação.
Suponha que em relação ao sistema de coordenadas padrão,
.
O escalonamento uniforme é uma transformação que é realizada em relação a algum ponto fixo central. Vamos supor que este ponto é a origem do sistema de coordenadas padrão. (Vamos deixar o caso geral como exercício.) Dado um
Em geral, é possível especificar fatores de escala separados para cada um dos eixos. Isso é chamado de escalonamento não uniforme. Os vetores unitários são esticados pelo fator de escala correspondente e a origem não é movida.
A forma matricial mais genérica dessa transformação é
.
Observe que tanto pontos quanto vetores são afetados por escalonamento.
Uma reflexão em 2D ao redor de uma linha mapeia os pontos refletindo-os em torno dessa linha.
Uma reflexão em 3D recebe um plano e reflete os pontos no espaço em torno desse plano. Neste caso, a reflexão é apenas um caso especial de escalonamento por um fator de escala negativo. Por exemplo, para refletir pontos sobre o plano
.
Os demais casos para os planos
De forma geral, uma rotação é definida em torno de algum ponto fixo em 2D ou em torno de algum vetor fixo no espaço 3D. Consideraremos o caso mais simples em que o ponto fixo é a origem do sistema de coordenadas e o vetor é um dos eixos de coordenadas. Assim, em 3D existem três rotações básicas: sobre os eixos
Por exemplo, no plano
.
Observe que tanto pontos quanto vetores são afetados por rotação. Para rotações aplicadas aos demais eixos temos:
, .
Uma transformação de cisalhamento é talvez a mais difícil de se visualizar. Pense em um cubo de gelatina. O que ocorre quando inclinamos esse cubo? Em 2D, um cisalhamento é uma transformação que mapeia um quadrado em um paralelogramo deslizando um lado paralelo a si mesmo enquanto mantém o lado oposto fixo. No espaço tridimensional, ele mapeia um cubo em um paralelepípedo deslizando uma face paralela enquanto mantém a face oposta fixa.
Consideraremos a forma mais simples, na qual começamos com um cubo unitário cujo canto inferior esquerdo coincide com a origem. Considere um dos eixos, digamos o eixo
Sob o cisalhamento
.
Os cisalhamentos envolvendo outros pares de eixos são definidos de forma análoga:
, .
Nessa aula começamos utilizar a forma matricial para representar transformações. Essa representação é bastante utilizada em computação gráfica por ser bastante compacta e eficiente. Na próxima aula, veremos como essas matrizes de transformação podem ser utilizadas no WebGL.
Uma forma de se aplicar uma translação a um conjunto de vértices no WebGL é usando um uniforme do tipo vec2
. Por exemplo, as posições do buffer aPosition
podem ser transladadas por um uniforme uniform vec2 uTranslacao
simplesmente usando a aritmética de vec2
do próprio GLSL como aPosition + uTranslation
, para calcular as posições transladadas.
Considere a animação de uma única bola, simplificando esse exemplo no JSitor. Modifique o vertex shader para incluir um uniforme in vec2 uTranslacao
que calcula a posição transladada e altere também o restante do programa de animação para usar a translação diretamente no shader ao invés de recalcular os vértices.
Suponha que você tenha a sua disposição uma função desenheQuadrado(Rz, Sx, Sy, Tx, Ty, color)
que desenha um quadrado de cor color
, de tamanho Rz
, escalonado por (Sx
, Sy
) e transladado para (Tx
, Ty
) em um canvas de resolução W
Fig. 11.2 Como desenhar essa figura usando a função desenheQuadrado()
?¶