Versão 0.3 - Eventos de teclado e Texturas

Eventos de teclado - Navegação

     Foi elaborado um sistema para navegação através do cenário do jogo, permitindo ao jogador ajustar a câmera, movendo-a para cima, para baixo, direita, esquerda, frente, trás ou rotacionando.
     Para realizar tais movimentos utilizamos a função gluLookAt do GLUT. Nela definimos a posição da câmera, o centro de referência e a direção do view up vector.

gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx, GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy, GLdouble upz);

     A biblioteca Camera.h recebe variáveis geradas a partir de eventos de teclado e transforma em parâmetros do gluLookAt.
     As teclas ‘a’, ‘d’, ‘w’, ‘s’ movem a câmera para a esquerda, direita, frente e trás, respectivamente. ‘q’ e ‘e’ fazem movimentos de subir e descer a câmera e ‘4’ e ‘6’ rotacionam a câmera no sentido horário e anti-horário e 'l' e 'L' apagam e acendem a fonte de luz da sala.

void keyboard(unsigned char k, int x, int y)
{
  switch (k) {
	  case 'w':
            cam->moveFront(); //move para frente
            break;
        case 's':
            cam->moveBack(); //move para trás
            break;
        case 'q': // sobe a camera
            cam->moveUp();
            break;
        case 'e': //desce a camera
            cam->moveDown();
            break;
        case 'a': //move para a esquerda
            cam->moveLeft();
            break;
        case 'd': // move para direita
            cam->moveRight();
            break;
		case 'm': //inclina o taco p/ direita
            move_taco(0,0,-0.45);
            break;
		case 'n': //inclina o taco p/ esquerda
            move_taco(0,0,0.45);
            break;
		case 'b': //gira o taco rapidamente
            move_taco(0,0,45);
            break;
        case '6': //camera p/ esquerda
            cam->Yaw(CAM_LEFT);
            break;
        case '4': //camera p/ direita
            cam->Yaw(CAM_RIGHT); 
            break;
		case 'l': //apaga a luz
			luzes(0);
			break;
        case 'L':
			luzes(1); //acende a luz
			break;
  }
  glutPostRedisplay();
}

//... em Camera.cpp  
void Camera::Yaw(double ang)
{
    double dx,dy,dz;
    double t;
    double fx, fy, fz;
    t = (ang * M_PI * 2) / 360;
    dx = - camera.x;
    dy = - camera.y;
    dz = - camera.z;
    
    foco.x += dx;
    foco.y += dy;
    foco.z += dz;    
    
    fx = foco.x;
    fy = foco.y;
    fz = foco.z;
   
    // faz a rotacao em x
    if (nzero(view.x))
    {
        foco.y = cos(t)*fy + (-sin(t))*fz; // 0
        foco.z = sin(t)*fy + cos(t)*fz; // -2.5
        fx = foco.x;
        fy = foco.y;
        fz = foco.z;
    }    
    
    // faz a rotacao em y
    if (nzero(view.y))
    {
        foco.x = cos(t)*fx + sin(t)*fz; // 0
        foco.z = cos(t)*fz -sin(t)*fx; // -2.5 
        fx = foco.x;
        fy = foco.y;
        fz = foco.z;
    }
    
    // faz a rotacao em z
    if (nzero(view.z))
    {
        foco.x = cos(t)*fx + (-sin(t))*fy; // 0
        foco.y = sin(t)*fx + cos(t)*fy; // 0
    }
    
    foco.x -= dx;
    foco.y -= dy;
    foco.z -= dz;
}
void Camera::moveUp(){
    camera.y+=PASSO;
    foco.y+=PASSO;
}

void Camera::moveDown(){
    camera.y-=PASSO;
    foco.y-=PASSO;
}

void Camera::moveFront(){
    camera.z+=PASSO;
    foco.z+=PASSO;
}

void Camera::moveBack(){
    camera.z-=PASSO;
    foco.z-=PASSO;
} 

void Camera::moveLeft(){
    camera.x+=PASSO;
    foco.x+=PASSO;
}

void Camera::moveRight(){
    camera.x-=PASSO;
    foco.x-=PASSO;
}

void Camera::AtualizarPosicao()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, 1, 0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); 
    gluLookAt(camera.x, camera.y, camera.z,
                foco.x,   foco.y,   foco.z,
                view.x,   view.y,   view.z);
}

Eventos de teclado - Interatividade

     Além de definir os movimentos de câmera, os eventos de teclado também definiram o movimento do taco em cima da mesa. As setas do teclado movimentam o taco para frente e para trás e as teclas ‘m’ e ‘n’ rotacionam o taco no sentido horário e anti-horário ao redor de um ponto fixo. ‘b’ rotaciona o taco em um ângulo maior de 45°.

void special(int k, int x, int y)
{
 
	switch(k) 
    {
        case GLUT_KEY_LEFT: 
			move_taco(0.5,0,0);
			break;
        case GLUT_KEY_RIGHT: 
			move_taco(-0.5,0,0);
			break;
        case GLUT_KEY_UP: 
			move_taco(0,0.5,0);
			break;
        case GLUT_KEY_DOWN: 
			move_taco(0,-0.5,0);
			break;
  }
  glutPostRedisplay();
}
void move_taco(float x, float y, float ang)
{
	cout<<"Taco..." << x << "  " << y << " \n";
   frente = frente + y;
   lado = lado + x;
   angulo = angulo + ang;
}

//Na função Display:
void display(void)
{
.
.
.
glRotatef( angulo,0.0,1.0,0.0);
glTranslatef(lado, 0.0, frente);  
glCallList(lista_taco);
glutSwapBuffers();
}

Textura

     As texturas foram inseridas na cena a fim de deixar os objetos menos artificiais, simulando elementos como carpete no tampo da mesa de sinuca, madeira na base, mármore na mesa de canto, tecido no sofá, papel de parede etc.

 //Função para carregar textura
void carregar_texturas(GLuint id, char *NomeArquivo)
{

IMAGE *img;
GLenum gluerr;
glGenTextures(1, &textura[id]);
glBindTexture(GL_TEXTURE_2D, textura[id]);
  
if(!(img=ImageLoad(NomeArquivo))) 
    {
    MessageBox(NULL,"Falha ao encontrar texturas.","Erro Fatal",
MB_OK|MB_ICONERROR); 
    exit(-1); 
    }

gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 3, img->sizeX, img->sizeY, 
GL_RGB,GL_UNSIGNED_BYTE, (GLvoid *)(img->data));
			   
if(gluerr)
    {
    MessageBox(NULL,"Falha ao criar mipmaps.","Erro Fatal",MB_OK|
MB_ICONERROR ); 
    exit(-1);
    }

glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
// Faz interpolação vizinho mais próximo
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST );
// GL_DECAL faz a composição da textura com iluminação
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); 
}

     A função utilizada para carrega a textura utiliza a biblioteca image.h que carrega texturas no formato ‘.sgi’ ou ‘.rgb’, formatos suportados pelo OpenGL. Contudo, as imagens de texturas utilizadas neste trabalho estavam no formato JPEG, assim o programa Gimp foi utilizado para converter e editar as texturas.
     As figuras de 5 à 8 mostram o resultado do projeto após inserido os modelos de textura.

Figura 5. Cena do jogo


Figura 6. Cena do jogo


Figura 7. Cena do jogo


Figura 8. Cena do jogo (luz apagada)

      Clique aqui para baixar o código completo do projeto. Foi utilizado o microsoft visual C++ 2008 com a biblioteca do GLUT para compilar o programa.