Programação com OpenGL/Modern OpenGL Tutorial Navegacao

Origem: Wikilivros, livros abertos por um mundo aberto.

Entradas do teclado[editar | editar código-fonte]

  • glutKeyboardFunc
  • glutSpecialFunc
  • glutSpecialUpFunc
  • glutGetModifiers() == GLUT_ACTIVE_SHIFT or GLUT_ACTIVE_CTRL or GLUT_ACTIVE_ALT

Cuidado: a callback GLUT´s special() é chamada repetidamente quando mantemos pressionado.

Sistema de coordenadas[editar | editar código-fonte]

Existem diversas maneiras de posicionar os eixos (X, Y, Z).

A regra da mão direita
  • Z-is-up : Usado pelo Blender, signfica que (X, Y) é o chão, e Z é a altitude
  • Y-is-up : Usando pelo OpenGL, significa que (X,Y) é uma parede, assim Y é a altitude, e Z esta perto ou longe desta parede
  • Mão-direita / Mão-esquerda: O OpenGL e o Blender usam um sistema de coordenadas da mão direita, que você pode representar usando a sua mão direita, com X no polegar, Y é o indicador, e Z é dedo do meio. o sistema de coordenadas com a mão esquerda, é usado pelo DirectX, podendo representar do mesmo jeito usando a mão esquerda.

Usar o Blender Z-is-up no OpenGL pode ser tentador, mas apresenta algumas questões:

  • O arquivo .obj normalmente esta como Y-is-up, exigindo mudanças enquanto ele for carregado(ou enquanto é exportado no Blender)
  • A câmera está em Y-is-up, assim se você usar o Z-is-up, por padrão a camera esta em (0,0,0) e a face abaixo. Isto é bastante confuso quando a camera for roda, pois por exemplos, se nossa camera está olhando o horizonte no eixo Y, e você rodar no eixo Z, para olhar para direita ou esquerda,você realmente vai rodar a vista no eixo Y (barrel roll). quando for transformar a camera, você tem que imaginar que você grava seu vídeo a partir dos pés.
  • Outros motores como o Irrlicht e Ogre também usam o Y-is-up

Por isto vamos ficar com Y-is-up neste livro.

Posicionando a câmera[editar | editar código-fonte]

Não há conceitos pré definidos de câmera no OpenGL. Nos temos de fazer uma implementação que engane.

Nossa técnica é a seguinte: em vez de pensarmos em como mover nossa câmera em um mundo fixo. nós pensaremos em como mover o mundo em torno da nossa câmera.

Por exemplo, movendo a câmera para 3 unidades do eixo X é o mesmo que mover o mundo inteiro para -3 unidades do eixo X. O mesmo para todos os outros eixos e para rotações.

Manteremos isto em mente enquanto trabalhamos com a câmera. o resultado final ficará completamente intuitivo, mas sempre que vamos trabalhar com a câmera, se você esquecer que usamos este truque primeiro, você pode ter uma transformação estranha.

Controle da câmera[editar | editar código-fonte]

Vamos começar nossa implementação intuitiva:

  • Esquerda/Direita rodara no eixo Y da câmera.
  • Cima/Baixo moverá para Frente/Para trás
  • Page_up/Page_down rodara a câmera no eixo X.
/* code here */

Para if para frente/Para trás, vamos usar glm::translate Temos duas formas:

  • glm::translate(transformation_matrix, glm::vec3(dx, dy, dz)): aplicando a transformation_matrix, depois movendo em (dx, dy, dz) expressada no novo sistema de coordenadas.
  • glm::translate(glm::mat4(1), glm::vec3(dx, dy, dz)) * transformation_matrix: aplicando transformation_matrix, depois movendo em (dx, dy, dz) expressado no sistema de coordenadas que está depois da translação.
  • Neste caso a translação da câmera, não esqueça que nosso truque move o mundo inteiro, e não a câmera; por isto o significado acima esta ao contrario da matriz world2camera

Por exemplo, se existir um transformation_matrix rodando nossa câmera em 90º para direita, e depois trasladar sobre o Z:

  • Com a primeira forma você vai movimentar a câmera novamente a esquerda(sobre o eixo Z do mundo),
  • Enquanto da segunda forma você vai movimentar a câmera frontal (sobre o eixo X do mundo).

Esta implementação tem os seguintes problemas ao usar: Quando a câmera estiver rodando para esquerda/direita enquanto é dobrado, não usaremos a rotação do corpo da nossa entidade no dobro do eixo. Em vez disto, vamos usar a rotação apenas sobre nossa cabeça alinhada ao eixo Y. assim vamos movimentar o mundo no eixo Y da coordenada local da câmera:

      glm::vec3 y_axis_world = glm::mat3(transforms[MODE_CAMERA]) * glm::vec3(0.0, 1.0, 0.0);
      transforms[MODE_CAMERA] = glm::rotate(glm::mat4(1.0), -delta_rotY, y_axis_world) * transforms[MODE_CAMERA];

Por ultimo, vamos implmentar strifing:

/* code here */