Após entendermos como desenha na tela, agora vamos pular para "outro nível", nós iremos usar o teclado e o mouse para testar.
O código é grande, mas vocês irão entender o conceito.
- A seta direcional para cima aumenta a velocidade de rotação. Para baixo, diminui.
- Se a seta para o lado esquerdo/direito for apertada, o quadrado muda de direção.
- A barra de espaço altera o tipo de rotação.
- O F11 deixa em tela cheia.
- O Esc fecha a janela, detecta o movimento do mouse, e com o clique (em cima da tela) é impresso a localização, e se clicar também.
Para início de conversa, compilem esse código:
#include <GL/glut.h>
#include <stdio.h>
float angulo = 0.0f,rotX = 1.0,rotY = 0.0f,rotZ = 0.0f,velocidade = 1.00;
void DesenhaNaTela(void)
{
// Clear Color and Depth Buffers
glClear(GL_COLOR_BUFFER_BIT);
// Reset transformations
glLoadIdentity();
gluLookAt( 0.0f, 0.0f, 10.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
glRotatef(angulo, rotX, rotY, rotZ);
// Está colorido, caso queiram apenas uma cor, comente todos os glColor3f e descomente aqui
// glColor3f(0.0, 0.5, 0.9);
glBegin(GL_QUADS);
glColor3f(1,0,0);
glColor3f(1,0,0);
glVertex3f(-1, 1, 0);
glColor3f(1,1,0);
glVertex3f( 1, 1, 0);
glColor3f(0,1,0);
glVertex3f( 1,-1, 0);
glColor3f(0,0,1);
glVertex3f(-1,-1, 0);
glEnd();
angulo+=velocidade;
glutSwapBuffers();
}
void Inicializa (void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Define cor fundo para preto
}
void Teclado(unsigned char key, int x, int y){
if(key == 27) exit(0); // O Programa Fecha Caso o Esc seja apertado ...
if((char)key == ' '){
if(rotX == 1.0f){
rotX = 0.0f;
rotY = 1.0f;
rotZ = 0.0f;
}else if (rotY == 1.0f){
rotX = 0.0f;
rotY = 0.0f;
rotZ = 1.0f;
}else if(rotZ == 1.0f){
rotX = 1.0f;
rotY = 0.0f;
rotZ = 0.0f;
}
}
}
void TeclaEspeciais(int key, int x, int y){
if(key == GLUT_KEY_UP) {
velocidade += 0.05;
printf("Velocidade Rotação : %.2f\n",velocidade);
}
if(key == GLUT_KEY_DOWN) {
velocidade -= 0.05;
printf("Velocidade Rotação : %.2f\n",velocidade);
}
if(key == GLUT_KEY_LEFT)
if(velocidade < 0)velocidade *= -1;
if(key == GLUT_KEY_RIGHT)
if(velocidade > 0)velocidade *= -1;
}
void CliqueMouse(int button, int state, int x, int y){
if(button == GLUT_LEFT_BUTTON){
if(state == GLUT_DOWN){
printf("Clicou com o botão esquerdo na Posição X : %i Y : %i \n",x,y);
}else if (state == GLUT_UP){
printf("Soltou Botão esquerdo\n");
}
}else if(button == GLUT_RIGHT_BUTTON){
if(state == GLUT_DOWN){
printf("Clicou com o botão direito na Posição X : %i Y : %i \n",x,y);
}else if(state == GLUT_UP){
printf("Soltou Botão direito\n");
}
}else if (button == GLUT_MIDDLE_BUTTON){
if(state == GLUT_DOWN){
printf("Clicou com o botão do meio na Posição X : %i Y : %i \n",x,y);
}else if(state == GLUT_UP){
printf("Soltou Botão do meio\n");
}
}
}
void MovimentoMouse (int x,int y) {
printf("Mouse na Posição X : %i Y : %i \n",x,y);
}
void AlteraTamanhoTela(int w, int h) {
// Função é chamada caso a tela tenha tido alterada
if (h == 0)
h = 1;
float proporcao = w * 1.0 / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45.0f, proporcao, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(320,240);
glutInitWindowPosition(100,100);
glutCreateWindow("Manipulação Teclado e Mouse");
glutDisplayFunc(DesenhaNaTela);
glutIdleFunc(DesenhaNaTela);
glutReshapeFunc(AlteraTamanhoTela);
glutMouseFunc(CliqueMouse);
glutPassiveMotionFunc(MovimentoMouse);
glutKeyboardFunc( Teclado );
glutSpecialFunc( TeclaEspeciais);
Inicializa();
glutMainLoop();
}
glLoadIdentity :: reseta todas as transformações e/ou rotações.
gluLookAt :: esse, talvez, seja o maior "medo" de vocês, essa função define onde a câmera será posicionada:
glRotatef :: rotaciona a objeto (nesse caso, o quadrado) em determinada posição (obs.: eu coloquei aqui sem números, pois defini as variáveis e elas irão me ajudar a rotacionar de modo "legal").
Olhem como o OpenGL consegue "misturar" as cores.
Teclado:
- Se o Esc for pressionado, o programa é encerrado. Aqui, eu usei ((char)key) para não ter que trabalhar com os números da tabela ASCII.
- Se o espaço (" ") for pressionado, ele verifica para qual posição alterar.
TeclaEspeciais:
- Se a seta direcional para cima for apertada, a velocidade aumenta.
- Se a seta direcional para baixo for apertada, a velocidade diminui.
- Se a seta para o lado for apertada o quadrado muda de direção.
CliqueMouse:
- Se o botão do mouse for igual ao botão esquerdo, e ele estiver pressionado, imprimirá a posição aonde foi clicado, se for solto, mostrará que foi solto.
Os outros seguem a mesma regra:
MovimentoMouse:
- Esse mostra aonde o mouse passou (a posição).
AlteraTamanhoTela:
- Essa talvez é a mais assustadora: caso o tamanho da tela seja alterado, essa função é chamada.
Se a altura for igual a zero, o tamanho fica igual a 1.
A proporção (proporção da tela) é igual a largura * 1 / pela altura.
glViewport; :: seus parâmetros especificam o canto inferior esquerdo da viewport (x,y) dentro da janela, e a sua largura e altura em pixels (width e height). Em outras palavras, a viewport define a área dentro janela, em coordenadas de tela, que OpenGL pode usar para fazer o desenho.
gluPerspective; :: esta função estabelece os parâmetros da Projeção Perspectiva, atualizando a matriz de projeção perspectiva.
Main:
- glutInitDisplayMode : GLUT_DOUBLE :: eu usei, pois com o single a tela fica piscando freneticamente.
- glutIdleFunc :: essa função permite a atualização constante da tela.
- glutReshapeFunc :: função que passa os argumentos para a "AlteraTamanhoTela".
- glutMouseFunc :: passa os argumentos como qual o botão, o estado (pressionado ou levantado), e a posição "x" e "y".
- glutPassiveMotionFunc :: passa os argumentos da posição do mouse (sem clicar).
- glutKeyboardFunc :: argumentos do teclado (teclas do padrão ASCII).
- glutSpecialFunc :: argumentos das teclas especiais (setas direcionais, home, delete, etc.).
Pronto!
Agora já dá para criar alguns programas mais interessantes.