Exercício I
Disciplina: Computação Gráfica
Professora: Soraia R. Musse
Usando OpenGL
O objetivo desta aula é
aprender a utilizar a biblioteca OpenGL.
Clicando
aqui, você pode obter os códigos fontes que serão utilizados na aula de
hoje.
Inicialmente,
verifique o conteúdo do programa fonte fornecido para tentar entender o seu
conteúdo.
Depois, compile e
execute o programa que abrirá uma janela com fundo branco e um triângulo,
conforme mostra a próxima figura.
Observe atentamente
o código para entender o seu funcionamento,
considerando a estrutura básica de um programa OpenGL:
·
Criação de uma janela com glutCreateWindow;
·
Criação de um objeto que irá gerenciar os eventos (glutMainLoop);
·
Implementação da classe responsável pelo rendering
e pelo gerenciamento dos eventos de teclado
(no exemplo, Desenha e Teclado);
Agora altere o código
fonte conforme descrito a seguir e, a cada alteração,
execute novamente o programa para verificar os resultados obtidos.
Em caso de dúvida,
consulte a professora ou o tutorial de introdução à OpenGL disponível em
http://www.inf.pucrs.br/~manssour/OpenGL/Tutorial.html.
1. Troque a cor de
fundo da janela, modificando os argumentos da chamada da função glClearColor(0.0f,
0.0f, 0.0f,
2. Desenhe duas linhas
que representem os eixos cartesianos do universo (use glBegin(GL_LINES)
e glEnd(), acrescentando os quatro vértices necessários para o desenho
dos eixos); Considere que as coordenadas mínimas e máximas são,
respectivamente, -1.0 e 1.0. Importante: todas as rotinas de desenho
devem ser chamadas a partir do método display (Desenha);
3. Substitua a chamada
à função glBegin(GL_TRIANGLES);....gl.glEnd(); pelo desenho de um
triângulo e de um quadrado, que devem ser definidos de maneira a formar uma
casinha, como mostra a próxima figura. Os comandos para desenhar o
"telhado" da casinha são apresentados a seguir. Tente desenhar o
resto da casinha usando GL_LINE_LOOP. Observe que quando a cor é trocada de um
vértice para o outro, OpenGL faz um degrade entre as cores.
glLineWidth(3)
// Determina a espessura da
linha que será desenhada
glBegin(GL.GL_TRIANGLES);
glColor3f(0.0f, 0.0f,
glVertex2f(-0.2f,0.1f);
glColor3f(1.0f, 0.0f,
glVertex2f(0.0f,0.22f);
glColor3f(0.0f, 0.0f,
glVertex2f(0.2f,0.1f);
gl.glEnd();
4. Aplique uma
transformação geométrica de translação na casinha para mudá-la de lugar
utilizando o método glTranslatef(float, float, float) (importante: a
translação, bem como as transformações de escala e rotação, deve ser aplicada antes
que a casinha seja desenhada).
Como fazer para interagir com o
programa sem que seja necessário alterar e executar o código cada vez que o
objeto, por exemplo, é trocado de lugar? Neste caso, é necessário gerenciar
eventos do teclado e/ou mouse. Assim como já é feito com a tecla ESC na função
Teclado, vamos tratar o evento de outras teclas para que o usuário possa
interagir com a aplicação.
Declare os seguintes atributos
que deverão ser inicializados, por default, com 0:
float translacaoX, translacaoY;
Agora altere os parâmetros
passados para o método glTranslatef, que é chamado no método display,
para que sejam passados estes atributos, da seguinte maneira:
glTranslatef(translacaoX, translacaoY,
Finalmente, para fazer o
tratamento dos eventos, complemente a implementação do método Teclado de
maneira a permitir transladar o objeto para cima, para baixo, para a esquerda e
para a direita sempre que o usuário pressionar cada uma das teclas de setas
(incremente e decremente as variáveis translacaoX e translacaoY)
Utilize glutSpecialFunc para
as teclas especiais, exemplos: setas, Fs, PageUP, etc... Ao final chame a
função glutPostRedisplay para criar um evento de desenho.
Agora,
pressionando as teclas de setas é possível transladar a casinha, ou seja,
deslocá-la para cima, para baixo, para direita e para esquerda.
Para
implementar as operações de zoom e pan, altere o código fonte
conforme descrito a seguir. O zoom consiste no aumento ou redução do
tamanho da window no sistema de referência do universo. Portanto, para aplicá-lo
basta alterar as coordenadas do método gluOrtho2D
sempre que o usuário, por exemplo, pressionar as teclas Home e End.
Veja nas figuras abaixo um exemplo de zoom in e outro de zoom out.
Para
tanto, altere o código do método Teclado que é responsável por gerenciar
eventos do teclado, acrescentando o tratamento para as teclas GLUT_KEY_HOME
e GLUT_KEY_END.
Em
seguida, declare quatro atributos do tipo double, chamados left, right,
bottom e top, e os inicialize no método inicializa,
conforme mostram os trechos de código abaixo.
private
double left, right, bottom, top;
...
void Inicializa()
{
left = -1.0;
right = 1.0;
bottom = -1.0;
top = 1.0;
...
}
Isso
definirá uma área de trabalho, ou janela de seleção (window) com os limites
-1 até 1, tanto para x como para y.
Agora,
altere a chamada para o método gluOrtho2D para que use estes novos
atributos ao invés de colocar diretamente os valores 1.0 e -1.0, como mostra o
exemplo abaixo.
...
gluOrtho2D (left, right, bottom, top);
...
Em
seguida, complemente a implementação do método keyPressed, de forma que
estes atributos sejam alterados para implementar o zoom-in e o zoom-out
(incremente e decremente os atributos usando valores entre 0.0 e 0.5). Como
cada vez que estes atributos forem alterados deve-se chamar os métodos listados
abaixo, acrescente-os bem no início do método display.
void
Desenha() {
glMatrixMode(GL.GL_PROJECTION);
glLoadIdentity();
gluOrtho2D
(left, right, bottom, top);
glMatrixMode(GL.GL_MODELVIEW);
...
Execute
o programa e verifique o que acontece cada vez que as teclas Home e End
são pressionadas. Observe o efeito visual que ocorre quando essas teclas são
pressionadas muitas vezes e coloque um limite para o incremento e decremento
dos atributos (tente imaginar os valores para esse limite).
Executando
o programa também é possível notar que as linhas que representam os eixos
diminuem e aumentam de tamanho. Entretanto, é interessante que elas sempre
fiquem dentro do limite da janela, de ponta a ponta. Para que isto aconteça,
altere o método desenhaEixos para usar os atributos left, right,
bottom e top no lugar dos valores fixos -1.0 e 1.0.
Para
implementar o pan, que consiste, basicamente, no deslocamento da window
no sistema de referência do universo, o procedimento é semelhante ao zoom,
porém os parâmetros do método glu.gluOrtho2D devem ser alterados de
maneira que a window seja deslocada para cima, para baixo, para esquerda
e para direita. Veja na figura abaixo o resultado de um pan para a
direita.
Para
implementar esta operação, vamos precisar de dois atributos que armazenem este
deslocamento. Estes atributos devem ser declarados e inicializados conforme
ilustram os trechos de código a seguir.
...
private float panX, panY;
...
void
Inicializa()
{
panX = panY = 0;
...
Depois,
altere todas as chamadas do método gluOrtho2D da seguinte maneira:
gluOrtho2D(left+panX,
right+panX, bottom+panY, top+panY);
Agora
basta definir quais teclas irão deslocar a window, ou seja, que irão
alterar os valores destes atributos. Sugestão: use F9 (desloca para a direita),
F10 (para a esquerda), F11 (baixo) e F12 (cima).