Transformações Geométricas
[Parte II]
Sumário
●
Tópicos da aula de hoje:
●
Entendendo o uso de matrizes no
OpenGL
Aula passada
● Vimos na aula passada como podemos
realizar transformações geométricas em ambientes de CG
● Vimos que as principais transformações
geométricas são translação, rotação e escala
● Por fim, vimos que todas as transformações
podem ser realizadas através de operações matriciais
O problema
● Digamos que nosso problema seja modelar
O problema
O problema
● Veja que as janelas
são iguais, só mudando a escala e o posicionamento em relação a um referencial definido no momento de iniciar a modelagem.
O problema
● Sendo a janela composta por madeira e vidros, poderíamos criar uma função criaJanela edentro desta função, rotinas específicas para modelar a
O problema
● Poderíamos descrever essa modelagem da
seguinte forma:
● Desenhe a casa e desenha a janela na origem
(considere que há funções para isso).
● Partindo da origem, faça as transformações
geométricas necessárias para desenhar a primeira janela na posição correta.
● Jogue fora as transformações geométricas
utilizadas e faça novas transformações para desenhar a segunda janela.
● Jogue fora as transformações geométricas
utilizadas e faça novas transformações para desenhar a terceira janela.
O problema
● Nosso problema então é encontrar uma forma
de armazenar as matrizes utilizadas nas
transformações geométricas de cada janela e poder jogá-las fora, conservando o estado
anterior.
● Uma forma de resolver este problema é
Pilha de matrizes
● Pilhas de matrizes são úteis para criar
modelos hierárquicos, nos quais objetos complicados são construídos através da composição de objetos mais simples
● Através da utilização de pilhas, podemos
armazenar as transformações (no topo da pilha) e “desempilhá-las” sempre que
necessário.
Entendo o uso de matrizes
● Podemos dividir a utilização de matrizes em
computação gráfica em algumas categorias distintas:
● Transformações de modelos geométricos ● Visualização de modelos geométricos
● Projeção e recorte
Entendo o uso de matrizes
● Podemos dividir a utilização de matrizes em
computação gráfica em algumas categorias distintas:
● Transformações de modelos geométricos ● Visualização de modelos geométricos
● Projeção e recorte
● Mapeamento de texturas
GL_MODELVIEW
GL_PROJECTION
Entendo o uso de matrizes
● Projeção e recorte - determinam o volume
de visualização (também serão explicados mais à frente)
● Matrizes de modelagem e matrizes de
Projeção - determinam o volume de
visualização (análogo à escolha da lente para uma máquina fotográfica)
Entendo o uso de matrizes
● Transformações de modelos geométricos –
matrizes que auxiliam no posicionamento e orientação dos objetos na cena
● Visualização de modelos geométricos - as
matrizes de visualização determinam o posicionamento da câmera virtual
Pilha de matrizes
● O OpenGL mantém 3 pilhas de matrizes,
uma para cada tipo visto anteriormente
● Para especificarmos em qual matriz
trabalhar, utilizamos o comando
glMatrixMode(tipo_da_matriz)
● A matriz default é a GL_MODELVIEW
Pilha de matrizes
● Comandos de manipulação da pilha
● glPushMatrix()– adiciona a matriz em uso no
topo da pilha corrente
● glPopMatrix()– Descarta a matriz que estiver
no topo da pilha
● A pilha de matrizes da modelview pode
armazenar, no mínimo, 32 matrizes
Imagens de "OpenGL
Exemplo
● Veja o passo-a-passo a seguir para entender
na prática como as transformações são utilizadas em um exemplo real.
● Neste exemplo, criaremos um pequeno braço
mecânico virtual com uma única articulação.
● O posicionamento correto do segundo
segmento do braço é obtido através da correta utilização da pilha de matrizes.
Este exemplo servirá como base dos exercícios desta aula.
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Considere o código ao lado e sua respectiva renderização.
Vamos ver o que acontece se
executarmos por partes (considere em cinza o código comentado)
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Inicialmente criamos um cubo com uma unidade de lado com uma
operação de escala. Armazenamos esta operação na pilha de matrizes.
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }A seguir realizamos uma translação sobre o objeto fazendo com que uma de suas extremidades (o pivo do
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Agora realizamos uma rotação de 45º (sentido anti-horário) em relação a origem.
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Braço agora foi movido uma unidade para frente, já preparando para o novo segmento de mesmo tamanho que será criado na origem.
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Novo segmento é criado,
centralizado na origem. Percebam que a escala é realizada apenas no segmento criado e não no restante do braço
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }A translação realizada agora será aplicada a todo o conjunto (braço e antebraço).
Exemplo
void desenhaBraco(void) { glRotatef (5.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); glTranslatef (1.0, 0.0, 0.0); glRotatef (45.0, 0.0, 0.0, 1.0); glTranslatef (1.0, 0.0, 0.0); glPushMatrix(); glScalef (2.0, 0.5, 0.5); glutSolidCube (1.0); glPopMatrix(); }Finalmente é aplicada a rotação final que, como a translação, é aplicada a todo o conjunto.
Saiba mais!
● OpenGL Programming Guide
Seventh Edition
● Capítulo 3
Este capítulo fala sobre
transformações geométricas de uma forma geral. A parte
relacionada diretamente a aula de hoje começa na página 164.
Saiba mais!
● OpenGL Programming Guide,
8th Edition
● Capítulo 5
Os comandos glPushMatrix e
glPopMatrix foram descontinuados
a partir da versão 3.0 do OpenGL. Em OpenGL moderno, o sistema de pilha visto nesta aula deve ser desenvolvido manualmente. No capítulo indicado há informações
Resumo
●
Nesta aula vimos
●
O problema envolvendo a criação de
modelos hierárquicos.
●
A solução através de pilhas de matrizes.
●Um exemplo utilizando pilhas de
matrizes para fazer um braço virtual
articulado.
Exercícios - Instruções
●
Abra o projeto "Braço 3D"
●
Verifique o funcionamento do código, em
especial como funciona a pilha de matrizes
através dos comandos glPushMatrix e
glPopMatrix
●
Siga os comentários do código e tente
esboçar no papel o comportamento do
algoritmo.
Exercícios 1
● Altere o código "Braco3D"
acrescentando mais um segmento ao braço
robótico. Este segmento terá o mesmo
comportamento do restante do braço.
Exercícios 2
● Altere o código do exercício
2 acrescentando garras móveis na ponta do último segmento. Mapeie os
direcionais para cima e
para baixo para controlar o comportamento da garra.
Esboce no papel como montar as garras antes de partir para o código. Dica: crie uma função para definir a garra.