Transformações Geométricas em OpenGL
Disciplina: Computação Gráfica
Esta página foi criada a partir do material da profa. Isabel Harb Manssour

O objetivo desta aula é exercitar a aplicação das transformações geométricas, a criação de instâncias e a manipulação da window, ou janela de seleção, para realizar operações de zoom e pan. Para elaboração dos exercícios desta aula é fundamental que a primeira aula prática tenha sido finalizada.


Criando Animações com Transformações Geométricas

Altere o programa elaborado na primeira aula prática de maneira que as chamadas para as funções que desenham o triângulo fiquem em uma função, conforme o exemplo abaixo:

void DesenhaTriangulo(void)
{
// Desenha um triângulo no centro da janela
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0);
glVertex3f( 0.0, 0.5,0);
glVertex3f( 0.5,-0.5,0);
glEnd();
}

void Desenha(void)
{
....

DesenhaTriangulo();
....
}

Teste seu programa.


Defina no 'main' de seu programa uma rotina de tratamento para o evento 'idle'.

    .............
    // Registra a função callback de redesenho da janela de visualização

    glutDisplayFunc(Desenha);
   
    // Registra a função callback para 'idle'

    glutIdleFunc(Desenha);

Insira um comando glRotatef antes de chamara rotina de desenho do triângulo.

    ..............  
    glRotatef(10,0,0,1);
    DesenhaTriangulo();
    ................

Provavelmente com isto a tela de seu programa irá começar a piscar. Para que isto não aconteça devemos usar a técnica de DOUBLE BUFFER que exibe uma tela(buffer) enquanto o OpenGL desenha em outro buffer.
Para tanto, na main, altere a chamada da glutInitDisplayMode(....) para

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);


e na rotina de desenho, remova a chamada da função glFlush() e coloque
     ..........
     glutSwapBuffers();
   


Teste seu programa.

Agora altere seu programa incluindo no inicio da rotina de desenho a chamada da função glLoadIdentity(). Comisto, a cada ciclo de redesenho da tela, o OpenGL reinicia as transformações geométricas e o triângulo não irá mais girar na tela.

Crie uma variável global do tipo GLfloat, da seguinte forma

#include <stdlib.h>
#include <gl\glut.h>

GLfloat angulo=0;



Na rotina de redesenho da tela, coloque um comando de incremento desta variável e troque o primeiro parâmetro da glRotatef pela variável angulo, conforme o exemplo a seguir.

     angulo += 0.1;
    glRotatef(angulo,0,0,1);
    DesenhaTriangulo();



Teste seu programa.

Agora tente alterar o código de forma a obter dois triângulos girando na tela conforme a imagem abaixo.



Para obter um resultado satisfatório, voce terá de utilizar, além da função glTranslatef, para deslocar os triângulos, as funções glPushMatrix() e glPopMatrix().
Veja neste link o resultado esperado.



ZOOM e PAN

Agora implemente as operações de zoom e pan. Como o zoom consiste na alteração das coordenadas da window no sistema de referência do universo, para aplicar o zoom altere as coordenadas da função gluOrtho2D sempre que o usuário pressionar um dos botões do mouse. Portanto, considerando a interação através do mouse, para implementar o zoom é necessário alterar as coordenadas da função gluOrtho2D sempre que o usuário pressionar um dos botões do mouse


Primeiro, registre a função callback para gerenciar eventos do teclado acrestando a seguinte linha de código na função main, antes da chamada para a função Inicializa():
glutMouseFunc(GerenciaMouse);

A função GerenciaMouse deve ter o seguinte formato:

void GerenciaMouse(int button, int state, int x, int y)
{

    switch(button)
    {

        case GLUT_LEFT_BUTTON:      

                                    break;

        case GLUT_MIDDLE_BUTTON:

                                    break;

        case GLUT_RIGHT_BUTTON:

                                    break;

    }
}

Em seguida, declare a variável global win (logo após os includes) e a inicialize-a com 5.0, como mostram os trechos de código abaixo:

#include 
GLfloat win = 5.0;

Agora, na função Inicializa, altere a chamada da função glutOrtho2D para que use a variável win da seguinte maneira:

	// Define a janela de visualização 2D
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // o uso deste comando garante que o zoom
// seja feito de forma absoluta e não relativa
gluOrtho2D(-win, win, -win, win);
glMatrixMode(GL_MODELVIEW);

Atenção: Note que a colocação de um glLoadIdentity() antes do glOrtho2D é obrigatória !!

Em seguida, complete a função  GerenciaMouse. Esta função deve alterar a variável win de maneira a implementar o zoom-in e o zoom-out. Uma sugestão: some ou subtrair 0.1 da varíável win a cada clique de um dos botões.

Um exemplo completo da implementação do zoom está disponível em http://www.inf.pucrs.br/~manssour/OpenGL/Eventos.html. A única diferença é que no exemplo é feito o zoom-in e o zoom-out quando o usuário pressiona as teclas GLUT_KEY_UP e GLUT_KEY_DOWN, ao invés de clicar com o botão do mouse.

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 as coordenadas da função gluOrtho2D devem ser alteradas de maneira que a window seja deslocada para cima, para baixo, para esquerda e para direita. Para implementar esta operação, vamos precisar de duas variáveis globais que armazenem este deslocamento. Estas variáveis devem ser declaradas e inicializadas conforme ilustram os trechos de código a seguir.

#include 
GLfloat win=5.0;
GLfloat panX, panY;

Depois, altere a chamada da função gluOrtho2D da seguinte maneira:

gluOrtho2D (-win+panX, win+panX, -win+panY, win+panY);

Agora basta definir que as teclas que irão deslocar a window, ou seja, que irão alterar os valores das variáveis panX e panY.

FIM.