Exercício III
Disciplina: Computação Gráfica
Professora: Soraia R. Musse
Aula prática – Câmera e Projeção
O objetivo desta aula é
aprender como trabalhar com a visualização 3D em
OpenGL.
Clicando aqui,
você pode obter os códigos fontes que serão utilizados na aula de hoje.
Inicialmente, verifique o conteúdo do programa fonte
fornecido.
O método gluLookAt(0.0,80.0,200.0, 0.0,0.0,0.0, 0.0,1.0,0.0);
define a câmera, isto é, através dos seus argumentos
é possível indicar a posição da câmera e para onde ela está direcionada.
Sua assinatura é: void gluLookAt(double eyeX, double eyeY,
double eyeZ, double centerX,
double centerY, double centerZ,
double upX, double upY,
double upZ).
Os parâmetros: eyex, eyey e eyez são
usados para definir as coordenadas x, y e z, respectivamente, da posição da
câmera (ou observador);
centerx, centery
e centerz são usados para definir as
coordenadas x, y e z, respectivamente, da posição do alvo, isto é para onde o
observador está
olhando (normalmente, o centro da cena); upx, upy e upz são as
coordenadas x, y e z, que estabelecem o vetor up
(indica o "lado de cima" de uma cena 3D) [Wright 2000].
Agora altere o parâmetro upy
para -1 e veja o que acontece com o teapot.
Depois, atribua o valor 1 para upy novamente.
Em seguida, altere o parâmetro eyez para 100,
compile e visualize o resultado. Depois altere este mesmo parâmetro para 300,
compile e visualize o resultado novamente. Na seqüência,
passe o valor 200 para este parâmetro. Altere o parâmetro centerx
para 20, compile e execute o programa. Agora altere este mesmo parâmetro para
-20, compile e execute o programa.
Considerando as alterações feitas, e a teoria estudada
em aula, pense em que consiste alterar os parâmetros eyex,
eyey, eyez, centerx, centery e centerz.
Agora crie um método TeclasEspeciais
(não esqueça do callback no main)
e inclua os comandos abaixo.
...
switch (key)
{
case GLUT_KEY_LEFT: obsX -=10;
break;
case GLUT_KEY_RIGHT: obsX +=10;
break;
case GLUT_KEY_UP: obsY +=10;
break;
case GLUT_KEY_DOWN: obsY -=10;
break;
case GLUT_KEY_HOME: obsZ +=10;
break;
case GLUT_KEY_END: obsZ -=1;
break;
}
glutPostRedisplay();
...
Para que as alterações tenham efeito, no método PosicionaObservador troque a linha de código gluLookAt(0,80,200,
0.0,0.0,0.0, 0.0,1.0,0.0); para gluLookAt(obsX,obsY,obsZ, 0.0,0.0,0.0, 0.0,1.0,0.0) e não esqueça de
tirar a translação e rotação que está codificada.
Agora compile e execute o programa para verificar que
estas alterações possibilitaram alterar a posição do observador mantendo sempre
o mesmo alvo.
O metodo gluPerspective(angle, fAspect, 0.5,
500) estabelece os parâmetros da Projeção Perspectiva, atualizando a matriz
de projeção perspectiva. Sua
assinatura é: public void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);. Descrição dos parâmetros: fovy é o ângulo, em graus, na direção y (usada para
determinar a "altura" do volume de visualização); aspect
é a razão de aspecto que determina a área de visualização na direção x, e seu
valor é a razão em x (largura) e y (altura); zNear,
que sempre tem que ter um valor positivo maior do que zero, é a distância do
observador até o plano de corte mais próximo (em z); zFar,
que também sempre tem que ter um valor positivo maior do que zero, é a
distância do observador até o plano de corte mais afastado (em z). Este método
sempre deve ser chamado ANTES do método gluLookAt,
e no modo GL_PROJECTION [Wright 2000].
Altere o parâmetro zNear
do método gluPerspective para 0.2 (as vezes
pode haver um problema na iluminação se o valor for muito baixo, tal como 0.1).
Agora coloque 2 no lugar de fAspect, compile e
execute para ver o que acontece. Troque o valor 2 por 0.5, compile e execute
novamente. Coloque novamente a variável fAspect
no segundo parâmetro da gluPerspective. Com
estes testes, foi possível verificar as conseqüências
de alterar a razão de aspecto.
Agora altere o parâmetro zNear
da função gluPerspective para 210, compile e execute
para ver o que acontece. Coloque novamente o valor 0.5 para zNear
e troque o valor de zFar para 200, compile e
execute. Coloque novamente o valor 500 para zFar.
O método glutWireTeapot(35) é usado para desenhar o wire-frame de um teapot
(bule de chá). Sua assinatura é: void glutWireTeapot(double scale), onde o
parâmetro scale indica o fator de escala
aplicado no teapot, o que é usado para definir
o seu tamanho. Assim como o método teapot, a
classe GLUT também possui métodos para desenhar outros objetos 3D. Alguns
métodos estão listados abaixo [Woo 1999]:
- public void glutWireCube(float size);
- public void glutWireSphere(double radius, int slices, int stacks);
- public void glutWireCone(double base, double
height, int slices, int
stacks);
- public void glutWireTorus(double innerRadius, double outerRadius, int nsides, int
rings);
- public void glutWireIcosahedron();
- public void glutWireOctahedron();
- public void glutWireTetrahedron();
- public void glutSolidDodecahedron().
Os parâmetros slices
e stacks que aparecem na assinatura de alguns
métodos significam, respectivamente, o número de subdivisões em torno do
eixo y (como se fossem linhas longitudinais) e o número de subdivisões ao
longo do eixo z (como se fossem linhas latitudinais). Já rings e nsides
correspondem, respectivamente, ao número de seções que serão usadas para formar
o torus, e ao número de subdivisões para cada
seção.
Agora experimente trocar o teapot
pelos objetos cubo, cone, esfera e Octaedro. Coloque diferentes valores nos
parâmetros para ver como fica a imagem final.
Na seqüência, crie e
inicialize os seguintes atributos na classe Desenha
int rings = 6, nsides = 20, slices = 20, stacks = 10.
Depois, acrescente no seu código os comandos necessários para incrementar e
decrementar o valor destas variáveis. Por exemplo, F1 incrementa e F2
decrementa a variável rings, F3
incrementa e F4 decrementa a variável nsides,
e assim por diante.
Inclua no lugar do teapot
um torus. Passe por parâmetro para a função glutWireTorus as variáveis rings
e nsides criadas anteriormente, compile e
execute o programa. Depois altere os valores destas variáveis utilizando as
teclas especificadas anteriormente. Inclua também um cone e altere os valores
das variáveis slices e stacks
para ver o efeito.
Exercício: altere a implementação para
que seja desenhada uma pirâmide formada por uma lista de vértices e uma lista
de arestas no lugar do teapot. Dica: Faça o
desenho usando GL_LINES.