Aula Prática: Câmera, Projeção
Disciplina: Computação Gráfica
Professora: Isabel Harb Manssour
 

O objetivo desta aula é aprender como trabalhar com a visualização 3D em OpenGL. Para isto, é necessário compreender como são utilizadas as funções de projeção e manipulação da câmera em OpenGL. Será utilizada a API JOGL e a linguagem de programação Java.

Para implementação de aplicações com JOGL na linguagem de programação Java é necessário configurar um projeto para linkar as bibliotecas. Na primeira aula prática já foi explicado como configurar o projeto para o ambiente Eclipse, portanto, basta criar um novo projeto, configurá-lo conforme explicado e incluir os programas fonte que serão usados nesta aula.

Inicialmente, analise o código fonte para entender o que programa faz.

O método glu.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âmentro 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 inclua os comandos abaixo no método keyPressed.

...
switch (e.getKeyCode())
{ 
	case KeyEvent.VK_LEFT:	obsX -=10;
					break;
	case KeyEvent.VK_RIGHT:	obsX +=10;
					break;
	case KeyEvent.VK_UP:	obsY +=10;
					break;
	case KeyEvent.VK_DOWN:	obsY -=10;
					break;
	case KeyEvent.VK_HOME:	obsZ +=10;
					break;
	case KeyEvent.VK_END:	obsZ -=10;
					break;	
	...

Acrescente também os atributos que aparecem abaixo, inicializando-os com os valores especificados no método construtor.

	private double obsX, obsY, obsZ; //acrescente esta linha
	...
	public Renderer()
	{
		...
		obsX=0;
		obsY=0; 
		obsZ=200;
	}

Para que as alterações tenham efeito, no método PosicionaObservador troque a linha de código glu.gluLookAt(0,80,200, 0.0,0.0,0.0, 0.0,1.0,0.0); para glu.gluLookAt(obsX,obsY,obsZ, 0.0,0.0,0.0, 0.0,1.0,0.0);.

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 glu.gluPerspective(angle, fAspect, 0.5, 500) estabelece os parâmetros da Projeção Perspectiva, atualizando a matriz de projeção perpectiva. 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.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 glut.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 z (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 Renderer
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.

 ../../Imagens/emban15.png (1469 bytes)

../../Imagens/E-MAIL.JPG (3237 bytes) Comentários, dúvidas, sugestões, envie um mail para [email protected]

../../Imagens/emban15.png (1469 bytes)

[Homepage CG

Última alteração em 29 de abril de 2010.