7. Hierarquia
Aviso: Lembro que o código fonte dado
não é compilável por si só, e que um
ambiente OpenGL completo - aquele que fomos construindo ao longo das
aulas deve funcionar. Para compilar e executar os exemplos dados aqui,
é necessário apenas adicionar partes de código nos
locais corretos das suas implementações.
Objetivo: Construção e animação de
objetos hierárquicos.
A animação hierárquica é uma das técnicas existentes para animação de objetos cujos movimentos dependem dos movimentos de outros objetos. É usada também para animar objetos complexos (compostos por diferentes elementos que se movem uns em relação aos outros).
Dois exemplos:
1. Um planetário: neste caso os objetos
dependem uns dos outros (Planetas girando em torno do Sol e
satélites em torno dos planetas).
2. Articulated robot arm: neste caso temos um objeto complexo (partes
conectadas).
O movimento dos elementos será definido por transformações (translações, rotações e possivelmente escala).
Note que animação hierárquica diz respeito a segmentos rígidos; neste curso não veremos objetos deformáveis.
Exercício 1: hierarquia de um planetário (nosso Sistema Solar).
Iniciemos por um modelo simplificado
do Sistema Solar. Este modelo é composto pelo Sol, em torno do
qual giram a Terra e Marte. Ele tem também a Lua, que gira em
torno da Terra.
A hierarquia é representada da seguinte maneira:
Sol ¦ +- Terra ¦ ¦ ¦ +- Lua ¦ +- Marte |
Então diz-se que:
Cada filho depende do movimento do seu pai. Uma
imagem renderizada desse modelo é mostrada na figura 1.
Figura 1. Vista do planetário simplificado.
Começamos inicializando os ângulos de rotação para os corpos celestes.
/* rotation angles for the celestial bodies */ /* for the camera, remember the previous weeks
assignments */ |
Depois, escrevemos as funções que desenham os diferentes corpos (vocês podem substitui-la por uma das suas funções drawMesh para ver o que acontece).
void drawSun(){ glColor3f(
1, 1, 0 ); void drawEarth(){ glColor3f(
0, 0, 1 ); void drawMoon(){ glColor3f(
0.5, 0.5, 0.5 ); void drawMars(){ glColor3f(
1, 0.2, 0 ); |
Então, na função display, criamos a hierarquia. Observem com atenção o uso dos blocos glPushMatrix/glPopMatrix que permitem salvar e restaurar o contexto de transformações.
O uso desses blocos é necessário quando há ramificações na hierarquia, i. e., quando um pai tem mais de um filho. Nesse caso, é necessário usar PushMatrix para salvar o contexto e PopMatrix para recuperá-lo.
É o que acontece com as
ligações (Sol >> Terra) e (Sol >> Marte) e
que caracteriza uma bifurcação (revise o quadro da
hierarquia). Assim, depois de fazer as transformações da
Terra, que depende do Sol, será necessário voltar ao
contexto do Sol para aplicar as transformações referentes
a Marte, porque ele também depende do Sol.
Se o contexto não for recarregado, a hierarquia vai se perder
completamente.
void
display(void)
glLoadIdentity();
glutSwapBuffers(); |
E aqui, finalmente, o timer para animação do sistema.
void angleEarth
+= 3; angleMoon
+= 6; angleMars
+= 2;
glutPostRedisplay(); |
Para navegar em torno do sistema e observá-lo de diferentes pontos de vista, se pode reutilizar o código para animação de câmera visto anteriormente.
Questões:
1. Testem o example anterior e ENTENDAM a hierarquia.
2. Completem a cena:
Exercice 2 : Braço de robô
articulado
Agora veremos como animar outro tipo de hierarquia. Um braço robótico, que é um conjunto de partes articuladas que poderá dar algumas idéias para o projeto.
O braço é composto de 6 segmentos:
|
Uma imagem renderizada é mostrada na figura 2:
Figure 2. Vista do braço articulado
De forma análoga ao planetário, implementaremos os vários elementos.
As variáveis globais:
/* angles for the articulations */ int flag =
0; // flag to select the element to be edited /* for the camera, same thing of the previous exercice
*/ |
Depois, a função display com a hierarquia do robô.
void
display(void)
glLoadIdentity(); glPushMatrix(); // Draw Robot Arm glTranslatef( 0, 4, 0 ); glColor3f(
0.1, 0.1, 1 ); glTranslatef( 0, 3.5, 0 ); glColor3f(
1, 0.1, 0.1 ); glTranslatef( 0, 0.75, 0 );
glPushMatrix();
glPushMatrix(); glPopMatrix();
glutSwapBuffers(); |
Então, as
funções para mover as juntas.
(lembrem-se da interação pelo teclado)
void increment( int delta ){ switch(
flag ){ } void key( unsigned char k, int x, int y ){ switch( k ){ } void specialkey( int k, int x, int y ){ switch( k ){ case
GLUT_KEY_RIGHT: increment(5); break; } |
Mais estas duas para lembrarem da interação pelo teclado:
glutKeyboardFunc(key); glutSpecialFunc(specialkey); |
E o timer para cotrole da câmera.
void float ro; if( stop ){ value++; if( value == 720 ) value = 0; ro = ro_min
- sin(value/2.0*PI/360)*ro_min*0.8;
glutPostRedisplay(); |
Questão:
1. Melhorar o realismo da câmera em dois quesitos: