# Programação com OpenGL/Modern OpenGL Tutorial Navegacao
## Entradas do teclado

* 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

Existem diversas maneiras de posicionar os eixos (X, Y, Z).
* 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

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

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.
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:
Por ultimo, vamos implmentar strifing: