Programação com OpenGL/Modern OpenGL Tutorial Navegacao
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).
- 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 atransformation_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
: aplicandotransformation_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 */