UFPE - Processamento Gráfico

GLUT - Graphics Library Utility Toolkit

Manual de referência online


1. Introdução


GLUT é uma biblioteca de software (API – Application Programmer’s Interface) que possibilita a codificação de programas em OpenGL independentes da plataforma de hardware sendo utilizada. Desta forma um programa escrito utilizando-se OpenGL e GLUT pode potencialmente ser portado e compilado em plataformas diferentes de hardware, como estações de trabalho UNIX, Videogames e PCs. GLUT segue o padrão ANSI C em suas rotinas.


GLUT proporciona uma maneira rápida e eficiente de testar programas escritos em OpenGL. GLUT foi desenvolvido por Mark J. Kilgard da empresa Silicon Graphics inicialmente somente para uso em estações de trabalho UNIX. Posteriormente foram desenvolvidas versões de GLUT para o sistema Windows, Windows NT e OS/2.


Faça o download do manual glut-3.spec.pdf (pdf/404Kb)


2. Histórico


Um dos grandes avanços na especificação da biblioteca gráfica OpenGL foi o isolamento entre as rotinas para processamento gráfico e o sistema de hardware. Anteriormente, as bibliotecas gráficas incorporavam em sua implementação rotinas de baixo nível que por um lado possibilitavam o acesso aos recursos de hardware da máquina, mas ao mesmo tempo tornavam bastante difícil a portabilidade de programas entre plataformas diferentes. GLUT proporciona assim uma "camada" de software que possibilita o acesso aos recursos básicos de hardware necessários como criação de janelas e interação simples com dispositivos de entrada e saída como o mouse e teclado, enquanto que o programa em OpenGL, que constitui a parte maior do código, fica "livre" de dependências de plataforma.


3. Referências


A página Web para GLUT, incluindo o software para download e um manul online encontram-se em:


http://www.opengl.org/resources/libraries/glut/


As principais referências sobre GLUT em conjunto com OpenGL são:


a) OpenGL Programming Guide

A. Woo, J. Neider e T. Davis

Addison-Wesley

Guia oficial da biblioteca gráfica OpenGL. Os exemplos do livro utilizam GLUT para interfaceamento com o sistema.


b) Interactive Computer Graphics: A top-down approach with OpenGL

Edward Angel

Addison-Wesley

Livro texto para ensino básico de computação gráfica. Os conceitos de computação gráfica são ensinados utilizando-se OpenGL como linguagem suporte e GLUT para as interfaces.


c) GLUT para Windows


4. Filosofia de projeto de GLUT


GLUT foi projetada para ser independente, até onde possível, do sistema de janelas nativo de cada plataforma de hardware. Por exemplo, GLUT fornece o seu próprio conjunto de fontes para caracteres. As rotinas em GLUT são bastante simples, com passagem de poucos parâmetros e sem retornar nenhum ponteiro. Os únicos ponteiros recebidos como parâmetros são ponteiros para cadeias de caracteres.


GLUT foi projetada para desenvolvimento de programas de tamanho pequeno e médio escritos em OpenGL. GLUT implementa um gerenciador próprio para controle de eventos e tem um suporte limitado para criação de menus e sub-menus. Não há recursos sofisticados de interface como botões e sliders.


O paradigma de programação em GLUT é orientado a eventos do tipo: o mouse foi clicado; uma tecla foi pressionada e assim por diante. O programador apenas define quais rotinas devem ser chamadas quando um determinado evento acontecer e GLUT segue gerenciando estes eventos num laço de controle infinito.


5. Breve descrição das rotinas


Todas as rotinas em GLUT iniciam com o prefixo glut. As coordenadas de janela e de tela são expressas em pixels. O canto superior esquerdo é a origem do sistema de coordenadas (0,0). As coordenadas x aumentam na direção da esquerda para a direita e as coordenadas y na direção de cima para baixo. Os identificadores em GLUT (identificadores de janela, menus, etc) iniciam em 1 e não em 0. Pare ter acesso as rotinas de GLUT a seguinte diretiva de controle deve ser incluida no código:


#include <GL/glut.h>


A linkagem da biblioteca GLUT com o resto do sistema é obviamente dependente do tipo de máquina em que se está usando a biblioteca. As rotinas em GLUT podem ser agrupadas de acordo com suas funções. Abaixo apresenta-se uma breve descrição destes grupos de rotinas. Observe que esta descrição é extremamente limitada e deve servir apenas como uma referência rápida aos recursos da biblioteca GLUT que não se limitam ao aqui descrito.


5.1) Inicialização

Inicialização do sistema de janelas e criação da(s) janela(s) propriamente dita(s). A principal rotina neste grupo é:

void glutInit( int *argc, char **argc );

Esta rotina é utilizada para inicializar a biblioteca GLUT e recebe como parâmetros as opções de execução via linha de comando (command line options). Ela deve ser chamada ANTES de qualquer rotina GLUT que não seja de inicialização. Outras rotinas neste grupo permitem a especificação da posição da janela na tela (glutInitWindowPosition) e também o tamanho inicial da janela (glutInitWindowSize).


5.2) Processamento de eventos


Existe apenas uma rotina com o protótipo:


void glutMainLoop( void );


Esta rotina deve ser chamada após a inicialização. O controle do programa é entregue a GLUT que passa a monitorar os eventos e chamar as rotinas de callback apropriadas. Este procedimento não retorna nunca.


5.3) Gerenciamento de janelas

GLUT permite a criação de dois tipos básicos de janelas: principal e sub-janelas. Ambos tipos suportam operações em OpenGL e associação de rotinas callback. As principais rotinas são:


int glutCreateWindow( char *name );


Esta rotina cria uma janela principal com o nome recebido como parâmetro. O valor retornado é um inteiro identificador da janela no caso de se trabalhar com várias janelas e houver necessidade de troca de contexto. No caso de mais de uma janela o identificador pode ser utilizado como parâmetro da rotina glutSetWindow que especificará em que janela se deseja trabalhar. Outra rotina importante deste grupo é a rotina que força um evento de exibição da janela, ou seja, sinaliza ao sistema operacional que a janela corrente necessita ser exibida. O protótipo desta rotina é:


void glutPostRedisplay( void );


Esta rotina deve ser chamada toda vez que um evento ocasionar uma mudança no que está sendo exibido na tela e esta mudança precisa ser re-exibida.


5.4) Registro de rotinas callback

Este grupo de rotinas associa aos eventos monitorados por GLUT uma rotina específica para execução. As principais rotinas deste grupo são:


glutDisplayFunc(void (* func) (void));

Registra a rotina para exibição da janela. Não há parâmetros recebidos.


glutReshapeFunc(void (* func)(int largura, int altura));

Registra a rotina para reexibição da janela. Eventos que ocasionam a chamada desta rotina são por exemplo a modificação de tamanho da janela. Esta rotina recebe como parâmetros do sistema operacional as novas dimensões da janela, largura e altura.


glutKeyboardFunc(void(*func)(unsigned char tecla, int x, int y);

Registra a rotina para tratamento de eventos gerados pelo teclado. Os parâmetros recebidos do sistema operacional são a tecla pressionada e a posição em pixels do mouse (x,y) no momento que a tecla foi pressionada. Esta rotina não gerencia teclas denominadas especiais, do tipo F1, F2, Home, etc. Para gerência destas teclas especiais deve-se utilizar a rotina glutSpecialFunc.


glutMouseFunc(void(*func)(int botao, int estado, int x, int y));

Registra a rotina para tratamento de eventos originados pelo clique do mouse. Os parâmetros recebidos são: botao, que assume um dos 3 valores GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON e GLUT_RIGHT_BUTTON, dependendo se a tecla pressionada foi respectivamente a tecla esquerda, do meio ou direita; estado indica se o evento foi originado devido ao pressionamento ou liberamento do mouse assumindo um de 2 valores GLUT_UP ou GLUT_DOWN; (x,y) indicam a posição do mouse no momento que o clique foi efetuado.


5.5) Objetos pré-definidos


Este grupo de rotinas permite a exibição de objetos geométricos pré-definidos em modo sólido ou aramado, Os objetos principais são: esfera (glutSolidSphere ,glutWireSphere); cubo (glutSolidCube, glutWireCube); cone (glutSolidCone, glutWireCone); torus (glutSolidTorus, glutWireTorus); bule de chá, o famoso bule de chá de Utah (glutSolidTeapot, glutWireTeapot).


6) Exemplo de um programa utilizando GLUT e OpenGL


Abaixo encontra-se um exemplo de um programa simples (apenas conceitos de Computação Gráfica bidimensional) utilizando GLUT e OpenGL. Este programa desenha um quadrado na tela. O clique do botão esquerdo do mouse causa uma mudança de cor aleatória do quadrado. O programa encerra pressionando-se a tecla Q.


/*

*--------------------------------------------------

* exSimples.c

* UFPE

* Autor: Prof. Marcelo Walter

* Data: Jan 15, 1999

* Ultima modificacao: Nov 6, 2006

*

* Este programa introduz os principais

* conceitos de programacao 2D com GLUT e

* OpenGL. Este programa desenha um quadrado

* aproximadamente centrado no meio da tela

* A cor do quadrado muda aleatoriamente

* ao pressionar-se o botao esquerdo do mouse

*--------------------------------------------------

*/


/*

*--------------------------------------------------

* Includes

*--------------------------------------------------

*/


#include <stdio.h>

#include <GL/glut.h>


/*

*--------------------------------------------------

* Prototipos para as funcoes globais

*--------------------------------------------------

*/

void exibeCB( void );

void tecladoCB( unsigned char tecla, int x, int y );

void redesenhaCB( int w, int h );

void inic( void );

void mouseCB( int botao, int estado, int x, int y );


/*

*--------------------------------------------------

* Funcao principal

*--------------------------------------------------

*/

int main( int argc, char *argv[] )

{

glutInit( &argc, argv );

glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE );

inic();

glutMainLoop();

return 1;

}


/*

*--------------------------------------------------

* Esta funcao inicializa a janela OpenGL, registra

* as rotinas de callback e inicializa as matrizes

* do OpenGL

*--------------------------------------------------

*/

void inic( void )

{

glutInitWindowPosition( 200, 100 );

glutCreateWindow( "Exemplo Simples 1" );


/* Registra as rotinas de CallBack */

glutDisplayFunc( exibeCB );

glutKeyboardFunc( tecladoCB );

glutReshapeFunc( redesenhaCB );

glutMouseFunc( mouseCB );


/* Cor default fundo preta */

glClearColor( 0, 0, 0, 0 );

glMatrixMode( GL_MODELVIEW );

glLoadIdentity();


glMatrixMode( GL_PROJECTION );

glLoadIdentity();


/* Limpa buffer de cor */

glClear( GL_COLOR_BUFFER_BIT );


/* Cor default para objetos. Vermelho */

glColor3f( 1.0, 0.0, 0.0 );

}


/*

*----------------------------------------------------------

* Rotina para tratamento de eventos relacionados ao mouse

*

* botao: Botao que foi pressionado. Um de 3 valores

* GLUT_LEFT_BUTTON, GLUT_RIGHT_BUTTON, GLUT_MIDDLE_BUTTON

*

* estado: Se o mouse foi clicado ou solto

* GLUT_UP ou GLUT_DOWN

*

* x,y: posicao do mouse dentro da janela

*----------------------------------------------------------

*/

void mouseCB( int botao, int estado, int x, int y )

{

if ( botao == GLUT_LEFT_BUTTON )

glColor3ub( (char) rand()%256, (char) rand()%256, (char) rand()%256);

glutPostRedisplay();

}


/*

*----------------------------------------------------------

* Rotina para tratamento de evento - Exibicao da janela

*----------------------------------------------------------

*/

void exibeCB( void )

{

glMatrixMode( GL_MODELVIEW );

glBegin(GL_POLYGON);

glVertex2i( 200, 200 );

glVertex2i( 200, 150 );

glVertex2i( 150, 150 );

glVertex2i( 150, 200 );

glEnd();

glFlush();

}


/*

*--------------------------------------------------

* Rotina para tratamento de evento - Teclado

*

* tecla: Tecla pressionada pelo usuario

* x - posicao x do mouse

* y - posicao y do mouse

*

*--------------------------------------------------

*/

void tecladoCB( unsigned char tecla, int x, int y )

{

switch( tecla ) {

case 'q': /* Encerra o programa */

case 'Q':

exit( 0 );

default:

printf("Opcao nao definida!\n");

}

}


/*

*--------------------------------------------------

* Rotina para tratamento de evento

* Alteracao de tamanho da janela

* w - largura corrente da janela

* h - altura corrente da janela

*--------------------------------------------------

*/

void redesenhaCB( int w, int h )

{

glViewport( 0, 0, w, h );

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho( 0, (GLfloat) w, 0, (GLfloat) h , -1.0, 1.0 );

}


7. Exercícios


Se você executar o exemplo acima, observará algumas situações que poderiam ser melhoradas. Pense nos problemas abaixo e como você acha que os resolveria utilizando as rotinas de GLUT.


7.1 Caso você tente redimensionar a janela, observará que o fundo da tela não será "limpo" e que a posição do quadrado é variável dentro da janela. Porque ocorrem estas duas situações? Como corrigi-las?


7.2 Tente desenhar outros objetos, ao invés de um quadrado um triângulo por exemplo.


7.3 Vamos supor que você queira mudar interativamente a posição onde o quadrado é desenhado via teclado, ou seja, suponha que pressionando-se determinada tecla o quadrado deva mover-se 20 pixels acima e à direita da posição corrente. Como você faria isto?


7.4 O clique do mouse na verdade causa 2 mudanças de cor em seguida, muito rápidas. Porque isto acontece? Como você mudaria o código acima para a cor do quadrado mudar somente uma vez quando o mouse é pressionado?