• Nenhum resultado encontrado

OpenGL na Computação Gráfica

N/A
N/A
Protected

Academic year: 2019

Share "OpenGL na Computação Gráfica"

Copied!
30
0
0

Texto

(1)

OpenGL na Computação Gráfica

(2)

Capítulo I

Iniciando a programação com OpenGL

w w w w w w

Programação inicial com OpenGL

Ingredientes básicos de todo programa OpenGL Primitivas geométricas

OpenGL como Máquina de Estados OpenGL orientada a eventos

Controlando programas com Mouse e Teclado

(3)

Este estudo visa ajudar na compreensão da Computação Gráfica utilizando OpenGL, uma das APIs gráficas mais poderosas e mais usadas no mundo. Ao longo dele serão apresentados os principais conceitos de Computação Gráfica e as principais funções OpenGL em diversos programas exemplos que auxiliarão muito aquele que estudar por esse material.

Antes de programar utilizando OpenGL é preciso saber de algumas de suas características mais significativas, cada uma delas será vista em detalhes nos exemplos mostrados no decorrer do estudo:

w

w

w

w

w

w

w

w

w

OpenGL é uma API (Interface de Programação de Aplicação) gráfica

Isso significa que OpenGL trabalha entre o Software e o Hardware, simplificando os cálculos necessários para as transformações vetoriais e matriciais.

Outras APIs e bibliotecas são associadas à OpenGL:

A GLU (OpenGL Utility Library) faz parte do padrão OpenGL. Contém utilitários que permitem a construção de curvas, trianguladores, quádricas. É construída sobre a OpenGL.

A GLUT (OpenGL Utility Toolkit) é uma API portátil de acesso ao sistema de janelas. Não é parte oficial do OpenGL. É construída sobre a GLU.

A GLUI é uma API para a construção de interfaces gráficas, faz com que a interação entre o usuário e o aplicativo seja mais simples com a construção de janelas, menus, botões, etc. É construída sobre a GLUT.

OpenGL é uma Máquina de Estados.

Algumas funções do OpenGL guardam flags necessárias às configurações do programa como as características de cor de fundo de tela, configurações de janelas e outras habilitações ao programa, veremos isso também em muitos programas colocados como exemplo.

OpenGL é orientada a eventos.

O programa escrito utilizando a OpenGl permanece em loop até que algum evento aconteça. Na especificação dos eventos está mencionada a função Callback que será chamada toda a vez que o evento a ela relacionado acontecer. O programa só se encerra se o evento correspondente ao final da execução for ativado.

Callback

Callbacks são rotinas que serão chamadas para tratar eventos. Para que uma rotina callback seja efetivamente chamada deve ser registrada através da função:

glutXxxFunc (callback)

Onde Xxx designa uma classe de eventos e callback é o nome da rotina.

Exemplo

Para registrar uma callback de desenho chamada Desenho usamos:

glutDisplayFunc (Desenho)

OpenGL é independente da Plataforma e do Sistema de Janelas.

(4)

funções não mudam e um código escrito para um compilador de uma plataforma UNIX, por exemplo, compila tranquilamente em um do Windows e vice-versa.

De posse dessas informações podemos começar a tratar dos principais conceitos para a programação com OpenGL.

Ingredientes Básicos Necessários a todo programa OpenGL

1- Sistema de Coordenadas (2D)

O sistema de Coordenadas de uma aplicação OpenGL tem origem no canto inferior esquerdo da tela (em relação ao observador). Assim os valores de y crescem à medida que o ponto se aproxima do topo da tela, e os valores de x crescem à medida que o ponto se aproxima da lateral direita da tela (Figura 1).

Figura 1

2- Configurações iniciais da janela

Para desenhar utilizando um programa OpenGL é necessário uma janela de visualização. As configurações da janela ou das janelas de visualização são feitas na função main( ).

Um exemplo de função main () tratando as configurações de janela segue abaixo:

#include <stdlib.h> #include <GL/glut.h>

(5)

}

void main (int argc, char** argv) {

glutInit (&argc, argv); // inicializa a glut

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // especifica modo de desenho glutInitWindowSize (640, 480); // tamanho da janela

glutInitWindowPosition (100, 150); // posicao da janela na tela glutCreateWindow (argv[0]); // cria a janela

glutDisplayFunc (desenho);

glutMainLoop (); // inicia o Loop infinito do programa }

glutInit (&argc, argv) – Esta função inicializa a GLUT. Esses argumentos passados poderão ser passados como parâmetros para o programa, como foi feito com o parâmetro argv, que representa o nome da janela, conforme especificado pela função glutCreateWindow ()

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB) – Essa função especifica como o desenho será inicializado. A constante GLUT_SINGLE indica que será utilizado apenas um buffer para alocar a imagem – ou seja, o desenho será construído diretamente na tela -, e diz que a imagem será feita utilizando o padrão de cores RGB (vermelho, verde e azul) para colorir.

glutInitWindowSize (640, 480) – Esta função especifica qual o tamanho inicial da janela. No caso são 640 pixels de largura por 480 pixels de altura. Quando o programa está rodando, o usuário pode redimensionar a janela, se prererir.

glutInitWindowPosition (100, 150) – Esta função especifica que a janela posicionada a uma distância de 100 pixels do limite esquerdo da tela e a 150 pixels do limite superior da tela.

glutCreateWindow (argv[0]) – Esta função abre uma janela de visualização de acordo com as configurações especificadas nas funções acima. Esta janela terá como nome o parâmetro passado para esta função, no caso a entrada de dados na chamada do executável de acordo com o parâmetro argv[0].

glutDisplayFunc (Desenho) – Esta é uma função callback necessária para a execução de qualquer programa que utilize a biblioteca glut (a partir da versão 3.0). Explicaremos melhor as funções callbacks no próximo exemplo.

glutMainLoop () - Esta função é responsável por manter o programa em loop até que seja chamado algum evento que determine o fim da aplicação. Essa função caracteriza a especificação de OpenGL como uma API orientada a eventos, o que será tratado no próximo ponto de estudo.

O código acima irá abrir uma janela sem conteúdo algum. Para todos os programas feitos usando OpenGL esse código será utilizado.

3- Orientação a Eventos

Como foi dito, a OpenGL é orientada a eventos e trata eventos de Mouse, de Teclado ou de Alterações da Janela de Visualização. A especificação dos eventos e seus callbacks ficam no

(6)

glutXxxFunc().

Um exemplo de função main () que abre uma janela e se prepara para tratar os diversos eventos segue abaixo:

#include <stdio.h> #include <GL/glut.h>

void main () {

---ABRINDO UMA JANELA DE VISUALIZAÇÃO ---

glutInit (&argc, argv); // inicializa a glut

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); // especifica modo de desenho glutInitWindowSize (640, 480); // tamanho da janela

glutInitPosition (100, 150); // posicao da janela na tela glutCreateWindow (“nome da janela”); // cria a janela

---ESPECIFICANDO AS FUNÇÕES CALLBACKS --- glutDisplayFunc (Desenho); // registro de função de desenho

glutReshapeFunc (Reshape); // registro de função de Atualização de janela glutMouseFunc (Mouse); // registro de função de mouse

glutKeyboard (Teclado); // registro de função de teclado glutMainLoop (); // inicia o Loop infinito do programa

}

glutDisplayFunc (Desenho) - Sempre que o sistema determinar que uma janela deve ser redesenhada na tela, isso significa um evento de atualização de desenho. Neste exemplo a função Desenho( ) é registrada como a função de atualização de desenho e chamada sempre que é preciso redesenhar uma cena.

glutReshapeFunc (Reshape) – O tamanho da janela de visualização pode ser alterado com o mouse por exemplo. Neste exemplo a função Reshape( ) é registrada como um evento de atualização de tamanho de janela. A função Reshape, como veremos adiante, está passando parâmetros automaticamente para que sejam atualizados a largura e a altura da janela.

glutMouseFunc (Mouse) – Quando um botão do mouse é pressionado ou solto, um evento de mouse é acionado. Neste exemplo a função Mouse( ) é registrada como uma função para ser chamada quando ocorrer eventos de Mouse. A função Mouse ( ) recebe argumentos que identificam posição do cursor e a natureza da ação iniciada no Mouse ( ).

glutKeyboardFunc (Teclado) – Este comando chama a função Teclado quando uma tecla do teclado é pressionada ou solta. Os argumentos da função Teclado ( ) possuem argumentos que indicam que tecla foi pressionada além da posição do cursor naquele instante.

Como as funções callbacks não foram ainda declaradas, o código acima não realizará função alguma, mas estará preparado para receber o código das funções callbacks especificadas como parâmetros e realizar aquilo a que se propõem. Abaixo falaremos sobre como a OpenGL trata a plotagem de gráficos.

4- Desenhando primitivas

(7)

Todos os desenhos produzidos pela OpenGL são gerados por primitivas geométricas básicas. Pontos, retas, sequência de retas, polígonos e outras primitivas são combinadas de forma que geram todas as figuras que veremos ao longo de nosso estudo.

Para especificar qual a primitiva utilizada no desenho é preciso passá-la como parâmetro para a função de estado glBegin ( ). Tudo o que estiver entre o glBegin( ) e o glEnd( ) será desenhado utilizando a primitiva passada.

Ex:

glBegin (GL_POINTS);

Desenho ( ):

glEnd ( );

No código acima, a função Desenho vai desenhar tudo aquilo por ela especificado utilizando pontos, que é a primitiva passada como parâmetro para a glBegin ( ).

As funções que estabelecem o que será desenhado ficam na função callback de desenho. São muitas as funções de desenho da OpenGL, citaremos aqui as mais utilizadas, suas vantagens e onde e como podem ser usadas.

Antes porém, é preciso identificar um padrão seguido por todas as funções do OpenGL. Para facilitar o entendimento e a utilização das funções, a OpenGL segue o seguinte padrão:

{gl library} {comando básico} {número de argumentos} {tipo dos argumentos}

gl library indica a biblioteca à que a função pertence

comando básico é o radical da função, a função em si

número de argumentos é a quantidade de parâmetros passados para a função

tipo de argumento é o tipo dos argumentos passados para a função

No caso, a primeira função que nós aprenderemos é a Vertex, uma função que recebe as

coordenadas de um ponto como parâmetros. Cada função Vertex estabelece que o ponto recebido como parâmetro é um vértice de uma figura. Se a função for chamada em sequência, ligará os vértices utilizando a primitiva especificada, se apenas uma Vertex for chamada, será desenhada apenas uma primitiva. Utilizando o padrão OpenGL se quisermos uma função Vertex que receba um ponto com 2 coordenadas inteiras teremos: glVertex2i (param1, param2).

glVertex2i(...)

tipo de argumentos númeo de

argumentos comando

básico Biblioteca

gl

(8)

Sufixo Tamanho de dados Tipo de dado no C++ Nome na OpenGL

b inteiro 8-bits signed char Glbyte

s inteiro 16-bits short Glshort

i inteiro 32-bits int or long Glint, Glsizei f floating points 32 bits float Glfloat, Glclampf d floating points 64 bits double Gldouble, Glclampd ub unsigned 8-bits unsigned char Glubyte, Glboolean us unsigned 16-bits unsigned short Glushert

ui unsigned 32 bits unsigned int or unsigned long Gluint, enum, bitfield

Um exemplo de problema que a OpenGL evita com essa característica seria se determinada função espera como parâmetro um inteiro de 32 bits, mas o sistema considera inteiro com 16 bits. Dessa forma o exemplo número 1, abaixo, estaria errado, pois passa como parâmetros para a função um inteiro 16 bits, enquanto o exemplo número 2 estaria correto pois passa o argumento com a tipagem característica da OpenGL que no exemplo é o Glint (inteiro de 32 bits.).

Exemplo 1:

void desenha_ponto (int x, int y) // ERRADO {

// desenha um ponto no ponto (x, y) glBegin (GL_POINTS);

glVertex (x, y); glEnd ( );

}

Exemplo 2:

void desenha_ponto (GLint x, GLint y) // CORRETO {

// desenha um ponto no ponto (x, y) glBegin (GL_POINTS);

glVertex (x, y); glEnd ( );

}

As primitivas utilizadas pela OpenGL são as seguintes:

GL_POINTS Desenha pontos independentes

GL_LINE Desenha uma linha entre dois pontos passados

GL_LINE_STRIP Desenha uma sequência de linhas

GL_LINE_LOOP Desenha uma sequência de linhas que retorna à origem

GL_QUADS Desenha quadriláteros independentes a cada 4 pontos chamados.

GL_QUAD_STRIP Desenha uma sequência de quadriláteros ligados. Dois pontos de um quadriláteros formam intersecção com outros dois pontos de outro quadrilátero. Para n quadriláteros são necessários 2*(n+1) pontos.

(9)

GL_TRIANGLE_STRIPS Desenha triângulos conectados com origens diferentes.

GL_TRIANGLE_FAN Desenha triângulos conectados com origem comum, são necessários 3n –1 pontos.

GL_POLYGON Desenha um polígono convexo

Utilizaremos o exemplo a seguir para falar sobre alguns conceitos importantes na programação com OpenGL.

#include <stdlib.h> #include <GL/glut.h>

/*---minha funcao init ( ) ---*/

void init (void) {

glClearColor (1.0, 1.0, 1.0, 0.0); glPointSize (4.0);

glMatrixMode (GL_PROJECTION); glLoadIdentity ( );

gluOrtho2D (-50.0, 50.0, -100.0, 100.0); }

/*---minha funcao desenho ( ) ---*/

void desenho(void) {

glClear (GL_COLOR_BUFFER_BIT); glBegin (GL_POINTS);

glVertex2i (40, 80); glVertex2i (40, 30); glVertex2i (-20.0, 30); glEnd ( );

glFlush ( ); }

/*---main ---*/

(10)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (640, 480);

glutInitWindowPosition (100, 100);

glutCreateWindow ("Meu primeiro programa"); glutDisplayFunc (desenho);

init ( );

glutMainLoop ( ); }

O programa acima desenha 3 pontos em uma janela de visualização. Na função callback desenha ( ) vemos a utilização da função vertex ( ) utilizando o parâmetro GL_POINTS em 3 pontos distintos. A cor de fundo de tela é especificada na função init ( ), que além do fundo de tela guarda funções com as configurações iniciais do programa tais como tamanho do ponto a ser usado nos desenhos, dimensões do world window (cujo significado será conhecido no próximo capítulo), cor do ponto a ser desenhado, etc.

Abaixo teremos uma explicação sobre as novas funções e os novos conceitos da programação com OpenGL encontrados nesse código .

5- OpenGl como uma Máquina de Estados

A OpenGL, como foi dito anteriormente é uma Máquina de Estados. O programa fica em Loop lendo determinadas variáveis e esperando pela ativação de alguma das funções Callbacks que indicarão alterações a serem feitas no valor das variáveis de estado do programa. Abaixo teremos algumas dessas variáveis de estado e o papel de cada uma em um programa feito com OpenGL.

glColor3f (red, green, blue) – A função, com prefixo gl e recebendo 3 parâmetros do tipo float no exemplo, ativa a variável de estado que define a cor do próximo objeto a ser

desenhado. Pode representar o preenchimento da primitiva usada na função Callback de Desenho ( no caso dessa primitiva ser do tipo POLYGON ou QUAD ou TRIANGLE), ou ainda representar a cor de contorno de figuras produzidas com as primitivas linha ou ponto. Uma curiosidade é que a variável de estado funciona como uma função e recebe como parâmetros valores de componentes de cor vermelha, verde e azul, que combinadas formarão 256 cores diferentes. Para se conseguir tons de cinza (variando do preto ao branco) utilizamos os valores das constantes r (vermelho), g (verde) e b (azul) iguais (variando de 0 a 1) em valores decimais ou de 0 a 255 em valores inteiros. Neste exemplo foi estabelecido um tom de cor para cada vértice do triângulo desenhado. Como resultado tivemos a formação de um degradê na linha da figura, esse é um artifício legal a ser usado com a função glColor.

glClearColor (red, green, blue, alpha) – A variável de estado ClearColor, com prefixo gl, indica a cor do fundo da tela. Recebe como parâmetros as componentes r, g e b das cores, assim como na variável glcolor, e ainda recebe a componente alpha que é responsável pela transparência – estudaremos a questão de transparência melhor quando estudarmos iluminação, por enquanto utilizaremos a constante alpha com valor 0.0.

6- Outras funções OpenGL

(11)

estabelecer o modo de inicialização de outros buffers a serem utilizados, como por exemplo o

Depth Buffer.

glPointSize (int) – Esta é uma função que define o tamanho da primitiva a ser usada. Caso não seja especificado esse tamanho, o valor default é 1. No nosso exemplo a função especifica o tamanho, em pixels, dos pontos.

glFlush () - Como não são utilizadas outras funções callback além da função desenho (), foi preciso usar a função glFlush (); que será responsável por garantir que nada deixou de ser feito no programa, que todos os desenhos foram corretamente feitos, ou seja, que o buffer de cores foi corretamente “esvaziado”. Adiante veremos que quando outras funções callback que trarão o efeito de animação começarem a ser utilizadas o glFlush não terá tanta utilidade.

7- Estabelecendo o Sistema de Coordenadas

Usaremos para estabelecer o Sistema de Coordenadas Iniciais de nossos programas algumas funções e variáveis de estado que estarão na função init ( ) que é uma função de auxílio às

configurações iniciais do programa OpenGL. Nesta função estarão os dados que indicarão também como serão feitas as transformações durante o decorrer do programa. Falaremos de Transformações mais tarde, mas desde já é preciso saber que para qualquer transformação a OpenGL utiliza-se de Matrizes de Transformação e a especificação inicial dessas matrizes de Transformação pode ser feita na função init ( ) de nossos programas, como feito anteriormente.

Na função init ( ) estaremos também estabelecendo os limites do “mundo” criado em nossos programas. A computação Gráfica nos permite brincar de Criadores de pequenos mundos, mas é preciso estabelecer os limites de nosso mundo. Isso será feito utilizando a função glortho2D no exemplo acima tivemos:

void init ( ) {

glMatrixMode ( GL_PROJECTION); glLoadIdentity ( );

glOrtho2f ( -50.0, 50.0, -100.0, 100.0); }

A função Ortho acima é da biblioteca gl. O sufixo 2D não se refere à quantidade e ao tipo de parâmetros como em outras funções, mas sim ao espaço dimensional do “mundo” a ser criado. Neste caso iremos trabalhar em 2 Dimensões. (3D se fosse 3 dimensões). Esta função tem como parâmetros pontos com coordenadas x, y – por isso recebe 4 valores. Esses pontos indicam os limites do mundo a ser trabalhado, nesse caso o ponto mais à direita é o ponto -50.0, o mais à esquerda é o ponto 50.0, o ponto mais abaixo é o ponto -100.0 e o ponto mais acima é o ponto 100.0. Isso quer dizer que eu só posso trabalhar com valores de -50 a 50 na largura da tela e de -100 a 100 na altura, mas não significa que todo o meu mundo estará sendo mostrado na tela. A parte que aparece na tela é definida por outra função, a função de Viewport que veremos no próximo capítulo. Por enquanto estamos definindo apenas os limites em que podemos trabalhar. A variável de estado MatrixMode define o tipo de matriz de transformação que será usado, mas falaremos disso mais tarde, quando falarmos de animação, como já foi dito.

Por enquanto você pode brincar com o código dado, pode alterar a posição do desenho a fim de observar o que acontece com a imagem quando esta é definida fora dos limites de seu mundo. Como no exemplo anterior ao modificarmos a função desenho para:

(12)

void desenho(void) {

glClear (GL_COLOR_BUFFER_BIT); glBegin (GL_LINE_LOOP);

glColor3f (1.0, 0.0, 0.0);

glVertex2i (40, 130);

glColor3f (0.0, 1.0, 0.0);

glVertex2i (40, 30);

glColor3f (0.0, 0.0, 1.0);

glVertex2i (-20.0, 30);

glEnd ( ); glFlush ( ); }

Nas linhas em negrito no código acima foi verificada uma modificação em relação ao código visto anteriormente: o ponto a ser desenhado foi estabelecido fora dos limites do mundo definido pela função glOrtho. Como resultado vimos que o desenho foi cortado no ponto limite (y = 100) não sendo obtido o triângulo esperado. Esse conceito de “dimensão de mundo” será estudado com mais detalhes no capítulo 2 deste tutorial.

8- Eventos de Mouse e Teclado

Já temos conhecimento de todas as configurações necessárias para começarmos a programar com OpenGL. Fizemos nosso primeiro programa utilizando OpenGL e plotamos 3 pontos na janela de visualização. Sabemos que OpenGL é Orientada a Eventos de mouse Teclado e alteração de janela, e sabemos como especificar as funções callbacks responsáveis por gerenciar esses eventos.

Entretanto, não sabemos ainda como utilizar esses eventos de mouse e teclado, o que podemos controlar e como podemos controlar. Teremos abaixo um exemplo de programa utilizando eventos de mouse e teclado. É um exemplo simples, mas podemos adiantar que é possível o controle de eventos mais complexos e até de uma combinação de eventos utilizando o recurso das flags

(variáveis de controle que guardam o estado atual de trabalho, podem guardar as opções escolhidas durante a execução do programa e a depender da sequência das opções realizar diferentes funções). Agora iremos direto ao exemplo para depois comentarmos os diferentes conceitos e funções

desconhecidos:

O exemplo abaixo desenha três pontos na tela, como em um anterior, mas tem seu desenho modificado a depender da ocorrência de eventos durante a execução do programa. Se for apertada alguma tecla com representação em ASCII é chamada a função teclado( ), se for alguma tecla sem representação em ASCII é chamada a função especiais ( ) e se for apertado o mouse será chamada a função mouse. Todas elas têm a mesma função simples de fechar a janela de visualização, mas cada um pode implementar qualquer outra alteração no programa a partir desses eventos.

#include <stdlib.h> #include <GL/glut.h>

int x1=-30, y1=-60, x2=30, y2=-60, x3=0, y3=60;

/*---minha funcao init ( ) ---*/ void init (void)

{

glClearColor (0.0, 0.0, 0.0, 0.0); glMatrixMode (GL_PROJECTION);

glLoadIdentity ( );

(13)

/*---minha funcao desenho ( ) ---*/ void desenho (void)

{

glClear (GL_COLOR_BUFFER_BIT); glBegin (GL_LINE_LOOP);

glColor3f (1.0, 1.0, 1.0); glVertex2i (x1, y1);

glVertex2i (x2, y2); glVertex2i (x3, y3);

glEnd ();

glFlush (); }

/*---minhas funções de mouse ( ) ---*/ void mouse (int button, int state, int x, int y)

{

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {

exit (0); } }

/*---minhas funções teclado ( ) ---*/ void teclado (unsigned char key, int x, int y)

{

switch (key)

{

case 27:

exit (0);

break; case '+': x1+=05; y1+=05; x2+=05; y2+=05; break;

case '-':

x1-=05; y1-=05; x2-=05; y2-=05; break; } glutPostRedisplay(); }

void especiais (int key, int x, int y) {

switch (key)

{

case GLUT_KEY_F4:

exit (0);

break; }

}

/*---main ---*/ int main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (640, 480);

glutInitWindowPosition (100, 100);

glutCreateWindow ("Para fechar a janela: Bt Direito do Mouse ou F4 | Mover pontos: '+' ou '-' ");

(14)

init ( );

glutMainLoop ( ); }

Baseado no código acima comentaremos agora cada nova função e conceito utilizados, da mesma forma que fizemos anteriormente.

GlutMouseFunc (mouse) – Essa função chama a função mouse ( ) como função callback que vai realizar todas as ações referentes aos eventos de clique no mouse. A função mouse recebe como parâmetros o botão acionado, o estado do botão, a posição do cursor no momento em que se acionou o botão. É possível trabalhar com o botão (GLUT_LEFT, GLUT_RIGHT,

GLUT_MIDLE) e com o estado (GLUT_DOWN, GLUT_UP)

GlutKeyboardFunc (teclado) – Essa função chama a função teclado ( ) sempre que uma tecla for apertada, identifica a tecla pelo código ASCII. Recebe como parâmetros o código ASCII da tecla em questão e a posição do cursor no momento em que a tecla for pressionada.

GlutSpecialFunc (especiais) – Essa função chama a função especiais ( ) sempre que uma tecla "especial" for apertada, identifica a tecla por representações especiais da OpenGL. As teclas às quais a referência é feita através desta função são:

GLUT_KEY_F1função para tecla F1

GLUT_KEY_F2 função para tecla F2

GLUT_KEY_F3 função para tecla F3

GLUT_KEY_F4 função para tecla F4

GLUT_KEY_F5 função para tecla F5

GLUT_KEY_F6 função para tecla F6

GLUT_KEY_F7 F7 função para tecla F7

GLUT_KEY_F8 F8 função para tecla F8

GLUT_KEY_F9 F9 função para tecla F9

GLUT_KEY_F10 F10 função para tecla F10

GLUT_KEY_F11 F11 função para tecla F11

GLUT_KEY_F12 F12 função para tecla F12

GLUT_KEY_LEFT função para direcional à esquerda

GLUT_KEY_UP Up função para direcional acima

GLUT_KEY_RIGHT função para direcional à direita

GLUT_KEY_DOWN função para direcional abaixo

GLUT_KEY_PAGE_UP função para tecla Page up

GLUT_KEY_PAGE_DOWN função para tecla Page down

GLUT_KEY_HOME função para tecla Home

GLUT_KEY_END função para tecla End

GLUT_KEY_INSERT função para a tecla Insert

(15)

Capítulo II

Trabalhando com Janelas

w w w w

Introdução ao conceito de Viewport Transformações em Viewport World Window X Viewport

(16)

1- Introdução

No capítulo anterior, todos os nossos desenhos eram feitos usando o sistema de coordenadas da tela: Divisão da janela de visualização em pixels, variando de 0 ao valor estabelecido como largura para a janela no eixo x e de 0 ao valor estabelecido como altura para a janela no eixo y. Dessa forma só é possível utilizar de valores positivos para representar aquilo que se deseja desenhar na tela, assim sendo são necessários valores muito altos para as coordenadas x e y se quisermos obter um

desenho de tamanho razoável. Esses limites estabelecidos são chamados de limites de world window ou limites do mundo virtual criado pelo programador.

Como solução para esse problema, entretanto, nós podemos não pensar em termos de pixels, mas sim em termos de variação das coordenadas x e y no universo dos reais (negativos, positivos, decimais). Dessa forma, é claro, teremos que encontrar uma relação entre as dimensões da figura no mundo virtual e as dimensões mostradas na tela para o usuário.

Para entender melhor o que foi dito no parágrafo anterior é preciso conhecer os conceitos de world window e de Viewport. World window é conhecido como o retângulo cujas dimensões representa os limites que definem o mundo do programador. O programa só poderá atuar nas dimensões estabelecidas por esses limites. Nada poderá ser desenhado fora das posições especificadas como limites de mundo, o que não quer dizer que tudo o que for desenhado dentro desses limites será visualizado ao mesmo tempo na tela. Para isso existe o conceito de Viewport que é a função que define a porção do mundo virtual que será visualizado. Define o que será mostrado na janela de visualização, e essa definição é feita em relação aos limites do mundo virtual.

A figura abaixo representa melhor essa definição:

(17)

Conhecendo os conceitos de Viewport e de World Window, precisamos agora de um bom exemplo que ilustre esses conceitos e possa introduzir o tratamento dado a eles pela OpenGL.

O programa abaixo desenha um triângulo na janela e altera as especificações do world window e do viewport a partir de eventos de mouse e teclado. Com o mouse o usuário determina se quer alterar parâmetros da função de world window (botão esquerdo) ou de viewport (botão direito) e com o teclado determina se quer alterar altura (tecla ‘a’|’A’) ou largura (‘l’|’L’) e ainda se quer aumentar (‘+’)ou dimiuir (‘-‘) o valor desses parâmetros. Com esse programa o usuário poderá entender melhor o significado de cada conceito estudado e o que cada um modifica em um programa.

#include <stdio.h> #include <stdlib.h> #include <gl/glut.h>

#define LARG 300 #define ALTU 300

//<<<<<<<<<<<<<<<<<<<<<<<< prototipos e variaveis >>>>>>>>>>>>>>>>>>>

GLint Larg = LARG; GLint Alt = ALTU;

// variaveis do viewport GLint Base_vis=0;

GLint Esq_vis=0; GLint Larg_vis = LARG; GLint Alt_vis = ALTU; // variaveis do WorldView GLint Base_mundo=0; GLint Esq_mundo=0; GLint Larg_mundo = LARG; GLint Alt_mundo = ALTU;

GLint flag_mundo = 0; GLint flag_vis = 0; GLint altura; GLint largura;

void init (void);

void teclado (unsigned char key, int x, int y); void mouse (int button, int state, int x, int y); void desenho (void);

void reshape (GLint Larg, GLint Alt);

//<<<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>> int main(int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (Larg, Alt);

glutInitWindowPosition (0, 0);

glutCreateWindow ("Estudando a Janela"); glutDisplayFunc (desenho);

glutMouseFunc (mouse); init ();

glutReshapeFunc( reshape );

glutKeyboardFunc(teclado); glutMainLoop ();

return (0);

}

//<<<<<<<<<<<<<<<<<<<<<<< init >>>>>>>>>>>>>>>>>>>> void init(void)

{

glClearColor(1.0,1.0,1.0,0.0); }

//<<<<<<<<<<<<<<<<<<<<<<<< desenho >>>>>>>>>>>>>>>>> void desenho(void)

{

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D(Esq_mundo, Larg_mundo, Base_mundo , Alt_mundo); glViewport (Esq_vis,Base_vis, Larg_vis, Alt_vis);

(18)

glColor3f(0,0,1); glVertex2i(0, 0); glColor3f(0,1,0); glVertex2i(0, ALTU); glColor3f(1,0,0); glVertex2i(LARG, ALTU/2); glEnd(); glFlush(); }

//<<<<<<<<<<<<<<<<<<<<<< Reshape >>>>>>>>>>>>>>>>>>>

void reshape (GLint x, GLint y) {

Larg_vis=x;Alt_vis=y;

glViewport (0, 0, Larg_vis, Alt_vis);

}

//<<<<<<<<<<<<<<<<<<<<<<< mouse >>>>>>>>>>>>>>>>>>>> void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: flag_mundo=0; flag_vis=1;

if (state == GLUT_DOWN ) {

printf ("viewport ligado\n");

printf ("world window desligado\n"); }

break; case GLUT_RIGHT_BUTTON:

flag_mundo=1; flag_vis=0;

if ( state == GLUT_DOWN ) {

printf ("world window ligado\n"); printf ("viewport desligado\n"); }

break; } }

//<<<<<<<<<<<<<<<<<<<<<<< teclado >>>>>>>>>>>>>>>>>>>> void teclado (unsigned char key, int x, int y)

{ switch (key) { case '+': if (flag_mundo) { if (altura) {

if ( (Alt_mundo - 10) > 0 ) {

Alt_mundo+=10; }

}

if (largura)

{

if ( (Alt_mundo - 10) > 0 ) {

Larg_mundo+=10; }

}

}

else if (flag_vis)

{

if (altura) {

if ( (Alt_vis - 10) > 0 ) { Alt_vis+=10; } } if (largura) {

(19)

{ Larg_vis+=10; } } } break; case '-': if (flag_mundo) { if (altura) {

if ( Alt_mundo > 10 ) { Alt_mundo-=10; } } if (largura) {

if ( Larg_mundo > 10 ) {

Larg_mundo-=10; }

} }

else if (flag_vis) { if (altura) { Alt_vis-=10; } if (largura) { Larg_vis-=10; } } break; case 'a'|'A': altura= !altura; if (altura)

printf ("altura ligada\n"); else

printf ("altura desligada\n"); break;

case 'l'|'L':

largura= !largura; if (largura)

printf ("largura ligada\n"); else

printf ("largura desligada\n"); break;

case 27:

exit (0);

break; }

printf ("Altura Mundo = %d Largura Mundo = %d \nAltura Viewport = %d Largura Viewport = %d \n", Alt_mundo, Larg_mundo, Alt_vis, Larg_vis); glutPostRedisplay ();

}

Agora iremos explicar o que aconteceu no exemplo acima... o que há de novo em termos de funções e conceitos de Computação Gráfica.

Já são conhecidas muitas funções de configuração do programa, além das funções responsáveis por chamar as callbacks e manter a orientação a eventos da OpenGL. No nosso exemplo acima temos que:

(20)

glutMouseFunc (mouse) – A função callback de mouse é a função mouse. Nesse exemplo a função possui tarefas para dois eventos:

Quando é pressionado o botão esquerdo do mouse (button = GLUT_LEFT_BUTTON && state = GLUT_DOWN) é acionada uma flag (variável que guarda um estado, simula uma variável booleana, já que C não possui tipo booleano) chamada flag_vis.

Quando é pressionado o botão direito do mouse ( button = GLUT_RIGHT_BUTTON && state = GLUT_DOWN ) é acionada uma flag chamada flag_mundo.

Essas flags serão usadas em outras funções, como na função callback de teclado, da qual falaremos a seguir.

glutKeyboardFunc (teclado) – A função callback de eventos de teclado é a função teclado. Nesse caso vimos que essa função está respondendo a 5 teclas diferentes:

Quando é apertada a tecla 'a' minúscula ou maiúscula, é acionada uma flag chamada altura.

Quando é apertada a tecla 'l' minúscula ou maiúscula, é acionada uma flag chamada largura.

Quando é apertada a tecla '+' a função callback irá avaliar todas as flags já comentadas (altura, largura, flag_vis, flag_mundo) e irá incrementar a altura ou largura correspondente ao world window ou ao viewport, de acordo com as flags especificadas.

Quando é apertada a tecla '-' a função callback irá avaliar todas as flags já comentadas (altura, largura, flag_vis, flag_mundo) e irá decrementar a altura ou largura correspondente ao world window ou ao viewport, da mesma forma que quando é apertada a tecla '+'.

Esse exemplo retrata bem a Orientação a Eventos da OpenGL, além de mostrar as diferenças entre World Window e Viewport. O usuário verá o que acontece quando se altera cada uma dessas variáveis.

glutReshapeFunc (reshape) – A função Reshape não havia sido apresentada. É uma função responsável por tratar os eventos de alteração de janela. Se o usuário mover a janela, ou alterar o seu tamanho é preciso uma função que garanta que o desenho irá acompanhar as transformações ocorridas com a janela, seja alterando suas dimensões ou simplesmente a posição em que é desenhado na tela.

No nosso caso, a função Reshape recebeu apenas a Viewport:

glViewport (x, y, largura, altura)- Especifica a janela de visualização, diz o retângulo observado pelo usuário. Os parâmetros definem as dimensões do novo retângulo de viewport em relação ao retângulo atual, onde:

x, y - Especifica o canto esquerdo inferior do retângulo de Viewport, em pixels.

largura, altura - Especificam a largura e a altura, respectivamente, do retângulo de Viewport. Quando as dimensões da janela são alteradas, essas variáveis são atualizadas automaticamente.

(21)

desenho da tela e as dimensões da mesma, mas também simular um zoom na imagem.

(22)

Capítulo III

w w w

Desenvolvendo ferramentas para transformar uma figura em outra.

(23)

Vimos como trabalhar com OpenGL. Já conseguimos desenhar gráficos simples em 2D, mas na computação Gráfica os programas raramente são estáticos. Os desenhos não são feitos para se admirar, mas para serem manipulados, estudados.

Assim como na álgebra se usa de transformações lineares para modificar gráficos, também na computação gráfica esses tipos de transformações são usados para dinamizar os programas.

Transformações de Translação, Rotação e de Escala da figura obtida são as mais comuns. Além das transformações lineares citadas há as transformações de câmera - que não modificam o objeto desenhado, mas permitem modificar o ângulo e posição de visão da cena desenhada entre outras coisas, manipulando a câmera.

Transformações

Na álgebra as transformações lineares podem ser representadas por matrizes que representam a transformação geométrica desejada: Rotação, Escala, Cizalhamento .... Também em programas que utilizam OpenGL são usadas matrizes para guardar as transformações realizadas sobre objetos ou sobre a câmera, mas vamos nos ater às transformações sobre o objeto por enquanto, transformações estas que incluem ainda a Translação, que não é Transformação Linear porque sua aplicação sobre a origem não retorna a origem. Essas matrizes são chamadas de Matrizes de Transformação. Elas guardam a posição do objeto em determinado instante e tornam possível serem realizadas transformações sobre transformações.

No exemplo abaixo vemos um exemplo de transformações, nele utilizamos as funções glRotate e glTranslate que internamente são tratadas pela OpenGL como matrizes. No caso desse exemplo temos um cubo que gira e se move a partir de comandos do teclado.

#include <stdlib.h> #include <GL/glut.h>

//<<<<<<<<<<<<<<<<<< Variáveis Globais>>>>>>>>>>>>>>>>>> int rotaciona=1, translada=0, escala=0;

int largura, altura;

float angle=0, t_x=0, t_y=0,e_x=1,e_y=1;

//<<<<<<<<<<<<<<<<<<<< Protótipos >>>>>>>>>>>>>>>>>>>>>>> void teclado (int key, int x, int y);

void reshape (int largura, int altura); void desenho (void);

void init(void);

//<<<<<<<<<<<<<<<<<<<< Main >>>>>>>>>>>>>>>>>>>>>>> int main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (300, 300);

glutInitWindowPosition (10, 10); glutCreateWindow ("Transformações"); glutDisplayFunc (desenho);

glutKeyboardFunc (teclado); glutReshapeFunc (reshape); init ();

glutMainLoop (); return (0); }

void init(void) {

glClearColor(1.0,1.0,1.0,0.0);

glMatrixMode(GL_PROJECTION); glLoadIdentity();

gluOrtho2D(-100, 100, -50, 50); }

(24)

{

glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity();

glTranslatef (t_x, t_y,0); glRotatef (angle, 0, 0, 1); glScalef (e_x, e_y, 1);

glBegin(GL_POLYGON);

glColor3f(0,0,1); glVertex2i(0, 0); glColor3f(0,1,0); glVertex2i(0, 20); glColor3f(1,0,0); glVertex2i(30, 10); glEnd();

glFlush(); }

//<<<<<<<<<<<<<<<<<<<< Teclado >>>>>>>>>>>>>>>>>>>>>>> void teclado (unsigned char key, int x, int y)

{

if (translada)

{

switch (key) {

case '+':

t_x+=10; break;

case '-':

t_x-=10; break; } } if (rotaciona) {

switch (key) {

case '+':

angle+=10; break;

case '-':

angle-=10; break; } } if (escala) { switch (key) { case '+': e_x+=1; break;

case '-':

e_x-=1; break; } } switch (key) { case 't'|'T':

translada = !translada;

break; case 'r'|'R':

rotaciona = !rotaciona; break;

case 'e'|'E': escala = !escala; break;

}

printf("Translada=%c\n",translada?'V':'F'); printf("Rotaciona=%c\n",rotaciona?'V':'F');

printf("Escala =%c\n",escala?'V':'F'); printf("X=%f\n",t_x); printf("Angulo=%f\n",angle); printf("Escala=%f\n\n",e_x); glutPostRedisplay();

}

//<<<<<<<<<<<<<<<<<<<< Reshape >>>>>>>>>>>>>>>>>>>> void reshape (int largura, int altura)

(25)

glViewport (0, 0, largura, altura); }

Iremos agora falar das novidades do programa, das novas funções e dos novos conceitos. É preciso treinar, e por isso preferimos colocar um exemplo mais geral e comentar pouco a pouco as

novidades.

No exemplo dado, trabalhamos com 3 coordenadas (x, y, z) mas representamos apenas 2 Dimensões pois mantivemos a coordenada z com valor fixo.

GlTranslate (t_x, t_y, t_z) – Para transladar um sistema é preciso multiplicar todos os pontos do sistema de coordenadas por uma matriz de translação. A função GLTranslate cria uma matriz de translação a partir dos parâmetros tx, ty, tz . As constantes t_x, t_y, t_z serão os valores a serem somados às respectivas coordenadas x, y e z.

GlRotate (angle, r_x, r_y, r_z) – Para rotacionar um sistema de coordenadas é preciso multiplicar as coordenadas atuais por uma matriz de rotação. A função GLRotate cria uma matriz de rotação a partir dos parâmetros angle ( que indica o ângulo de rotação ), r_x, r_y e r_z (que descrevem as coordenadas de um vetor que definirá o eixo de rotação). No exemplo trabalhado os valores das coordenadas do eixo de rotação foram 0,0,1, o que significa que o sistema vai girar em torno do eixo z, que é o eixo perpendicular ao plano da tela.

GlScale (e_x, e_y, e_z) – Para escalonar um sistema de coordenadas é preciso

multiplicar cada coordenada de um objeto por um fator de escala. Através dos parâmetros e_x, e_y, e_z, que representam os fatores de escala relativos a cada eixo coordenado, a função GLScale realiza essa transformação .

GlLoadIdentity – A função GLLoadIdentity carrega a matriz identidade na matriz de transformações no Pipeline do OpenGL. O conceito de Pipeline será visto em uma futura lição.

GlMatrixMode () – Todas as transformações acima são feitas sobre o objeto, é importante especificar que as transformações podem ser sobre os objetos e sobre a câmera. O que vai determinar que tipo de transformação será realizada é a função GLMatrixMode. Para que as

transformações sejam realizadas sobre o objeto (sistema de coordenadas) o parâmetro dessa função deve ser GL_MODELVIEW e para que sejam efetuadas sobre a câmera o parâmetro deve ser

(26)

Capítulo IV

• Transformações de Câmera

• Conceitos de Visualização

• Conceitos de Visualização 3D

• Conceitos de Câmera

(27)

Vimos no capítulo anterior como manipular as imagens através de transformações diretas no objeto desenhado. Mas as manipulações de cena podem ser feitas sob o ponto de vista do observador sem que seja alterado o objeto desenhado. Essas manipulações são possíveis através das transformações de câmera da OpenGL.

Assim como nas transformações do objeto, nas transformações de câmera é necessária a utilização de Matrizes de Transformação, que agora deixam de ser do tipo GL_ModelView e passam a ser do tipo GL_Projection. Elas guardam a posição da câmera, o ângulo do campo de visão do observador e outros parâmetros que podem modificar o modo como se vê a cena, se alterados.

Entre outras coisas, será possível “viajar” pela imagem gerada com a modificação da posição da câmera de observação, será possível observar a imagem em seus mínimos detalhes através do efeito de zoom obtido com a diminuição do ângulo do volume de visão do observador.

No exemplo abaixo vemos como trabalhar com câmeras em OpenGL é simples. Utilizamos nele as funções gluPerspective e gluLookAt. Essas duas funções apenas permitem inúmeras transformações como será observado no exemplo:

#include <stdlib.h> #include <GL/glut.h>

//<<<<<<<<<<<<<<<<<< Variáveis Globais>>>>>>>>>>>>>>>>>> int projecao =1;//inicializa como perspective

float graus=60.0; float Aspecto=1.0; float Zmin=0.01; float Zmax=1000.0; float Xmin=-150; float Xmax=150.0; float Ymin=-100; float Ymax=100.0; float CamX=0; float CamY=60; float CamZ=200; float FocoX=0; float FocoY=0; float FocoZ=0; float NormalX=0; float NormalY=1; float NormalZ=0;

//<<<<<<<<<<<<<<<<<<<< Protótipos >>>>>>>>>>>>>>>>>>>>>>> void teclado (unsigned char key, int x, int y);

void desenha (void); void init(void);

//<<<<<<<<<<<<<<<<<<<< Main >>>>>>>>>>>>>>>>>>>>>>> int main (int argc, char** argv)

{

glutInit (&argc, argv);

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB| GLUT_DEPTH); glutInitWindowSize (600,400 );

glutInitWindowPosition (0, 0); glutCreateWindow ("Projeções"); glutDisplayFunc (desenha); glutKeyboardFunc (teclado); init ();

glutMainLoop (); }

void init () {

glClearColor (0,0,0, 0); glEnable (GL_DEPTH_TEST); }

//<<<<<<<<<<<<<<<<<<<< Desenho>>>>>>>>>>>>>>>>>>>>>>> void desenha (void)

(28)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (projecao) { gluPerspective(graus,Aspecto,Zmin,Zmax); } else {

glOrtho (Xmin, Xmax, Ymin, Ymax, Zmin, Zmax); }

glMatrixMode (GL_MODELVIEW); glLoadIdentity ();

gluLookAt(CamX,CamY,CamZ,FocoX,FocoY,FocoZ, NormalX,NormalY,NormalZ ); glBegin(GL_LINES); glVertex3i(0,0,0); glVertex3i(100,0,0); glVertex3i(0,0,0); glVertex3i(0,100,0); glVertex3i(0,0,0); glVertex3i(0,0,100); glEnd();

glPushMatrix ();

glTranslatef(0,0,-200); glColor3f(0,1,0); glutWireTeapot(40.0f); glPopMatrix ();

glColor3f(1,1,1); glutWireTeapot(40.0f); glutSwapBuffers(); }

//<<<<<<<<<<<<<<<<<<<< Teclado >>>>>>>>>>>>>>>>>>>>>>> void teclado (unsigned char tecla, int x, int y) { switch (tecla) { case '+': CamZ+=10; break; case '-': CamZ-=10; break; case 27: exit (1); break; case 'p'|'P':

projecao = !projecao;

break;

}

glutPostRedisplay(); }

O exemplo acima possui dois Teapots, um localizado no centro do eixo de coordenadas e outro transladado para uma posição atrás do primeiro Teapot. Há a função de teclado que permite modificar o tipo de projeção de Ortogonal para em Perspectiva. Com isso é possível compreender as diferenças entre as projeções na prática.

Projeção Ortogonal não diferencia a distância que o sólido está do observador para representa-lo na tela. Se representarmos dois objetos de mesmas dimensões, um a 30 metros e um a 50 metros do observador, na imagem gerada na tela não haverá diferenças entre eles.

Projeção em Perspectiva procura ser mais fiel à realidade e define que um objeto mais distante da câmera terá dimensões menores na tela do que um mais próximo da câmera.

É importante observar que foi usada uma imagem em 3 Dimensões para trabalharmos com câmera. É impossível trabalhar com câmera sem trabalhar em 3 Dimensões, ou seja, sem trabalhar com 3 Coordenadas (x, y, z). Utilizamos a função glutWireTeapot que é uma ferramenta pronta da

(29)

Por se tratar de uma imagem em 3D, percebemos que foi usado um parâmetro diferente para a função glutInitDisplayMode e para a função GLClear.

Um dos parâmtros utilizados para a primeira foi o GLUT_DOUBLE, ou seja, que serão usados 2 buffers para desenhar o objeto na tela: um para desenhar na tela diretamente e outro para fazer as transformações necessárias durante a animação da imagem. Um buffer fica oculto e transfere a imagem gerada completa depois das transformações para a tela, evitando efeitos indesejáveis como o piscar da imagem.

Outro parâmetro utilizado nessa mesma função foi o GL_DEPTH_BUFFER, que significa que haverá um Buffer exclusivo para as imagens com profundidade (afinal, profundidade é diferente de 3 Dimensões). O DEPTH_BUFFER é responsável por garantir que não serão desenhadas imagens ocultas na tela, que a face oculta de um objeto em 3 Dimensões (a parte de trás do objeto) não aparecerá indevidamente.

Na função GL_Clear fica especificado que o DEPTH_BUFFER deverá ser limpo sempre que se limpar a tela de visualização.

Vamos abaixo especificar o que faz cada função de câmera vista no exemplo acima.

GL_PROJECTION – Esse é o parâmetro da função GL_MATRIX_MODE para especificar que as transformações atuais se referem à câmera e não ao objeto. Representa dizer que a projeção da imagem em 3D srá feita em Perspectiva e não de forma Ortogonal.

GluPerspective () – Esta função é responsável por garantir que o volume de visualização será uma Pirâmide. A função define o ângulo do volume de visualização (que quando menor for, vai capturar imagens mais detalhadas de espaços menores do sólido gerado ), a relação entre a altura e a largura da imagem visualizada (gerando distorções na imagem, deixando-a mais estreita ou larga, comprida ou curta...), o ponto mais perto a ser observado (primeiro limite de visualização) e o ponto mais distante a ser observado (segundo limite de visualização).

GluLookAt() – Esta função recebe 9 parâmetros sendo os três primeiros para definir as coordenadas x, y e z do ponto no espaço tridimensional em que a câmera se encontra. Os três parâmetros seguintes indicam as coordenadas x,y,z do ponto no espaço tridimensional para onde a câmera está focando e os três últimos parâmtros definem o vetor normal da câmera, ou seja, o vetor perpendicular à câmera (indica qual o “lado de cima” da câmera).

Com isso, vimos mais um conceito da programação gráfica utilizando OpenGL. Mas sabemos que ainda há muito que estudar. O exemplo deste capítulo tem muitas funções que não vimos a

especificação porque não estudamos ainda os conceitos, mas as usamos para termos um bom exemplo sobre um conceito difícil de se compreender (câmera de visualização e suas

transformações) e para mostrar um pouquinho do que a OpenGL é capaz, deixando um gostinho de “quero estudar mais” no ar.

Não nos esqueçamos que esta é apenas a primeira versão do nosso tutorial de OpenGL. Num futuro breve, estaremos divulgando novos materiais com novos conceitos e a mesma vontade de ajudar no aprendizado da Computação Gráfica.

Maiores informações no site http://twiki.im.ufba.br/Fractais ou por email para brown@im.ufba.br

(30)

Boa Sorte nos estudos!!!!!!!!!!!

Referências

Documentos relacionados

Não foram muitos os escritores a intuir que não se estava precisamente ante uma revolução, mas ante uma nova religião... Para ele, todos os apóstolos

Então, preste atenção neste ponto muito importante, de que tanto é assim, que não é pelo fato de os crentes continuarem sujeitos ao pecado, mesmo depois de

OpenGL Utility Toolkit (GLUT): dene o sistema de janelas, e outras funções de desenho de superfície. 12

6 Funções OpenGL para Viewing 3D Função de Projeção Ortogonal OpenGL Transformação de Visão OpenGL Projeção Perspectiva Simétrica OpenGL.. 7 Algoritmos de

O Climate Policy Initiative/ Núcleo de Avaliação de Políticas Climáticas da PUC-Rio trabalha para aprimorar políticas públicas de energia e uso da terra gerando evidências para

The Climate Policy Initiative/ Núcleo de Avaliação de Políticas Climáticas da PUC-Rio works to improve public energy and land use policies by generating evidence for decision makers

Curso de Regente Agrícola pela Escola de Regentes Agrícolas de Évora Licenciado em Medicina Veterinária pela Escola Superior de Medicina Veterinária, Universidade Técnica de

Reunir com os alunos e outros colegas para socialização dos registros, avaliação e novos encaminhamentos que contribuam para o sucesso do