Exercício IV (2014/1)

Disciplina: Computação Gráfica
Professora: Soraia R. Musse

Pos Doc: Leandro Dihl

 

Aula prática – Movimentação de Objetos 3D

 

O objetivo desta aula é aprender aplicar transformações geométricas em objetos 3D usando OpenGL.

As transformações geométricas são usadas para manipular um modelo, isto é, através delas é possível mover, rotacionar ou alterar a escala de um objeto. A aparência final da cena ou do objeto depende muito da ordem na qual estas transformações são aplicadas.

A biblioteca gráfica OpenGL é capaz de executar transformações de translação, escala e rotação através de uma multiplicação de matrizes. A idéia central destas transformações em OpenGL é que elas podem ser combinadas em uma única matriz, de tal maneira que várias transformações geométricas possam ser aplicadas através de uma única operação.

Isto ocorre porque uma transformação geométrica em OpenGL é armazenada internamente em uma matriz. A cada transformação que é aplicada, esta matriz é alterada e usada para desenhar os objetos a partir daquele momento. A cada nova alteração é feita uma composição de matrizes. Para evitar este efeito "cumulativo", é necessário utilizar as funções glPushMatrix() e glPopMatrix(), que salvam e restauram, respectivamente, a matriz atual em uma pilha interna da OpenGL.

A translação é feita através da função glTranslatef(Tx, Ty, Tz), que pode receber três números float ou double (glTranslated) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de translação baseada nos valores dados.

A rotação é feita através da função glRotatef(Ângulo, x, y, z), que pode receber quatro números float ou double (glRotated) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de rotação de "Ângulo" graus ao redor do eixo definido pelo vetor "x,y,z" no sentido anti-horário.

A escala é feita através da função glScalef(Ex, Ey, Ez), que pode receber três números float ou double (glScaled) como parâmetro. Neste caso, a matriz atual é multiplicada por uma matriz de escala baseada nos valores dados.

Iremos aprender a movimentar um objeto 3D usando as teclas especiais ç e è. Depois utilizaremos um Timer para fazer a animação automática de um objeto 3D.

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. 

MOVIMENTAÇÃO USANDO TECLADO

Primeiro, precisamos definir quais parâmetros iremos variar. Para a esfera da Figura 1 iremos variar a coordenada x.

Figura 1

Para isso, criamos uma variável global X e uma variação delta:

float X = -20;
float delta = 0.4;

Agora, temos que associar X com as teclas especiais ç e è. Com a GLUT, usaremos a função glutSpecialFunc():

Ela tem que ser chamada uma vez no main().

TeclasEspeciais é uma função chamada automaticamente quando as teclas especiais são pressionadas. Ela é a função que vai fazer a variável X variar, Observe no código.

void TeclasEspeciais(int key, int x, int y){

      if(key == GLUT_KEY_LEFT){

            X-=4;

            if(X< -30)

            X = -30;

      }

      if(key == GLUT_KEY_RIGHT){

            X+=4;

        if(X> 30)

            X = 30;

      }

      glutPostRedisplay();

}

 

MOVIMENTAÇÃO USANDO ANIMAÇÃO

Para animar um objeto temos que associar a variável X ao tempo e ao método de transformação do objeto. Com a GLUT, usaremos a função glutTimerFunc:

void glutTimerFunc(unsigned int msecs, void (*func)(int value), value);

Ela tem que ser chamada uma vez no main() para estabelecer qual função timer será usada, como por exemplo:

TimerFunction é uma função chamada automaticamente que definiremos depois. Ela é a função que vai fazer a variável X variar ao longo do tempo.

void TimerFunction( int value ){
  if( X < -10 ) delta = 0.4;
  if( X > 10 ) delta = -0.4;
  X += delta;
  glutPostRedisplay();
  glutTimerFunc( 33, TimerFunction, 1);
}

Neste exemplo usamos a seguinte função de desenho. Perceba que a variável X é usada para transladar a esfera.

void Objetos(void)

{

  // DRAW PLANE

  glPushMatrix();

    glColor3f(0,1,0);

    glTranslatef(-100,0,-100);

    glScalef(200,200,200);

    drawPlane();

  glPopMatrix();

 

  // DRAW SPHERE

  glPushMatrix();

    glColor3f(1,1,0);

    glTranslated( X, 15, 0 );

    glutSolidSphere(30,16,16);

  glPopMatrix();

 

  // DRAW WALLS

  glPushMatrix();

    glColor3f(1,0,0);

    glTranslated( -65, 50, 0 );

    glScalef(0.2,3.0,1.0);

    glutSolidCube(35);

  glPopMatrix();

 

  glPushMatrix();

    glColor3f(1,0,0);

    glTranslated( 65, 50, 0 );

    glScalef(0.2,3.0,1.0);

    glutSolidCube(35);

  glPopMatrix();

  glutSwapBuffers();

}

 

#include <stdlib.h>

Includes

#include <GL/glut.h>

 

#include <stdio.h>

 

 

Variáveis

GLfloat rotX, rotY, rotX_ini, rotY_ini;

 

GLfloat obsX, obsY, obsZ =200, obsX_ini, obsY_ini, obsZ_ini;

 

GLfloat fAspect = 1, angle = 44;

 

int x_ini,y_ini,bot;

 

float X = -30;

 

float delta = 0.4;

 

#define SENS_ROT  5.0

 

#define SENS_OBS  10.0

 

#define SENS_TRANSL     30.0

 

 

 

void PosicionaObservador(void)

Método de

{

posicionamento do

      glMatrixMode(GL_MODELVIEW);

observador

      glLoadIdentity();

 

      glTranslatef(-obsX,-obsY,-obsZ);

 

      glRotatef(rotX,1,0,0);

 

      glRotatef(rotY,0,1,0);

 

      gluLookAt(0.0,40.0,200.0, 0.0,0.0,0.0, 0.0,1.0,0.0);

 

}

 

void drawPlane()//Desenha o plano

Método para o desenho

{

do Plano Verde

  glBegin(GL_POLYGON);

 

    glVertex3f(1,0,1);

 

    glVertex3f(1,0,0);

 

    glVertex3f(0,0,0);

 

    glVertex3f(0,0,1);

 

  glEnd();

 

}

 

 

 

void Objetos(void)

Método para o desenho

{

dos objetos da cena

  // DRAW PLANE

 

  glPushMatrix();

 

    glColor3f(0,1,0);

 

    glTranslatef(-100,0,-100);

 

    glScalef(200,200,200);

 

    drawPlane();

 

  glPopMatrix();

 

 

 

  // DRAW SPHERE

 

  glPushMatrix();

 

    glColor3f(1,1,0);

 

    glTranslated(X, 15, 0 );

Controla a translação

    glutSolidSphere(30,16,16);

da esfera pela variável

  glPopMatrix();

“X”

 

 

  // DRAW WALLS

 

  glPushMatrix();

 

    glColor3f(1,0,0);

 

    glTranslated( -65, 50, 0 );

 

    glScalef(0.2,3.0,1.0);

 

    glutSolidCube(35);

 

  glPopMatrix();

 

 

 

  glPushMatrix();

 

    glColor3f(1,0,0);

 

    glTranslated( 65, 50, 0 );

 

    glScalef(0.2,3.0,1.0);

 

    glutSolidCube(35);

 

  glPopMatrix();

 

 

 

 // glFlush();  // Makes sure that we output the model to the graphics card

 

    glutSwapBuffers();

 

}

 

 

 

void EspecificaParametrosVisualizacao(void)

Método para a

{

especificação dos

      glMatrixMode(GL_PROJECTION);

parâmetros de

      glLoadIdentity();

Visualização

      gluPerspective(angle,fAspect,0.5,500);

 

    PosicionaObservador();

 

}

 

 

 

void Desenha(void)

Método que Desenha a

{

Cena

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

 

    EspecificaParametrosVisualizacao();

 

    Objetos();

 

}

 

 

 

void AlteraTamanhoJanela(GLsizei w, GLsizei h)

 

{

Método para o ajuste da

      // Para previnir uma divisão por zero

Visualização caso o

      if ( h == 0 ) h = 1;

Tamanho da Janela

      // Especifica as dimensões da viewport

seja alterado

      glViewport(0, 0, w, h);

 

      // Calcula a correção de aspecto

 

      fAspect = (GLfloat)w/(GLfloat)h;

 

      EspecificaParametrosVisualizacao();

 

}

 

 

 

void Teclado (unsigned char key, int x, int y)

Método de finalização

{

do programa

      if (key == 27)

 

            exit(0);

 

}

 

 

 

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

Método que gerencia o

{

mouse

      if(state==GLUT_DOWN)

 

      {//salva os parâmetros atuais

 

            x_ini = x;

 

            y_ini = y;

 

            obsX_ini = obsX;

 

            obsY_ini = obsY;

 

            obsZ_ini = obsZ;

 

            rotX_ini = rotX;

 

            rotY_ini = rotY;

 

            bot = button;

 

      }

 

      else bot = -1;

 

}

 

void GerenciaMovim(int x, int y)

Método de configuração

{

dos movimentos do

      if(bot==GLUT_LEFT_BUTTON)

mouse

      {

 

            int deltax = x_ini - x;

 

            int deltay = y_ini - y;

 

            rotY = rotY_ini - deltax/SENS_ROT;

 

            rotX = rotX_ini - deltay/SENS_ROT;

 

      }

 

      else if(bot==GLUT_RIGHT_BUTTON)

 

      {

 

            int deltaz = y_ini - y;

 

            obsZ = obsZ_ini + deltaz/SENS_OBS;

 

      }

 

      else if(bot==GLUT_MIDDLE_BUTTON)

 

      {

 

            int deltax = x_ini - x;

 

            int deltay = y_ini - y;

 

            obsX = obsX_ini + deltax/SENS_TRANSL;

 

            obsY = obsY_ini - deltay/SENS_TRANSL;

 

      }

 

      PosicionaObservador();

 

      glutPostRedisplay();

 

}

 

 

 

void TeclasEspeciais(int key, int x, int y){

Método que controla as

      if(key == GLUT_KEY_LEFT){

teclas especiais

            X-=4;

 

            if(X < -30)

 

            X = -30;

 

      }

 

      if(key == GLUT_KEY_RIGHT){

 

            X+=4;

 

        if(X > 30)

 

            X = 30;

 

      }

 

      glutPostRedisplay();

 

}

 

 

 

void TimerFunction( int value ){

Método que controla o

  if( X < -30 ) delta = 0.4;

Timer

  if( X > 30 ) delta = -0.4;

 

  X += delta;

 

  glutPostRedisplay();

 

  glutTimerFunc( 33, TimerFunction, 1);

 

}

 

 

 

int main(void)

Método principal e de

{

inicialização das

      int argc = 0;

Principais funções

      char *argv[] = { (char *)"gl", 0 };

 

     glutInit(&argc, argv);

 

      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);

 

      glutInitWindowPosition(5,5);

 

      glutInitWindowSize(450,450);

 

      glutCreateWindow("Movimentação 3D");

 

     glutTimerFunc(33, TimerFunction, 1 ); // 33 ms

Inicializa o Timer

      glutDisplayFunc(Desenha);

 

      glutReshapeFunc(AlteraTamanhoJanela);

 

      glutKeyboardFunc (Teclado);

 

      glutSpecialFunc(TeclasEspeciais);

 

      glutMotionFunc(GerenciaMovim);

 

      glutMouseFunc(GerenciaMouse);

 

      glutMainLoop();

 

      return 0;

 

}

 

EXERCÍCIOS:

1) Usando o código acima como modelo desenvolva os seguintes exercícios:

        a) Utilizando as teclas especiais é e ê faça a esfera se deslocar na coordenada Z ;

        b) Utilizando a tecla especial F1 faça com que a movimentação das teclas ç, è, é e ê passe a movimentar outro objeto da cena.

        c) Tente criar uma nova animação movendo outros objetos com outras variáveis;