# Programação com OpenGL/Modern OpenGL Tutorial 05

Nosso animação do triângulo é divertido, mas vamos aprender agora sobre gráficos em 3D.
Vamos criar um cubo!

## Colocando na 3ª Dimensão

Um cubo são 8 vértices em um espaço 3D (4 pontos na face frontal, 4 pontos na face traseira) Podemos renome o triângulo para cube Também comentaremos sobre as vinculações de fade
Agora vamos escreve as vertices do cubo. Vamos posicionar nosso sistema de coordenadas(X,Y,Z) o melhor possível para imagem. Vamos escrever ele assim para relacionar com o centro do objeto. É mais limpo assim, e ainda permitira rodar o cubo em torno do seu centro depois:
Nota: Aqui, a coordenada Z é no sentido do utilizador. Você pode procurar outras convenções que o Z ficara no topo(altura) como o Blender, mas no OpenGL´s o padrão é Y-is-up(Y é para cima )
Para algo melhor que um massa preta, vamos então definir algumas cores:
Não esqueça do global buffer handles(manipuladores globais do buffer):

## Elementos - Index Buffer Objects (IBO)

Nosso cubo tem 6 faces. Duas faces são compartilhadas com algumas vértices, além disso nossa face como uma combinação de 2 triângulos (assim teremos 12 triângulos)
Por isto vamos introduzir o conceito de elementos: vamos usar o glDrawElements, em vez de glDrawArrays. É preciso um conjunto de indices que farão referencia ao array de vértices. Com glDrawElements, nós podemos especificar qualquer ordem, e até mesmo algumas vértices várias vezes. Vamos guardar estes índices em um Index Buffer Object (IBO).
É melhor especificar todas as faces de modo similar, em modo anti-horário, porque isto será importante para o mapeamento de textura(veremos no próximo tutorial) e luz.(assim um triângulo normal precisam apontar para o caminho certo)
Note que usamos um buffer object denovo, mas com GL_ELEMENT_ARRAY_BUFFER em vez GL_ARRAY_BUFFER.
Nós vamos chamar o OpenGL para desenhar nosso cubo em onDisplay
Nós usamos glGetBufferParameteriv para pegar o tamanho do buffer. deste jeito, nós não precisamos declarar cube_elements

## Ativando profundidade

Agora podemos ver a face frontal do quadrado, mas para ver as outras faces do cubo, precisamos roda-lo. Ainda podemos olhar através da remoção de uma(ou duas) face frontal do triângulo. :)

## Matriz de Model-View-Projection

Até agora, temos trabalhado com as coordenadas de objetos, especificamente sobre o centro do objeto. Para trabalhar com vários objetos e posicionamento no mundo 3D, nós calcularemos uma matriz de transformação que vai:
* Mudança da coordenada do modelo (object) para a coordenado do mundo (model->world)
* Em seguida das coordenadas do mundo para a coordenadas de visualização (câmera) (world->view)
* Depois as coordenadas de visualização para as coordenadas de projeção(2D screen) (view->projection)
Isto também vai cuidar do problema em relação ao aspecto.
O objetivo é calcular a matriz global de transformação. chamado MVP, que vamos aplicar em cada vértice para obter os pontos finais da visualização 2D.
Note que as coordenadas da tela 2D estão no intervalo [-1,1]. Existe um 4º passo non-matrix para converter estes para [0, screen_size], controlado por glViewPort
Nota histórica: O OpenGL 1.x tinha duas matrizes inclusas, acessível através de glMatrixModel(GL_PROJECTION) e glMatrixMode(GL_MODELVIEW). Aqui nós estamos substituindo eles, e estamos colocando uma camera :)
Vamos colocar em nosso código na função onIdle, onde nós atualizamos o uniform fade no tutorial anterior, mas ao invés disto nós passaremos um uniform mvp.
Iniciando: No começo de cada fase, nós temos uma matriz identidade, que não faz nenhuma transformação, criado usando glm::mat4(1.0f).
Modelo(Model): Vamos colocar nosso cubo um pouco em segundo plano, então não misturaremos com a câmera:
Visualização(View): O GLM tem uma ré-implementação do gluLookAt(eye, center, up). O eye é a posição da camera, o center é onde a camera é apontada, e o up é o topo da camera (no caso é inclinado). Vamos centralizar nosso objeto um pouco acima, com a camera reta:
Projeção(Projection): O GLM também possui um re-implementação do gluPerspective(fovy, aspect, zNear, zFar). fovy é o angulo da lente, aspect é o aspecto da tela (largura/altura), zNear e ZFar são os limites da visualização aérea (min/max profundidade), ambos positivo, zNear é um valor pequeno e diferente de zero. Nós precisamos ver nosso quadrado, então usuaremos 10 para zFar.
O screen_width e screen_height serão uma nova variável global que definirá o tamanho da janela:
Resultado:
Poderemos passar ele para o shader:
E no shader:

## Animação

Para animar o objeto, nós poderemos aplicar uma simples transformação antes da matriz do Modelo(Model).
Para rodar o cubo, vamos colocar no onIdle:
Então fizemos uma tradicional cubo com voo rotativo!

## Redimensionando a Janela

Para suportar o redimensionamento de janela do GLUT, você pode usar a função glutReshapeFunc:
Nota: A cena tende a pular quando é redimensionada - Eu não consigui descobrir de onde vem isto.