Transformações geométricas

Capítulo 4. Transformações geométricas – cubos4

O propósito desta lição é compreender como as transformações geométricas são
realizadas sobre os objetos em relação a um determinado sistema de coordenadas.
No OpenGL existem funções para realizar translação, rotação e escalamento,
bastando apenas ao usuário ajustar os seus parâmetros para obter o efeito
desejado. Será analisado um programa simples composto de 4 cubos dispostos em uma janela conforme ilustra a Figura
4-1


O programa que implementa os 4 cubos é mostrado no Exemplo
4-1
. Para finalizar o programa, basta digitar ESC. As teclas e
suas respectivas ações estão definidas na função keyboard().

Exemplo 4-1. programa cubos4.c

#include <GL/glut.h>
#include <stdlib.h>

void init(void){
  glClearColor (0.0, 0.0, 0.0, 0.0);
}

void display(void){
  glClear (GL_COLOR_BUFFER_BIT);
  glPushMatrix();

  /* Cubo 1 */
  glPushMatrix();
  glTranslatef (-2.0, 0.0, 0.0);
  glScalef (3.0, 2.0, 5.0);
  glutWireCube (1.0);
  glPopMatrix();
   
  /* Cubo 2 */
  glPushMatrix();
  glRotatef (25.0, 0.0, 0.0, 1.0);
  glTranslatef (2.0, 0.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();

   /* Cubo 3 */
  glPushMatrix();
  glTranslatef (0.0, 2.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();

     /* Cubo 4 */
  glPushMatrix();
  glTranslatef (0.0, -2.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();

  glPopMatrix();
  glutSwapBuffers();
}

void reshape (int w, int h){
  glViewport (0, 0, (GLsizei) w, (GLsizei) h);
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef (0.0, 0.0, -10.0);
}
void keyboard(unsigned char key, int x, int y){
  switch (key) {
  case 27:                                         // tecla Esc (encerra o programa)
	exit(0);
	break;
  }
}

int main(int argc, char** argv){
  glutInit(&argc, argv);
  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
  glutInitWindowSize (500, 500); 
  glutInitWindowPosition (100, 100);
  glutCreateWindow (argv[0]);
  init ();
  glutDisplayFunc(display); 
  glutReshapeFunc(reshape);
  glutKeyboardFunc(keyboard);
  glutMainLoop();
  return 0;
}

Para compilar e executar o programa cubos4.c, salve-o juntamente com o
arquivo Makefile em um diretório e execute a seguinte seqüência de
comandos:

$ make cubos4
$ ./cubos4

4.1. Descrição do programa cubos4.c

void init(void){
  glClearColor (0.0, 0.0, 0.0, 0.0);
}

Especifica as intensidade de vermelho (RED), verde (GREEN) e azul (BLUE) utilizadas para limpar a janela. Neste caso, a janela terá cor de fundo preta. O último
parâmetro é o canal alfa, utilizado para tratar com transparências.

void display(void)
{
  glClear (GL_COLOR_BUFFER_BIT);
  glPushMatrix();

Uma vez que as transformações geométricas no espaço são representadas por
matrizes, o uso de uma pilha de matrizes de transformação ajuda a lembrar a
seqüência de transformações realizadas. No OpenGL, esta facilidade é provida
pelas funções glPushMatrix(), que insere a matriz de
transformação corrente na pilha, e glPopMatrix(), que
retira a matriz do topo da pilha e torna esta última a matriz de transformação
corrente. Neste exemplo, a função glPushMatrix() serve
para lembrar os parâmetros de translação, rotação e escalamento no início das
operações de desenho.

  
  /* Cubo 1 */
  glPushMatrix();
  glTranslatef (-2.0, 0.0, 0.0);
  glScalef (3.0, 2.0, 5.0);
  glutWireCube (1.0);
  glPopMatrix();

O conjunto de transformações sobre o primeiro cubo a ser desenhado é delimitado pelo
glPushMatrix() e glPopMatrix().
A origem do sistema de coordenadas é levado para o ponto (x,y,z)=(-2.0,0.0,0.0)
através da função glTranslatef(), definindo a coordenada
de origem (pivô) para o desenho do cubo. Em seguida, usando a função glScalef(), o sistema de coordenadas é ampliado em (Sx,Sy,Sz)=(3.0,2.0,5.0),
e, finalmente, desenhado um cubo aramado através de glutWireCube().



  
  /* Cubo 2 */
  glPushMatrix();
  glRotatef (25.0, 0.0, 0.0, 1.0);
  glTranslatef (2.0, 0.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();


A função glRotatef() possui o seguinte protótipo:

void glRotatef(GLfloat angle, GLfloat x,
GLfloat y, GLfloat z);

Quando chamada, glRotatef() efetua uma rotação de angle graus no sistema de coordenadas na direção
contra o sentido do relógio em torno de um vetor que vai da origem ao ponto
(x,y,z)


Observe que os cubos 3 e 4 não são também rotacionados mesmo estando após o uso da função glRotatef()
sobre o cubo 2, em função da delimitação da pilha de execução delimitada por glPushMatrix() e
glPopMatrix().



  
   /* Cubo 3 */
  glPushMatrix();
  glTranslatef (0.0, 2.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();


  
     /* Cubo 4 */
  glPushMatrix();
  glTranslatef (0.0, -2.0, 0.0);
  glScalef (2.0, 1.0, 4.0);
  glutWireCube (1.0);
  glPopMatrix();


Os outros dois cubos são desenhados, segundo às mesmas orientações dadas acima.


  glPopMatrix();
  glutSwapBuffers();

A função glPopMatrix() remove a matriz de
transformação do topo da pilha, fazendo-a corrente, retornando assim o sistema
de coordenadas original. Quando glutSwapBuffers() é
chamada, os buffers de desenho e de apresentação são alternados e a nova imagem
dos cubos é apresentada.

void reshape (int w, int h)
{
  glViewport (0, 0, (GLsizei) w, (GLsizei) h); 

Define a área dentro da janela de desenho no sistema de coordenadas atual,
origem (x,y), largura (w) e altura (h), que OpenGL pode utilizar para efetuar
desenhos. Este trecho de código permite que toda a área da janela possa ser
utilizada quando a janela sofrer redimensionamento.

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluPerspective(65.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);

A função glMatrixMode() especifica a pilha de
matrizes que será o alvo das operações matriciais subseqüentes; neste caso, a
pilha de matrizes de projeção. A função glLoadIdentity()
inicia a matriz de projeção corrente como a matriz identidade. A função gluPerspective() define a transformação de perspectiva usada
no exemplo. Projeções geométricas não são alvo desta lição e por enquanto não
serão estudadas.

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef (0.0, 0.0, -10.0);

A função glMatrixMode() especifica agora que a pilha
de matrizes de modelview, usadas para definir
translação, rotação e escalamento, será o alvo das transformações subseqüentes.
A função glLoadIdentity() inicia a matriz de modelview corrente como a matriz identidade. Finalmente,
o objeto é deslocado em -10 unidades para o fundo da tela, melhorando a sua
visualização.

  glutReshapeFunc(reshape);

Especifica a função de retorno para redimensionamento de janela, possuindo o
seguinte protótipo:

funcao(int width, int height);