Computação Gráfica - Sinésio Pesco
Computação Gráfica - Sinésio Pesco
Computação Gráfica - Sinésio Pesco
Referncias:
Critrio de Avaliao
A avaliao ser realizada atravs de 2 trabalhos e 1 prova final realizada com consulta no final do
periodo:
- 1 trabalho (20%)
- 2 trabalho (50%)
- Prova final (30 %).
2
NDICE
CAPTULO I INTRODUO A LINGUAGEM C .........................................................5
1- ESTRUTURA BSICA DE UM PROGRAMA C...........................................................5
1.1 - Introduo................................................................................................................................5
1.2 - Variveis ...................................................................................................................................5
1.3 - A funo printf()...............................................................................................................6
1.4 - A funo scanf() .................................................................................................................7
1.5 - Operadores...............................................................................................................................8
1.6 - Comentrios.............................................................................................................................8
2 - LAOS (LOOPS)...............................................................................................................9
2.1 - Comando for( ; ; ) {} .............................................................................................................9
2.2 - Exemplo: Mtodos numricos de integrao (ponto a esquerda)..................................10
2.3 - Comando do {} while();..............................................................................................12
2.4 - Exemplo: Mtodo de Newton ..............................................................................................12
2.5 - Comando while() {};...................................................................................................12
2.6 - Comando break e continue ...........................................................................................13
3 - DECISES.......................................................................................................................13
3.1 - Comando if () {} ...........................................................................................................13
3.2 - Exemplo: Mtodo da Bisseo.............................................................................................15
4 - FUNES........................................................................................................................16
4.1 - Introduo..............................................................................................................................16
4.2 - Exemplo: Mtodos de Integrao Numrica (Ponto a esquerda, Trapzio e Simpson)
...........................................................................................................................................................17
5 - VETORES E MATRIZES ..............................................................................................18
5.1 - Vetores ....................................................................................................................................19
5.2 - Declarao ..............................................................................................................................19
5.3 - Inicializando vetores .............................................................................................................19
5.4 Exemplo: Mtodo de Ordenao .......................................................................................20
5.5 - Matrizes ..................................................................................................................................20
5.6 Exemplo: Produto de uma matriz por um vetor .............................................................21
6 - PONTEIROS....................................................................................................................22
6.1 - Introduo..............................................................................................................................22
6.2 O que um ponteiro ? .........................................................................................................23
3
6.3 Principais Aplicaes de Ponteiros ....................................................................................23
6.4 Armazenando o Endereos das Variveis ........................................................................23
6.5 Acessando o contedo de um endereo .............................................................................23
6.6 Ponteiros e Argumentos de Funes..................................................................................24
6.7 Ponteiros com Vetores .........................................................................................................25
6.8 Alocao de Vetores Dinamicamente ................................................................................27
6.9 Alocao de Matrizes Dinamicamente ..............................................................................27
6.10 Exemplo: Mtodo LU para resoluo de Sistemas Lineares.......................................28
4
CAPTULO I INTRODUO A LINGUAGEM C
1- ESTRUTURA BSICA DE UM PROGRAMA C
1.1 - Introduo
Vamos acompanhar um exemplo de programa em C.
#include <stdio.h>
main()
{
printf("Programa Inicial");
}
#include <stdio.h>
1.2 - Variveis
Uma varivel um espao reservado na memria do computador para armazenar certos tipos de dados.
#include <stdio.h>
main()
{
int num;
num = 2;
printf("Numero = %d",num);
}
Declarando uma varivel voc informa ao compilador o nome e o tipo da varivel. Como regra geral, todas
as variveis em C devem ser declaradas nas primeiras linhas da funo. O nome da varivel deve iniciar
com uma letra.
A segunda linha atribui o valor 2 para a varivel num:
num = 2;
5
char Capaz de conter um caractere (-128 a 127)
short Inteiro com capacidade reduzida (0 a 15384)
int Inteiro (32768 a 32767)
long int Inteiro estendido (-2 147 483 648 a 2 147 483 647)
float Ponto flutuante em preciso simples (10e38 a 10e38)
double Ponto flutuante em preciso dupla (10e308 a 10e308)
char Retira o sinal e portanto troca a variao de valores, por
int exemplo: unsigned int varia de 0 a 65 535
Unsigned long
Obs: No compilador Visual C++ 4.0, o tipo short tem capacidade: (32768 a 32767) e o tipo int e long
int tem a mesma capacidade: (-2 147 483 648 a 2 147 483 647)
#include <stdio.h>
main()
{
int a = 1;
char tipo = c;
float valor = 22.53;
O smbolo % dentro de uma sentena do printf indica que desejamos imprimir o contedo de alguma varivel.
Abaixo uma descrio dos principais tipos que o printf reconhece:
%c Caracter
%s String
%d Inteiro
%f Float (notao decimal)
%e Float (notao exponencial)
%g Float
%u Inteiro sem sinal
%x Hexadecimal inteiro
%o Octal inteiro
%ld Long
%lu
%lx
%lo
6
Ainda no ltimo exemplo, observe que o ultimo caracter do printf era \n. Este caracter de controle indica
que queremos inserir uma nova linha. Existem outros caracteres de controle, e todos iniciam com um \ ,
conforme a tabela abaixo:
\n Nova linha
\t Tabulao
\b Backspace
\ Aspas simples
\ Dupla aspas
\\ Barra
No exemplo abaixo ilustraremos alguns resultados obtidos com o comando printf (Os retngulos abaixo de
cada comando printf ilustra o resultado obtido na tela do computador):
#include <stdio.h>
main()
{
int i = 52;
float x = 28.534;
printf("i = %2d\n",i);
i = 5 2
printf("i = %4d\n",i);
i = 5 2
printf("x = %8.3f\n",x);
x = 2 8 . 5 3 4
printf("x = %-8.3f\n",x);
x = 28 . 5 3 4
}
#include <stdio.h>
main()
{
int i,j;
float x,y;
double a,b;
scanf("%d",&i);
scanf("%f",&x);
scanf("%lf",&a);
j = i % 2;
y = x * 2;
b = a / 2;
7
O comando scanf interrompe a execuo do programa e aguarda o usurio entrar com um valor para a
varivel x. Existem dois campos a serem informados neste comando:
Para o tipo double o prefixo do scanf deve ser lf, como no exemplo.
1.5 - Operadores
Os operadores aritmticos sobre as variveis so os seguintes:
+ Soma
- Subtrao
* Multiplicao
/ Diviso
% Resto da diviso
A operao de incremento de uma unidade tem tambm um formato reduzido, ou seja, o comando:
i = i + 1;
i++;
Como exemplo dos operadores, o programa abaixo calcula as razes reais de um polinmio de segundo grau:
#include <stdio.h>
#include <math.h>
main()
{
float a,b,c;
float x1,x2;
printf("Entre a,b,c:");
scanf("%f %f %f",&a,&b,&c);
x1=(-b+sqrt(b*b-4*a*c))/(2*a);
x2=(-b-sqrt(b*b-4*a*c))/(2*a);
printf("\n x1 = %f x2 = %f\n",x1,x2);
}
1.6 - Comentrios
possvel introduzir comentrios dentro de um programa C, bastando para isso coloc-los no seguinte
formato:
/* Comentario */
/* * * * * * * * * * * * * * * * * * * * * * * * */
8
/* Solues reais da equao ax*x + b*x + c = 0 */
#include <stdio.h>
#include <math.h>
main()
{
/* Definicao das variaveis */
float a,b,c; /* Coeficientes do polinomio */
float x1,x2; /* Solucoes desejadas */
/* Entrada de Dados */
printf("Entre a,b,c:");
scanf("%f %f %f",&a,&b,&c);
printf("\n x1 = %f x2 = %f\n",x1,x2);
}
2 - LAOS (LOOPS)
Existem trs formatos bsicos de laos:
1 do {} while();
2 - while() {}
3 - for( ; ;) { }
#include <stdio.h>
main()
{
int n;
9
for(n=0; n<10; n++) {
printf("n = %d\n",n);
}
}
O resultado ser:
n = 0
n = 1
n = 2
n = 3
n = 4
n = 5
n = 6
n = 7
n = 8
n = 9
Expresso de inicializao
Inicializa a varivel do lao. A inicializao feita uma nica vez quando o lao inicia.
Expresso de teste
Esta expresso testa (a cada vez que o conjunto de comandos no interior do for finaliza), se o lao deve ser
encerrado. Enquanto a expresso for verdadeira o lao repetido. Para realizar teste utilizamos os operadores
relacionais. Os principais operadores so:
Expresso de incremento
A cada repetio do lao, o terceiro argumento (n++) incrementa a varivel n.
x 2 dx
0
/* * * * * * * * * * * * * * * * * * * * */
/* Integracao Numerica: Ponto a Esquerda */
/* * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i;
10
int n;
float w;
float dx ;
float a,b ;
float soma;
printf("\nEntre o extremo inferior do intervalo: ");
scanf("%f",&a);
printf("\nEntre o extremo superior do intervalo: ");
scanf("%f",&b);
printf("\nEntre com o numero de particoes: ");
scanf("%d",&n);
soma = 0.0;
dx = (b-a)/n;
for(i=0; i< n; i++) {
w = a + i * dx;
soma += (w * w) * dx;
printf("\nSoma parcial = %f ",soma);
}
printf("\nIntegral = %15.9f ",soma);
}
11
2.3 - Comando do {} while();
Este segundo tipo de lao adequado para situaes onde no sabemos ao certo quantas vezes o lao deve ser
repetido. O exemplo abaixo ilustra a utilizao do comando:
#include <stdio.h>
main()
{
int n;
n = 0;
do {
printf("n = %d\n",n);
n++;
} while (n < 10);
}
No exemplo acima o programa entra dentro do lao faz o primeiro printf, incrementa n de uma unidade e s
ento verifica a condio while (n < 10). Caso a condio seja verdadeira, a execuo do programa
retorna a primeira linha do lao (printf("n = %d\n",n);) e prossegue at que a condio seja falsa.
O programa sempre entra executando os comando no interior do lao, para somente no final realizar o teste.
/* * * * * * * * * * */
/* Metodo de Newton */
#include <stdio.h>
#include <math.h>
main()
{
int i ;
double xn, x0,xn_1;
double erro ;
xn = x0;
i = 0;
do {
xn_1 = xn;
xn = xn_1 - (xn_1 * xn_1 - 2) / (2 * xn_1);
i++;
printf("\nx[%2d] = %20.17f",i,xn);
} while (fabs(xn - xn_1) > erro);
printf ("\n A raiz obtida foi: %20.17f\n",xn);
}
Neste exemplo, primeiro feito o teste (while (n < 10)) e somente em caso verdadeiro os comando
dentro do while so executados. Assim se a condio for falsa a primeira vez, em nenhum momento os
comandos dentro do lao sero executados. J no do{} while(); pelo menos a primeira vez os comandos
dentro do lao sero executados.
#include <stdio.h>
main()
{
int n;
n = 0;
while (n < 10){
printf("n = %d\n",n);
if (n > 3)
break;
n++;
}
printf (Fim do programa \n);
}
n = 0
n = 1
n = 2
n = 3
n = 4
Fim do programa
O comando continue; transfere a execuo do programa para o teste do lao, que pode ou no prosseguir
conforme a condio seja verdadeira ou falsa.
3 - DECISES
3.1 - Comando if () {}
13
O comando principal de deciso o if(). Atravs deste comando o fluxo do programa pode ser desviado
para executar ou no um conjunto de comandos. Considere o exemplo abaixo:
/* * * * * * * * * * * * * * * * * * */
/* Testa se um numero e par ou impar */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i,n;
printf("Entre com n = ");
scanf("%d", &n);
i = n % 2;
if (i == 0) {
printf("\n n e um numero par\n");
}
else {
printf("\n n e um numero impar\n");
}
}
Neste exemplo a varivel i armazena o resto da diviso de n por 2. Caso seja zero, ento o programa passa a
execuo do comando printf("\n n e um numero par\n"). Se a condio falha, o comando else
indica que o programa deve executar o comando printf("\n n e um numero impar\n").
Observe que o else um comando opcional. Caso voc no o inclua, o programa segue para o prximo
comando aps o if.
14
3.2 - Exemplo: Mtodo da Bisseo
O programa abaixo determina as razes da funo: y = x 2 2 utilizando o mtodo da bisseo. No
mtodo da bisseo procuramos uma raiz contida em certo intervalo [a,b] dado. A raiz existe desde
que a funo seja contnua e o sinal da funo troque de um extremo para outro (ou seja f(a) * f(b) <
0).
/* * * * * * * * * * * * * * * * * * */
/* Metodo da Bissecao */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
main()
{
float a,b,c;
float erro;
float fa,fb,fc;
printf("\nEntre com a = ");
scanf("%f",&a);
printf("\nEntre com b = ");
scanf("%f",&b);
fa = a*a - 2;
fb = b*b - 2;
if (fa * fc < 0) {
b = c;
}
else {
if (fb * fc < 0)
a = c;
else
break;
}
printf("\n Raiz parcial = %f ",c);
}
printf("\n\n Raiz obtida = %f \n",c);
}
15
4 - FUNES
4.1 - Introduo
As funes cumprem como primeiro papel, evitar repeties desnecessrias de cdigo. No exemplo anterior
precisamos calcular o valor y=x*x-2 em diversas partes do programa. Se desejssemos trocar a funo, seria
necessrio alterar vrias partes do cdigo. Para evitar isso, utilizaremos uma funo como no exemplo
abaixo:
/* * * * * * * * * * * * * * * * * * * */
/* Metodo da Bisssecao */
/* * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
float f(float x)
{
return(x*x-2);
}
void main()
{
int i = 0;
float a,b,c;
float erro;
float fa,fb,fc;
printf("\nErro: ");
scanf("%f",&erro);
fa = f(a);
fb = f(b);
if (fa * fc < 0)
b = c;
else
if (fb * fc < 0)
a = c;
else
break;
printf("Raiz parcial no passo %d = %f \n",i,c);
}
printf("\nRaiz obtida = %f \n",c);
}
float f (float x)
Define o tipo que Nome da Argumentos de
16
ser retornado funo entrada
{
float y;
y = x * x - 2;
return(y);
Valor a ser
retornado
}
Uma observao importante que as variveis dentro da funo no so conhecidas fora da funo e vice-
versa.
/* * * * * * * * * * * * * * * * * * */
/* Metodos de Integracao Numerica */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <conio.h>
float f(float x)
{
float y;
y = 1/(1+x*x);
return(y);
}
dx = (b-a)/n;
soma = f(a);
for(i=1; i < n; i++) {
soma = soma + 2*f(a + i*dx);
printf("\nSoma parcial = %f ",soma);
17
}
soma = dx/2 * (soma + f(b));
return(soma);
}
dx = (b-a)/n;
soma = f(a);
for(i=1; i < n; i++) {
if ((i%2) == 1)
soma = soma + 4*f(a + i*dx);
else
soma = soma + 2*f(a + i*dx);
printf("\nSoma parcial = %f ",soma);
}
soma = dx/3 * (soma + f(b));
return(soma);
}
main()
{
int i;
int n;
char c;
float a,b ;
float soma;
do {
printf("Selecione um do metodos de integracao \n");
printf("1- Ponto a esquerda \n");
printf("2- Trapezio \n");
printf("3- Simpson \n");
printf("Opcao: ");
scanf("%d",&i);
printf("\nEntre o extremo inferior do intervalo: ");
scanf("%f",&a);
printf("\nEntre o extremo superior do intervalo: ");
scanf("%f",&b);
printf("\nEntre com o numero de particoes: ");
scanf("%d",&n);
switch(i)
{
case 1:
soma = Integra_Ponto_a_esquerda(a,b,n);
break;
case 2:
soma = Integral_Trapezio(a,b,n);
break;
case 3:
soma = Integral_Simpson(a,b,n);
break;
}
printf("\nIntegral = %15.9f ",soma);
printf("\n Continua (s/n) ");
c = getche();
} while((c != 'n') && (c != 'N'));
}
5 - VETORES E MATRIZES
18
5.1 - Vetores
Quando voc deseja representar uma coleo de dados semelhantes, pode ser muito inconveniente utilizar um
nome de varivel diferente para cada dado.
Para ilustrar vamos considerar o seguinte exemplo: Montar um programa que armazena as notas de 15 alunos
e calcula a mdia obtida pela turma. As notas sero armazenadas em uma varivel do tipo float, porm ao
invs de criarmos 15 variveis, utilizamos uma varivel do tipo vetor, definida como abaixo:
float notas[15];
#include <stdio.h>
main()
{
int i ;
float media ;
float soma ;
float notas[15];
for(i=0;i<15;i++)
soma = soma + notas[i];
media = soma / 15;
5.2 - Declarao
Um vetor uma coleo de variveis de certo tipo, alocadas seqencialmente na memria. Para o compilador
C um declarao de varivel vetor do tipo:
int n[5];
reserva o espao de 5 variveis do tipo inteira, onde cada varivel pode ser referenciada conforme abaixo:
IMPORTANTE: Observe que a declarao anterior cria cinco variveis, porm o primeiro elemento n[0].
A declarao de vetor inicia com o ndice 0 e finaliza no ndice 4.
Se voc quer atribui um valor a um dos componentes do vetor basta referencia-lo por exemplo:
n[3] = 29;
resulta em:
29
n[0] n[1] n[2] n[3] n[4]
19
Assim como possvel inicializar uma varivel simples na mesma linha da declarao, o mesmo pode ser
feito para vetores. Observe o exemplo abaixo:
/* * * * * * * * * * * * * * * * * * * * * */
/* Metodo da Bolha (ordenacao de um vetor) */
/* * * * * * * * * * * * * * * * * * * * * */
#define MAX 10
#include <stdio.h>
main()
{
int i ;
int flag;
float swap;
float n[MAX];
/* Entrada de Dados */
flag = 1;
while(flag == 1) {
flag = 0;
for(i=0;i<(MAX-1);i++)
{
if (n[i] > n[i+1])
{
swap = n[i] ;
n[i] = n[i+1];
n[i+1] = swap ;
flag = 1 ;
}
}
}
/* Imprime a sequencia de numeros ordenada */
5.5 - Matrizes
Para representar uma matriz 3x4 (3 linha e 4 colunas) de nmeros reais utilizamos a seguinte declarao:
20
float A[3][4];
/* * * * * * * * * * * * * * * * * * * * * * */
/* Multiplicacao de um vetor por uma matriz */
/* * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i,j;
float A[3][3] = {{1.0, 1.5, 2.1}, {3.4, 2.2, 9.1}, {-1.2, -3.4, 0.9}};
float v[3] = {2.0, 1.0, 0.5};
float p[3];
for(i=0;i<3;i++) {
p[i] = 0;
for(j=0;j<3;j++) {
p[i] += A[i][j] * v[j];
}
}
for(i=0;i<3;i++) {
printf("\n[");
for(j=0;j<3;j++) {
printf("% 5.3f ",A[i][j]);
}
printf(" ] ");
printf(" [ %5.3f ]",v[i]);
}
for(i=0;i<3;i++)
printf("\n p[%1d] = %10.4f",i,p[i]);
}
21
6 - PONTEIROS
6.1 - Introduo
Considere o seguinte programa:
#include <stdio.h>
int teste(int i)
{
i = i + 20;
printf("Dentro da funcao i = %d \n",i);
return(i);
}
void main()
{
int i,j;
i = 1;
printf("Fora da funcao i = %d \n",i);
j = teste(i);
printf("Fora da funcao i = %d \n",i);
printf("Fora da funcao j = %d \n",j);
}
O resultado ser:
Observe que o valor da varivel i no tem seu contedo alterado pela funo. Isto ocorre porque quando uma
funo chamada durante o programa, todas as variveis presentes na funo so criadas neste. Quando a
funo finaliza, todas as variveis da funo so apagadas da memria. Muitas vezes gostaramos que os
argumentos de entrada da funo pudessem ter seus valores alterados quando a funo finalizasse. Esta ser
uma das aplicaes do conceito de ponteiros.
22
6.2 O que um ponteiro ?
Um ponteiro uma varivel que contm o endereo de memria de outra varivel. Todas as variveis so
alocadas em algum espao de memria do computador. O ponteiro fornece um mecanismo para obter e
armazenar este endereo de memria. Considere o exemplo:
#include <stdio.h>
void main()
{
int i;
printf("Endereco de i = %x\n",&i);
}
O endereo da varivel obtido utilizando-se o operador unrio & na frente da varivel. Assim &i fornece o
endereo da varivel i.
#include <stdio.h>
void main()
{
int i ;
int *pi;
pi = &i;
printf("Endereco de i = %x ou %x\n",&i,pi);
}
A varivel pi uma varivel do tipo ponteiro para inteiro (ou seja, ela recebe o endereo de uma varivel do
tipo inteiro). Para informar que esta varivel do tipo apontador colocamos um asterisco (*) na frente da
varivel no momento da sua declarao:
int * pi;
Tipo de Indica Nome da
ponteiro ponteiro varivel
23
Considere o exemplo anterior em que pi = &i. Alm do endereo de i, (j armazenado em pi) podemos
tambm acessar o contedo armazenado no endereo de memria. Isto equivale a obter o valor da varivel i.
Observe o exemplo:
#include <stdio.h>
void main()
{
int i ;
int j ;
int *pi;
pi = &i;
i = 25;
j = *pi + 8; /* equivalente a j = i + 8 */
printf("Endereco de i = %x \n",pi);
printf("j = %d \n",j);
}
O operador unrio * trata seu operando como um endereo e acessa este endereo para buscar o contedo da
varivel. Observe que o * tem dupla funo:
1. Em uma declarao de varivel, indica que a varivel do tipo ponteiro.
2. Durante uma atribuio, acessa o contedo do endereo armazenado pela varivel ponteiro.
No nosso exemplo, para alterar o valor da varivel i, temos duas alternativas (totalmente equivalentes) :
i = 5;
*pi = 5;
24
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Este programa NO consegue permutar os valores */
#include <stdio.h>
void troca(float x, float y)
{
float auxiliar;
auxiliar = x;
x = y;
y = auxiliar;
}
main()
{
float x = 1.2;
float y = 56.89;
troca(x,y);
printf("x = %6.2f e y = %6.2f\n",x,y);
x = 1.2 e y = 56.89
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Este programa permutar os valores das variaveis */
#include <stdio.h>
main()
{
float x = 1.2;
float y = 56.89;
troca(&x,&y);
O uso comum de argumentos do tipo ponteiro ocorre em funes que devem retornar mais de um valor. No
exemplo acima, a funo retornou dois valores.
25
Na linguagem C, o relacionamento de ponteiros com vetores e matrizes to direto que daqui para frente
sempre trataremos vetores e matrizes utilizando ponteiros. Qualquer operao que possa ser feita com ndices
de um vetor pode ser feita atravs de ponteiros. Vamos acompanhar atravs do exemplo de ordenao:
/* * * * * * * * * * * * * * * * * */
/* Ordenacao pelo metodo da bolha */
#define MAX 10
#include <stdio.h>
void troca(float *x, float *y)
{
float auxiliar;
auxiliar = *x;
*x = *y;
*y = auxiliar;
}
flag = 1;
while(flag == 1) {
flag = 0;
for(i=0;i<(MAX-1);i++)
{
if (px[i] > px[i+1])
{
troca(&(px[i]),&(px[i+1]));
flag = 1;
}
}
}
}
main()
{
int i ;
float n[MAX];
/* Entrada de Dados */
Observe que quando chamamos a funo ordena(n,MAX), utilizamos como argumento n referncia a
nenhum ndice. A funo ordena declarada como:
26
void ordena(float *px, int limite)
Como o C sabe que estamos nos referenciando a um vetor e no a uma simples varivel ? Na verdade px
uma varivel ponteiro para um float. Ela recebe o endereo do primeiro elemento do vetor . Porm, os vetores
so alocados sequencialmente na memria do computador. , de forma que a referncia px[5] , acessa o
quinto contedo em sequencia na memria.
Quando o nome de um vetor passado para uma funo, o que passado a posio do incio do vetor.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void main()
{
int i;
int n;
float *v;
for(i=0;i<n;i++)
printf("v[%2d]=%f\n",i,v[i]);
free(v);
}
Para efetuar a alocao dinmica observe as etapas do programa:
1. O vetor que ser alocado foi declarado como um ponteiro: float *v;
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
float **matalloc(int n,int m)
{
int j;
float **A;
27
A = (float **)malloc(n * sizeof(float *));
for(j=0;j<n;j++)
A[j] = (float *) malloc(m * sizeof(float));
return(A);
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%f",&(A[i][j]));
for(i=0;i<n;i++) {
printf("\n");
for(j=0;j<m;j++)
printf("A[%2d][%2d]=%f\n",i,j,A[i][j]);
}
matfree(A,n,m);
}
Vamos descrever este mtodo partindo de um exemplo. Considere o sistema linear abaixo:
2 1 1 x 5
4 6 0 y =
2
2 7 2 z 9
Determinando a matriz L e U
28
Nosso objetivo inicial aplicar um conjunto de operaes elementares sobre a matriz dos coeficientes de tal
forma que ao final do processo obtemos A = LU, ou seja, a matriz A pode ser escrita como o produto de duas
matrizes onde:
L : Matriz triangular inferior, cuja diagonal contm apenas o valor 1.
U : Matriz triangular superior.
Para obter estas matrizes existem trs tipos de operaes elementares:
1- Permutao de linhas (Li <-> Lj) (No necessrio implementar, para o primeiro trabalho).
2- Multiplicao de uma linha por um escalar K (Li = K Li). (No necessrio implementar, para o
primeiro trabalho).
3- Substituio da i-sima linha pela i-sima linha acrescida de K vezes a j-sima linha (Li = Li + K Lj )
Vamos iniciar determinando a matriz U. Para isso nosso objetivo transformar a matriz dada em uma matriz
triangular superior. Comeamos na primeira coluna, eliminando todos os elementos abaixo do 2:
2 1 1 2 1 1
4 6 0 L2 L2 2 L1
0
8 2
2
7 2 2 7 2
2 1 1 2 1 1
0 8 2 L3 L3 + L1
0
8 2
2
7 2 0 8 3
Passamos agora para a segunda coluna e eliminaremos os elementos abaixo do 8 (neste exemplo o 8):
2 1 1 2 1 1
0 8 2 L3 L3 + L2
0
8 2
0 8 3 0 0 1
Obtemos ento uma matriz triangular superior. Esta matriz matriz U desejada.
Para obter a matriz L, observamos que cada uma das operaes elementares aplicadas pode ser representada
por uma matriz. Vamos acompanhar pelo exemplo.
L2 L2 2L1
Esta operao elementar representada pela matriz:
1 0 0
2 1 0
0 0 1
Tal que:
1 0 0 2 1 1 2 1 1
2 1 0 4 6 0 =
0 8 2
0 0 1 2 7 2 2 7 2
29
De forma geral todas as operaes elementares so representadas por matrizes:
1. Permutao de linhas (Li <-> Lj): Partindo da matriz identidade (de mesma dimensao que a matriz A)
troque a i-sima linha pela j-sima linha.
Ex: L2 <-> L3, basta trocar as linhas 2 e 3 da matriz identidade para obter a matriz:
1 0 0
0 0 1
0 1 0
2. Multiplicao de uma linha por um escalar K (Li = K Li): Partindo da matriz identidade troque o i-
simo elemento da diagonal pelo valor K.
Ex: L2 = 5 L2, basta trocar na segunda linha da identidade a diagonal para 5:
1 0 0
0 5 0
0 0 1
3. Substituio da i-sima linha pela i-sima linha acrescida de K vezes a j-sima linha (Li = Li + K Lj ):
Partindo da matriz identidade, coloque o valor K na i-sima linha e j-sima coluna.
Ex: L2 = L2 + 4 L3. Partindo da matriz identidade, coloque na segunda linha e na terceira coluna o valor 4:
1 0 0
0 1 4
0 0 1
1 0 0
L3 L3 + L1 0
1 0
1 0 1
1 0 0
L3 L3 + L2 0
1 0
0 1 1
1 0 0 1 0 0 1 0 0 2 1 1 2 1 1
0 1 0 0 1 0 2 1 0 4 6 0 = 0 8 2
2 1 1 1 0 0 2 1 1
4 6 0 = 2 1 0 0 8 2
144274432 142
2
A
4 434 14424413
1 1 1 0 0
L
U
No necessrio fazer as contas para obter a matriz L. Observe que a matriz L s possui elementos abaixo da
diagonal. Estes elementos so obtidos simplesmente invertendo o sinal da constante K obtida em cada
operao elementar, e posicionando na matriz conforme a linha e coluna adequada.
Resolvendo Lc = b
1 0 0 c0 5
2 1 0 c1 =
2
1
1 1 c2 9
Assim:
c0 = 5 c 0 5
c1 = 2 10 = 12 e portanto: c
1
=
12
c 2 = 9 + 5 12 = 2 c 2
2
Resolvendo Ux = c
2 1 1 x0 5
0 8 2 x1 =
12
0 0 1 x 2 2
E obtemos:
x2 = 2
12 + 4
x1 = =1
8
31
5 1 2
x0 = =1
2
A soluo do nosso sistema ser:
x0 1
x
1
= 1
x 2
2
32
CAPTULO II VISUALIZAO E APLICAES GRFICAS 2D ____________ 3
1- PONTOS E RETAS NO OPENGL ______________________________________ 3
1.1 A Tela do Computador _________________________________________________ 3
1.2 Cores________________________________________________________________ 3
1.3 Introduo ao OpenGL_________________________________________________ 4
1.4 Exemplo: Plotar um ponto na tela utilizando as bibliotecas do OpenGl _________ 4
1.5 Exemplo: Plotar uma reta unindo dois pontos ______________________________ 6
1.5.1 Algoritmo ingnuo__________________________________________________________ 6
1.5.2 Algoritmo de Bresenham_____________________________________________________ 7
1.5.3 Retas no Opengl __________________________________________________________ 11
1.6 Exemplo: Plotar o grfico de uma funo_________________________________ 11
2 TECLADO E MOUSE (Callbacks) ____________________________________ 15
2.1 Introduo __________________________________________________________ 15
2.2 Teclado _____________________________________________________________ 15
2.3 Exemplo: Utilizao do teclado no programa funes. ____________________ 15
2.3.1 - Mdulo funcao011.h ____________________________________________________ 15
2.3.2 - Mdulo funcao010.cpp __________________________________________________ 16
2.3.3 - Mdulo funcao011.cpp _________________________________________________ 16
2.4 Mouse ______________________________________________________________ 18
2.4.1- glutMouseFunc ____________________________________________________________ 18
2.4.2- glutMotionFunc____________________________________________________________ 19
2.4.3- glutPassiveMotionFunc______________________________________________________ 20
3 CURVAS PARAMTRICAS _________________________________________ 20
3.1 Introduo __________________________________________________________ 20
3.2 Exemplo: Visualizao de Curvas Paramtricas ___________________________ 21
3.2.1 Mdulo curvas010.cpp _________________________________________________ 21
3.2.2 Mdulo curvas011.cpp _________________________________________________ 22
3.2.3 Mdulo curvas011.h ____________________________________________________ 23
3.2.4 Exerccio_________________________________________________________________ 23
3.3 Curvas na forma Polar ________________________________________________ 23
3.4 Exemplo: Visualizao de Curvas Polares ________________________________ 24
3.5 Exerccios ___________________________________________________________ 25
4 RETAS E POLGONOS NO OPENGL _________________________________ 26
4.1 Retas e Polgonos _____________________________________________________ 26
4.2 Exemplo: Visualizao dos Mtodos Numricos de Integrao _______________ 27
4.2.1 - Mdulo Intvis01.c_____________________________________________________ 27
4.2.2 - Mdulo Intvis02.cpp __________________________________________________ 29
4.2.3 - Mdulo Intvis03.cpp __________________________________________________ 30
4.3 Exemplo: Realizando Zoom do grfico ___________________________________ 32
5 CURVAS IMPLCITAS _____________________________________________ 35
5.1 Introduo __________________________________________________________ 35
5.2 Visualizao de Curvas Implcitas_______________________________________ 35
5.3 Programa Curva Implcita _____________________________________________ 36
1
5.3.1 Mdulo impl010.cpp ____________________________________________________ 36
5.3.2 Mdulo impl011.cpp ____________________________________________________ 37
5.3.3 Mdulo impl011.h ______________________________________________________ 39
5.4 Exerccio ____________________________________________________________ 39
6 FRACTAIS _______________________________________________________ 40
6.1 Conjuntos auto semelhantes____________________________________________ 40
6.2 Dimenso Hausdorff e o conceito de fractal _______________________________ 41
6.3 Exemplos de fractais __________________________________________________ 41
6.3.1- Tringulo de Sierpinski ______________________________________________________ 42
6.3.2- Tringulo de Sierpinski utilizando Monte Carlo ___________________________________ 46
6.3.3- Fern utilizando Monte Carlo ________________________________________________ 48
6.3.4- Curva de Koch_____________________________________________________________ 50
2
CAPTULO II VISUALIZAO E
APLICAES GRFICAS 2D
1- PONTOS E RETAS NO OPENGL
1.1 A Tela do Computador
A tela do computador pode ser considerada uma matriz de clulas discretas (Pixels), cada qual pode estar
acesa ou apagada.
A definio da tela varia conforme o monitor e a placa grfica. As definies bsicas encontradas na
maioria dos monitores so:
640 x 480
800 x 600
1024 x 768
1280 x 1024
1.2 Cores
A cada pixel associamos uma cor. Para obter uma cor, o monitor envia certa combinao de vermelho,
verde e azul (RGB). O nmero de cores possveis varia conforme o hardware. Cada pixel tem uma mesma
quantidade de memria para armazenar suas cores. O buffer de cores (Color Buffer) uma poro da
memria reservada para armazenar as cores em cada pixel. O tamanho deste buffer usualmente medido
em bits. Um buffer de 8 bits pode exibir 256 cores diferentes simultaneamente. Conforme a capacidade da
placa grfica podemos ter:
Existem duas formas bsica de acessar as cores no OpenGL: RGB e Modo Indexado. Trabalharemos
sempre em formato RGB. No formato RGB voc deve informar as intensidades de Vermelho, Verde e
Azul desejadas. Estas intensidades devem variar entre 0.0 a 1.0. A tabela abaixo mostra como obter as
cores bsicas:
Cores R G B
Vermelho 1.0 0.0 0.0
Verde 0.0 1.0 0.0
Azul 0.0 0.0 1.0
Amarelo 1.0 1.0 0.0
Cyan 0.0 1.0 1.0
Magenta 1.0 0.0 1.0
Branco 1.0 1.0 1.0
Preto 0.0 0.0 0.0
3
1.3 Introduo ao OpenGL
O sistema grfico OpenGL (GL significa Graphics Library) uma biblioteca (de aproximadamente 350
comandos) para aplicaes grficas. O OpenGL foi desenvolvido pela Silicon Graphics (SGI) voltado
para aplicaes de computao grfica 3D, embora possa ser usado tambm em 2D. As rotinas permitem
gerar primitivas (pontos, linhas, polgonos, etc) e utilizar recursos de iluminao 3D.
O OpenGL independente do sistema de janelas, ou seja, suas funes no especificam como manipular
janelas. Isto permite que o OpenGL possa ser implementado para diferentes sistemas: X Window System
(Unix), Windows 95 e NT, OS/2 , Macintosh, etc.
#include <gl\glut.h>
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
glFlush();
}
glutInit(&argc,argv);
utilizado para iniciar a biblioteca GLUT.
glutInitWindowSize(400,400);
Indica o tamanho da janela a ser aberta (em pixels).
glutInitWindowPosition(1,1);
Indica a posio inicial da janela.
glutCreateWindow("Ponto");
Cria uma janela para o OpenGL denominada Ponto
gluOrtho2D(0,399,399,0);
4
Este comando estabelece a escala da tela. Sua sintaxe :
gluOrtho2D(GLdouble left, Gldouble right, Gldouble bottom, Gldouble top);
glutDisplayFunc(redesenha);
Este comando registra que a funo void redesenha() ser a rotina a ser chamada sempre que a
janela necessita ser redesenhada.
glutMainLoop();
Inicia o gerenciamento da janela e mantm o programa em loop, aguardando por eventos.
glClearColor(0.0,0.0,0.0,0.0);
Indica cor para ser utilizada no fundo da tela.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Pinta os buffers indicados com a cor do glClearColor()
glColor3f(1.0,0.0,0.0);
Define o vermelho como cor atual.
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
Plota um ponto na posio (200,200) na tela.
glFlush();
Imprime o contedo do buffer na tela.
Exerccios:
1) Comente as seguintes linhas na funo redesenha e veja o resultado:
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
void redesenha()
{
static int i = 0;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
glFlush();
printf(" %d ",i++);
}
3) Comente a seguinte linha do cdigo e veja o resultado.
glutDisplayFunc(redesenha);
5
1.5 Exemplo: Plotar uma reta unindo dois pontos
Como exemplo vamos desenhar uma reta (no vertical) unindo dois pontos (x0,y0) e (x1,y1).
A equao da reta que passa por dois pontos :
y1 y 0
y= ( x x 0) y 0
x1 x0
A primeira idia de como resolver este problema proposto pelo programa abaixo. Este um exemplo
ingnuo de como desenhar a reta que passa por dois pontos dados. Vamos discutir a seguir os principais
problemas deste programa e as possveis solues.
/* -------------------------------------------------------------- */
/* Exemplo ingnuo de como plotar a reta definida por dois pontos */
/* -------------------------------------------------------------- */
#include <gl\glut.h>
#include <stdio.h>
int pontos;
float x0,y0,x1,y1;
float Reta_dois_pontos(float x)
{
float y;
y = (y1-y0)/(x1-x0)*(x-x0) - y0;
return(y);
}
void display()
{
int i ;
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
for (i=0;i<pontos;i++)
{
x = x0 + i * (x1 - x0)/pontos;
y = Reta_dois_pontos(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
glFlush();
glutSwapBuffers();
}
printf("x0 = ");
scanf("%f",&x0);
printf("\ny0 = ");
scanf("%f",&y0);
printf("\nx1 = ");
scanf("%f",&x1);
printf("\ny1 = ");
scanf("%f",&y1);
printf("\nPontos = ");
6
scanf("%d",&pontos);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glOrtho(0,399,399,0,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
1) Este mtodo requer operaes em ponto flutuante (float ou double) para cada pixel. Isto acarreta em
um algoritmo lento, se comparado a um algoritmo que opera somente com nmeros inteiros. Para o
caso da reta, existe um tal algoritmo que utiliza somente aritmtica com nmeros inteiros. Este
algoritmo foi desenvolvido por Jack E. Bresenham na dcada de 60 e ser descrito adiante.
2) O usurio estabelece o nmero de pontos da reta a serem plotados entre os dois pontos. Podem
ocorrer dois casos: faltarem pontos (a reta fica pontilhada), sobrarem pontos (neste caso o
algoritmo faz contas desnecessrias). O ideal o prprio programa se encarregar de determinar o
nmero de pontos necessrios e suficientes para resolver o problema.
3) O caso particular da reta vertical x = K (onde K constante) no pode ser plotado.
Para os casos em que a inclinao no est entre 0 e 1, utilizamos a mesma soluo considerando
simetrias. O algoritmo completo deve considerar oito casos:
Vamos descrever o funcionamento do algoritmo para o caso 1, os casos restantes seguem por simetria.
7
Para mais detalhes consultem a web:
htpp://www.cs.unc.edu/~hoff/projects/comp235/bresline/bresen.html.
Observe que todo o trabalho consiste em resolver este problema utilizando somente nmeros inteiros.
Partindo do ponto (Ax,Ay), como 0 m 1 , ento para o prximo pixel temos somente
duas escolhas possveis: (Ax+1,Ay) e (Ax+1,Ay+1). Lembre da figura anterior que os crculos
transparentes so as duas opes. O incremento em uma unidade vem do fato que estamos
avanando um pixel na direo do x (Ax + 1), e podemos ou no avanar um pixel na direo
do y (Ay ou Ay +1).
O ponto ideal dado por (Ax+1,y) onde y = m (Ax + 1) + b. Ns devemos portanto escolher
qual dos dois pontos anteriores est mais prximo do ponto ideal (Ax+1, y). Para isso
calculamos a distncia entre destes dois pontos para o ponto ideal:
D1 = y Ay e D2 = Ay + 1 - y
Assim se D1 <= D2 ento escolhemos o ponto (Ax+1,Ay), caso contrrio, se D1 > D2 ento
escolhemos o ponto (Ax+1, Ay+1). Contudo, como queremos desenvolver um algoritmo
rpido para fazer isto, teremos que nos restringir a aritmtica inteira. Observe que o ponto ideal
y real e no inteiro. Assim, os prximos passos tm por objetivo obter um resultado
equivalente a testar D1 e D2, porem utilizando somente nmeros inteiros.
Considere P1 = D1 D2. Testar D1 <= D2 , ou D1 > D2 equivalente respectivamente a testar
P1 <= 0, ou P1 > 0. Esta varivel P1 ser denominada a varivel de deciso. Assim, temos
que:
P1 = D1 D2
= y Ay (Ay + 1) + y
= 2y 2Ay -1
Substituindo y = m (Ax + 1) + b, obtemos
P1 = 2m(Ax + 1) + 2b 2Ay -1
Temos que m = dY/dX, onde dY = abs(By Ay) e dX = Bx Ax e substituindo obtemos:
P1 = 2 dY/dX (Ax + 1) + 2b 2Ay -1
Multiplicando por dX obtemos:
P1 dX = 2 dY (Ax + 1) + 2 b dX 2Ay dX - dX
Observe que para o caso 1 em questo dX > 0, assim o sinal de P1 e de P1 * dX o mesmo.
Consideramos ento a varivel de deciso P1 como sendo
P1 = dY (Ax + 1) + 2 b dX 2Ay dX - dX
A expresso
2 dY (Ax + 1) + 2 b dX 2Ay dX - dX
o teste que estamos procurando, pois ele envolve somente nmeros inteiros
(dY,dX,Ax,Ay,b). Porm ainda podemos melhorar o algoritmo, pois esta avaliao ficaria
demasiada cara para ser feita a cada novo pixel da reta.
Neste passo vamos tentar calcular a varivel de deciso P2 para o prximo pixel, utilizando a
informao que adquirimos no passo anterior para estimar P1. De forma geral para dois passos
subseqentes temos que:
P2 P1 = 2dY(Ax + 2) +2b dX 2Ay dX dX (2dY(Ax + 1) +2b dX 2Ay dX - dX)
= 2 dY -2 (Ay Ay) dX
Temos duas possibilidades: ou Ay = Ay ou Ay = Ay+1, o que se resume a:
P2 P1 = 2 dY ,caso em que escolhemos o ponto (Ax+1,Ay)
P2 P1 = 2 dY -2 dX ,caso em que escolhemos o ponto (Ax+1,Ay+1)
Assim uma vez que calculamos a varivel de deciso P1 para o primeiro pixel, nos pixels
subseqentes, basta incrementar 2 dY ou (2 dY 2 dX), conforme o pixel escolhido no passo
anterior.
8
o dY = By Ay
o Deciso inicial P1 = 2 dY dX
o Incremente Ax at Bx e para cada passo:
Se P1 <= 0 escolha o pixel Ay e incremente P1 = P1 + 2 dY
Se P1 > 0 escolha o pixel Ay + 1 e incremente P1=P1 + 2 dY 2 dX.
#include <gl\glut.h>
#include <stdio.h>
//====================================================================
// b r e s l i n e . c
//
// VERSION 1: draws only from one end and calculates both x and y.
//
// Programmer: Kenny Hoff
// Date: 10/25/95
// Purpose: To implement the Bresenham's line drawing algorithm
for
// all slopes and line directions (using minimal
routines).
//===================================================================
//====================================================================
=
// Fills the intermediate points along a line between the two given
// endpoints using Bresenham's line drawing algorithm. NOTE: this
// routine does no clipping so the coordinate values must be within
the
// FrameBuffer bounds.
// NOTE: USE (Ax,Ay) as the starting point (values that are
// incremented)
//====================================================================
//--------------------------------------------------------------
-
// INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT
// AFFECTED BY THE SLOPE OR DIRECTION OF THE LINE
//--------------------------------------------------------------
int dX = abs(Bx-Ax); // store the change in X and Y of the
// line endpoints
int dY = abs(By-Ay);
//--------------------------------------------------------------
// DETERMINE "DIRECTIONS" TO INCREMENT X AND Y (REGARDLESS OF
// DECISION)
//--------------------------------------------------------------
-
int Xincr, Yincr;
if (Ax > Bx) { Xincr=-1;} else { Xincr=1;}//which direction in
X?
if (Ay > By) { Yincr=-1;} else { Yincr=1;}//which direction in
Y?
//--------------------------------------------------------------
// DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS INCREMENTS BY
// 1 (OR -1) )AND INITIATE APPROPRIATE LINE DRAWING ROUTINE
// (BASED ON FIRST OCTANT ALWAYS). THE X AND Y'S MAY BE FLIPPED
//IF Y IS THE INDEPENDENT VARIABLE.
//--------------------------------------------------------------
-
9
if (dX >= dY) // if X is the independent variable
{
int dPr = dY<<1; // amount to increment decision
// if right is chosen (always)
int dPru = dPr - (dX<<1); // amount to increment
// decision if up is chosen
int P = dPr - dX; // decision variable start
value
void display()
{
int i;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
BresLine(0,0,400,400);
10
glFlush();
glutSwapBuffers();
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glOrtho(0,399,0,399,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
O OpenGL dispe em sua biblioteca interna de um comando que plota uma reta por dois pontos dados.
Este comando descrito abaixo:
void display()
{
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex2f(x0,y0);
glVertex2f(x1,y1);
glEnd();
glFlush();
}
#include <gl\glut.h>
#include <stdio.h>
float funcao(float x)
{
return(x*x);
}
void display()
{
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
for(x=-1;x<1;x+=0.01)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
11
glEnd();
}
glFlush();
}
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
gluOrtho2D(-1,1,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
1) Acrescentando os eixos.
2) Criando uma varivel pontos que permita melhorar a discretizao.
3) Separa os programa em dois mdulos:
funcao01.cpp: funes bsicas de inicializao e controle do glut.
funcao02.cpp: funes grficas definidas com a tarefa especfica de plotar o grfico da
funo.
/* * * * * * * * * * * * * */
/* Modulo: Funcao01.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao02.h"
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
glFlush();
glutSwapBuffers();
}
12
/* * * * * * * * * * * * * */
/* Modulo: funcao02.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#define PI 3.1415926535897932384626433832795
/* -------------------------------- */
float funcao(float x)
/* -------------------------------- */
{
return(sin(x));
}
/* -------------------------------- */
void plota_eixo()
/* -------------------------------- */
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
/* -------------------------------- */
void plota_funcao()
/* -------------------------------- */
{
int i ;
float dx ;
float x,y;
dx = (xmax - xmin)/pontos;
glColor3f(1.0,0.0,0.0);
x = xmin;
for(i=0;i<pontos;i++)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
x = x + dx;
13
}
/* funcao02.h */
void plota_eixo();
void plota_funcao();
Nossa prxima etapa permitir que o usurio possa alterar o domnio de visualizao da funo
interativamente. Na prxima sesso apresentamos algumas das principais interrupes do glut que nos
permitiro executar esta tarefa.
14
2 TECLADO E MOUSE (Callbacks)
2.1 Introduo
O usurio pode interagir com o programa de duas formas principais: atravs do Mouse ou Teclado. Para
isso o GLUT dispe de dois tipos de funes (que denominamos Callbacks) especficas para habilitar a
utilizao do teclado e do mouse. Vamos descrev-las a seguir.
2.2 Teclado
Para registrar ocorrncias no teclado o GLUT dispe da funo:
Esta funo determina que quando uma tecla for pressionada, o controle do programa deve passar a
funo definida no campo (*func) e esta funo receber como parmetros de entrada, a tecla
pressionada (unsigned char key), e a posio do mouse (int x, int y). O exemplo abaixo
exemplifica uma aplicao para o programa funes.
/* * * * * * * * * * * * * * */
/* Modulo: funcao011.h */
/* * * * * * * * * * * * * * */
void plota_eixo();
void plota_funcao();
void entra_dominio();
15
2.3.2 - Mdulo funcao010.cpp
Este mdulo contm as rotinas bsicas do OpenGL e a abertura do programa (void main()). Observe
que a funo glutKeyboardFunc(le_tecla); informa que quando alguma tecla pressionada o
controle do programa deve passar a rotina void le_tecla(unsigned char key, int x,
int y).
/* * * * * * * * * * * * * * */
/* Modulo: funcao010.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
glFlush();
}
Neste mdulo separamos as rotinas que trabalham com a funo ser desenhada.
/* * * * * * * * * * * * * * */
/* Modulo: funcao011.cpp */
/* * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin,ymin,xmax,ymax,incremento;
float funcao(float x)
{
return(sin(x));
16
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
17
2.4 Mouse
O GLUT capaz de obter trs tipos de ocorrncias diferentes a partir do mouse. Vamos descrev-las a
seguir.
2.4.1- glutMouseFunc
void glutMouseFunc(void (*func)(int button, int state, int x, int y))
Este evento detecta quando algum boto do mouse foi pressionado. Quando isto ocorre, o programa
executa a rotina definida em void (*func). Os parmetros desta rotina podem receber os seguintes
valores:
- button : informa qual boto do mouse foi pressionado, sendo atribudo com um dos seguintes
valores: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON.
- state: informa quando o boto foi pressionado e quando o boto foi solto, sendo atribudo com dois
possveis valores: GLUT_DOWN ou GLUT_UP.
- X,y: informa a posio do mouse na janela quando o boto foi pressionado.
Como exemplo, vamos alterar o programa funo anterior, e acrescentar outra forma de interrupo
para alterar o domnio. Assim se o usurio pressionar o boto esquerdo do mouse, o programa solicita na
janela DOS o novo domnio de visualizao.
Para implementar esta alterao s precisamos mudar o programa funcao010.cpp. Seu novo cdigo
apresentado a seguir:
/* * * * * * * * * * * * * * */
/* Modulo: funcao010.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
glFlush();
}
switch(b) {
case GLUT_RIGHT_BUTTON:
18
switch(state) {
case GLUT_DOWN:
entra_dominio();
display();
break;
case GLUT_UP:
printf(" x = %d y = %d \n",x,y);
break;
}
break;
}
}
2.4.2- glutMotionFunc
void glutMotionFunc(void (*func)(int x, int y))
Este evento detecta o movimento do mouse enquanto algum boto do mouse est pressionado. Quando
isto ocorre, o programa executa a rotina definida em void (*func) e informa em x,y a posio do
mouse na janela.
No exemplo abaixo, a rotina le_botao_movimento_mouse(int x, int y) imprime a posio
do mouse enquanto mantemos um de seus botes pressionados.
/* * * * * * * * * * * * */
/* Programa mouse01.cpp */
/* * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glFlush();
}
19
2.4.3- glutPassiveMotionFunc
void glutPassiveMotionFunc(void (*func)(int x, int y))
Este evento detecta o movimento do mouse quanto nenhum boto do mouse est pressionado. Quando
isto ocorre, o programa executa a rotina definida em void (*func) e informa em x,y a posio do
mouse na janela.
No exemplo abaixo, a rotina le_movimento_mouse(int x, int y) imprime a posio do mouse
quando movimentamos o mouse dentro da janela OpenGL.
/* * * * * * * * * * * * */
/* Programa mouse02.cpp */
/* * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glFlush();
}
x = x(t)
y = y(t)
x = cos(t)
y = sen(t) onde 0 <= t <= 2*Pi
b) Ciclide (curva traada por um ponto da circunferncia quando o crculo rola sobre uma reta):
x = t - sen(t)
y = 1 - cos(t)
20
3.2 Exemplo: Visualizao de Curvas Paramtricas
Vamos implementar um programa que visualize curvas paramtricas. Observe que a diferena principal
para o programa funes que tanto a varivel x, quanto y devem ser calculadas em funo do parmetro
t. Vamos aproveitar uma boa parte da estrutura j implementada no programa funo. O programa
est dividido em dois mdulos principais:
- curvas010.cpp: Mantm as rotinas de visualizao do OpenGL
- curvas011.cpp: Mantm as rotinas relativas ao desenho da curva.
Temos ainda o mdulo:
- curvas011.h: Este mdulo deve ter apenas o cabealho das funes do programa
curvas011.cpp.
/* * * * * * * * * * * * * */
/* Modulo: Curvas010.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "curvas011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_curva();
glFlush();
}
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
entra_dominio();
display();
break;
case GLUT_UP:
break;
}
break;
}
}
21
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}
/* * * * * * * * * * * * * */
/* Modulo: Curvas011.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#define PI (4.0*atan(1.0))
float xmin = -1.0;
float ymin = -1.0;
float xmax = 1.0;
float ymax = 1.0;
float incremento = 0.01;
/* -------------------------------- */
void curva(float t,float *x,float *y)
/* float t (entrada) */
/* float *x (saida) */
/* float *y (saida) */
{
*x = cos(t);
*y = sin(t);
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_curva()
{
float x,y,t;
glColor3f(1.0,0.0,0.0);
for(t=0;t < 2*PI; t+=incremento)
{
curva(t,&x,&y);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
22
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Void plota_eixo();
Void plota_curva();
Void entra_dominio();
3.2.4 Exerccio
As coordenadas polares podem ser relacionadas com as coordenadas retangulares (ou cartesianas) atravs
das expresses abaixo:
23
r 2 = x 2 + y 2
y
tg ( ) =
x
x = r cos( )
y = r sen( )
Como exemplo de curvas na forma polar temos:
r = 1
=m
c) Circunferncia com centro em P(0, 0.5) e raio 1:
r = sin
d) Cardiide
r = a (1 + cos( ))
e) Espiral
r = a
f) Roscea
r = a sen(n )
r = f ( )
Em coordenadas cartesianas temos:
x = r cos( )
y = r sen( )
Substituindo r nas duas equaes obtemos:
x = f ( ) cos( )
y = f ( ) sen( )
Assim temos uma curva na forma paramtrica. Como exemplo vamos visualizar a curva do cardiide,
alterando apenas a rotina curva do programa anterior:
/* -------------------------------- */
void curva(float t,float *x,float *y)
/* float t (entrada) */
/* float *x (saida) */
/* float *y (saida) */
24
/* -------------------------------- */
/* -------------------------------- */
{
*x = (1+cos(t))*cos(t);
*y = (1+cos(t))*sin(t);
}
3.5 Exerccios
1) Como exerccio visualize as demais curvas dadas em coordenadas polares.
2) Visualize a curva dada em coordenadas polares por r = sec(theta).
25
4 RETAS E POLGONOS NO OPENGL
4.1 Retas e Polgonos
Alm de pontos e retas, o OpenGL possui no total 10 tipos de primitivas teis. Todos os modelos da
tabela abaixo devem ser utilizados iniciando com glBegin(...) e finalizando com glEnd(...),
por exemplo para o GL_LINES temos:
glBegin(GL_LINES);
glVertex2f(1.0,1.0);
glVertex2f(1.0,2.0);
glVertex2f(2.0,-2.0);
...
glEnd();
26
4.2 Exemplo: Visualizao dos Mtodos Numricos de Integrao
Como exemplo de aplicao dos novos objetos vamos visualizar alguns mtodos numricos de
integrao: ponto direita, ponto esquerda e trapzio.
Nosso programa ter trs mdulos principais:
- Intvis01.cpp: Mantm as rotinas de visualizao do OpenGL
- Intvis02.cpp: Mantm as rotinas relativas ao esboo do grfico da funo.
- Intvis03.cpp: Mantm as rotinas de visualizao dos mtodos numricos de integrao.
A seguir apresentamos o cdigo de cada um destes mdulos.
/* * * * * * * * * * * * * * */
/* Modulo: Intvis01.c */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "Intvis02.h"
#include "Intvis03.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
plota_integral();
glFlush();
glutSwapBuffers();
}
27
break;
case '0':
tipo = 0;
display();
break;
case '1':
tipo = 1;
display();
break;
}
}
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
visual = (visual + 1) % 2;
display();
break;
case GLUT_UP:
break;
}
break;
}
}
28
4.2.2 - Mdulo Intvis02.cpp
/* * * * * * * * * * * * * * */
/* Modulo: Intvis02.cpp */
/* * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float funcao(float x)
{
return(sin(x));
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
29
4.2.3 - Mdulo Intvis03.cpp
Neste mdulo separamos as rotinas que responsveis pela visualizao dos numricos mtodos de
integrao.
/* * * * * * * * * * * * * * */
/* Modulo: Intvis03.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include "Intvis02.h"
float a = 0;
float b = 1;
int tipo = 0;
int visual = 0;
int divisoes = 5;
void Integral_retangulo()
{
int i ;
float x,y;
float dx;
dx = (b-a)/divisoes;
for(i=0; i < divisoes; i++)
{
x = a+ i*dx;
y = funcao(x);
glColor3f(1.0,1.0,0.0);
if (visual == 0)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_POLYGON);
glVertex2f(x,y);
glVertex2f(x+dx,y);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
}
}
void Integral_trapezio()
{
int i ;
float x,y1,y2;
float dx;
dx = (b-a)/divisoes;
for(i=0; i < divisoes; i++)
{
x = a+ i*dx;
y1 = funcao(x);
y2 = funcao(x + dx);
glColor3f(1.0,1.0,0.0);
if (visual == 0)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_POLYGON);
30
glVertex2f(x,y1);
glVertex2f(x+dx,y2);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
}
}
void plota_integral()
{
switch(tipo) {
case 0:
Integral_retangulo();
break;
case 1:
Integral_trapezio();
break;
}
}
void entra_limites()
{
printf("Limites de Integracao \n");
printf("a = ");
scanf("%f",&a);
printf("\nb = ");
scanf("%f",&b);
printf("\ndivisoes = ");
scanf("%d",&divisoes);
}
31
4.3 Exemplo: Realizando Zoom do grfico
No processo de visualizao das funes, ou mesmo da integrao numrica, muitas vezes desejamos
alterar o domnio do nosso grfico. Para isso selecionamos a tecla D e d como uma interrupo do
teclado para que pudssemos informar o novo domnio. Uma forma mais gil seria selecionar com o
mouse interativamente um retngulo que gostaramos de visualizar. o que faremos no prximo
programa.
Para isso utilizaremos a funo glutMotionFunc(funcao) para selecionarmos a regio desejada.
Quando o boto direito do mouse pressionado, marcamos o ponto inicial da regio. Enquanto o mouse
est em movimento (com o boto direito pressionado), desenhamos o retngulo desejado. Quando o boto
do mouse solto, obtemos o ponto final da regio e atualizamos o domnio da funo.
Vamos incorporar ao programa Funcao.cpp a nova ferramenta de zoom.
/* * * * * * * * * * * * * * * * * */
/* Modulo: Funcao.cpp (com zoom) */
/* * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "plota.h"
int mov = 0; /* Detecta o movimento do mouse */
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
if (mov == 1)
plota_retangulo(xv1,yv1,xv2,yv2);
glFlush();
glutSwapBuffers();
}
32
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
redesenha();
break;
}
}
/* * * * * * * * * * * * * * * * */
/* Modulo: plota.cpp (com zoom) */
/* * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#include "funcao.h"
#define PI 3.1415926535897932384626433832795
/* -------------------------------- */
float funcao(float x)
/* -------------------------------- */
{
return(sin(50*PI*x));
}
/* -------------------------------- */
void plota_eixo()
/* -------------------------------- */
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
/* -------------------------------- */
void plota_funcao()
/* -------------------------------- */
{
int i ;
float dx ;
33
float x,y;
dx = (xmax - xmin)/pontos;
glColor3f(1.0,0.0,0.0);
x = xmin;
for(i=0;i<pontos;i++)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
x = x + dx;
}
}
/* -------------------------------- */
void plota_retangulo(int x,int y,int xv1,int yv1)
/* -------------------------------- */
{
float t;
float retxmin,retxmax,retymin,retymax;
t = (float)xv1 / 400.0;
retxmin = xmin + t * (xmax-xmin);
t = (float)x / 400.0;
retxmax = xmin + t * (xmax-xmin);
t = (float)y / 400.0;
retymin = ymax - t * (ymax-ymin);
t = (float)yv1 / 400.0;
retymax = ymax - t * (ymax-ymin);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(retxmin,retymin);
glVertex2f(retxmin,retymax);
glVertex2f(retxmax,retymax);
glVertex2f(retxmax,retymin);
glEnd();
}
/* -------------------------------- */
void entra_dominio()
/* -------------------------------- */
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
}
/* --------------------------------------------------------------- */
void recalcula_dominio(float xv_1,float yv_1,float xv_2,float yv_2)
/* --------------------------------------------------------------- */
34
{
float t;
float xmin1,xmax1;
float ymin1,ymax1;
t = (float)xv_1 / 400;
xmin1 = xmin + t * (xmax-xmin);
t = (float)xv_2 / 400;
xmax1 = xmin + t * (xmax-xmin);
xmin = xmin1;
xmax = xmax1;
t = (float)yv_2 / 400;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yv_1 / 400;
ymax1 = ymax - t * (ymax-ymin);
ymin = ymin1;
ymax = ymax1;
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
redesenha();
}
5 CURVAS IMPLCITAS
5.1 Introduo
J aprendemos na seo 3 como representar curvas na forma paramtrica. Vamos discutir agora outro tipo
de representao muito utilizada para curvas: a representao implcita.
A equao implcita de uma curva descreve uma relao entre as coordenadas x e y dos pontos que
pertencem a curva. Assim no plano xy a equao implcita de uma curva tem a forma :
f ( x, y ) = 0
Como exemplo a representao implcita de uma circunferncia de raio 1 centrado na origem dado por:
x2 + y2 1 = 0
Na forma paramtrica a mesma curva representada por:
x = cos(t )
0 t 2
y = sin(t )
Qual das duas representaes mais vantajosa em termos computacionais ? Na verdade ambas
representaes tm vantagens e desvantagens em comparao uma com a outra. Por exemplo, muito
simples determinar se um ponto P ( x 0 , y 0 ) dado pertence ou no a uma curva dada na forma implcita.
J na forma paramtrica simples determinar pontos que pertenam a curva, para que se possa fazer uma
representao grfica da curva (como foi feito na seo anterior). Vamos agora resolver este ltimo
problema para uma curva dada na forma implcita, ou seja, vamos representar graficamente a curva
implcita.
35
Assim a curva inicial desejada, ser a curva de nvel f ( x, y ) = 0 .
A estratgia para obter esta curva ser a seguinte:
- Vamos estabelecer um domnio [ 2,2] [ 2,2] no plano como partida (a priori no sabemos se
existem ou no pontos da curva nesse domnio).
- Em seguida discretizamos este domnio, determinando uma matriz de 10x10 pontos Pij ( xij , y ij ) ,
por exemplo.
- Para cada tringulo, observamos os sinais Vi = sinal( z ij ) obtidos em cada vrtice e temos as
seguintes situaes:
- Se V1 * V2 < 0, ento a funo se anula em um ponto entre V1 e V2. Este ponto pode ser
aproximado linearmente.
/* * * * * * * * * * * * * */
/* Modulo: impl010.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "impl011.h"
extern float xmin,xmax,ymin,ymax;
void display()
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
36
plota_eixo();
plota_curva_implicita();
glFlush();
glutSwapBuffers();
}
break;
case GLUT_UP:
printf(" x = %d y = %d \n",x,y);
break;
}
break;
}
}
/* * * * * * * * * * * * * */
/* Modulo: impl011.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
37
float ymax = 2.0;
float incremento = 0.1;
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void triangulo(float x1,float y1,float x2,float y2,float x3,float y3)
{
int i = 0;
float t;
float x[3],y[3];
float s1,s2,s3;
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glVertex2f(x3,y3);
glEnd();
s1 = funcao(x1,y1);
s2 = funcao(x2,y2);
s3 = funcao(x3,y3);
if (s1 == 0) {
x[i] = x1;
y[i] = y1;
i++;
}
if (s2 == 0) {
x[i] = x2;
y[i] = y2;
i++;
}
if (s3 == 0) {
x[i] = x3;
y[i] = y3;
38
i++;
}
if (i == 2) {
glLineWidth(2.0);
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex2f(x[0],y[0]);
glVertex2f(x[1],y[1]);
glEnd();
glLineWidth(1.0);
}
}
void plota_curva_implicita()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
for(y=ymin;y<ymax;y+=incremento)
{
triangulo(x,y,x+incremento,y,x,y+incremento);
triangulo(x+incremento,y+incremento,x,y+incremento,x+incremento,y);
}
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Divisoes =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
5.4 Exerccio
Como exerccio implemente as seguintes curvas implcitas:
1) x + y2 1 = 0 .
2
1
2) x y + = 0.
2 2
10
39
3) x
2
y2 = 0 .
4) 4 x 2 + 9 y 2 = 1
6 FRACTAIS
6.1 Conjuntos auto semelhantes
Exemplo 1: Um tringulo pode ser expresso como a unio de quatro tringulos congruentes e no
1
sobrepostos. Cada um dos tringulos congruente ao original por um fator s= e o tringulo um
2
conjunto auto-semelhante com k = 4.
Exemplo 2 (Tringulo de Sierpinski) : Este exemplo foi apresentado pelo matemtico Waclaw Sierpinski
(1882-1969). Neste exemplo, partindo de um tringulo, temos a unio de trs tringulos no sobrepostos
1
(portanto k = 3 ), cada um dos quais congruente ao original com um fator de escala s = . Em
2
seguida, o processo se repete para cada um dos trs tringulos, e assim sucessivamente.
40
6.2 Dimenso Hausdorff e o conceito de fractal
Definio: A dimenso Hausdorff de um conjunto auto-semelhante definido por:
ln k
d H (S ) =
ln(1 / s)
onde d H (S ) denota a dimenso Hausdorff.
Observe que no exemplo 1, a dimenso Hausdorff, coincide com a dimenso topolgica usual, uma vez
que uma regio em tem dimenso 2. Porm no exemplo 2, obtemos uma dimenso no inteira para o
2
tringulo de Sierpinski. Partindo desta observao, Mandelbrot sugeriu em 1977 a seguinte definio:
41
s fator de escala
x cos sen x a
T = s + onde angulo de rotao
y sen cos y b a
translao
b
6.3.1- Tringulo de Sierpinski
Para obter o tringulo de Sierpinski, utilizaremos uma aplicao que a partir de um tringulo, obtm trs
novos tringulos conforme a figura abaixo:
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "fract011.h"
42
extern int pontos;
int xp[2],yp[2];
int tamx = 400;
int tamy = 400;
int st = -1;
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(0.0,0.0,1.0,0.0,0.0,1.0,6);
glFlush();
glutSwapBuffers();
}
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xp[0] = x;
yp[0] = y;
st = 0;
printf("down %d %d ",x,y);
break;
case GLUT_UP:
xp[1] = x;
yp[1] = y;
printf("up %d %d ",x,y);
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)xp[1] / tamx;
xmax1 = xmin + t * (xmax-xmin);
xmin = xmin1;
xmax = xmax1;
t = (float)yp[1] / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
ymin = ymin1;
ymax = ymax1;
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
display();
break;
}
break;
}
}
void mov_mouse(int x, int y)
{
float t;
43
float xmin1,xmax1,ymin1,ymax1;
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)x / tamx;
xmax1 = xmin + t * (xmax-xmin);
t = (float)y / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
display();
glDrawBuffer(GL_FRONT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_STRIP);
glVertex2f(xmin1,ymin1);
glVertex2f(xmin1,ymax1);
glVertex2f(xmax1,ymax1);
glVertex2f(xmax1,ymin1);
glVertex2f(xmin1,ymin1);
glEnd();
glDrawBuffer(GL_BACK);
glFlush();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(tamx,tamy);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
gluOrtho2D(xmin,xmax,ymin,ymax);
glutKeyboardFunc(le_tecla);
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
glutMainLoop();
}
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
44
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao(float x0,float y0,
float x1,float y1,
float x2,float y2,
int n)
{
int i,j;
float x[3][3],y[3][3];
float e[3] = {0.0, 0.5, 0.0};
float f[3] = {0.0, 0.0, 0.5};
for(i=0;i<3;i++) {
x[i][0] = x0;
y[i][0] = y0;
x[i][1] = x1;
y[i][1] = y1;
x[i][2] = x2;
y[i][2] = y2;
}
for(i=0;i<3;i++)
for (j=0;j<3;j++)
funcao(&(x[j][i]),&(y[j][i]),e[j],f[j]);
if (n == 0) {
for (i=0;i<3;i++) {
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex2f(x[i][0],y[i][0]);
glVertex2f(x[i][1],y[i][1]);
glVertex2f(x[i][2],y[i][2]);
glEnd();
}
return;
}
else {
for(i=0;i<3;i++)
plota_funcao(x[i][0],y[i][0],x[i][1],y[i][1],
x[i][2],y[i][2],n-1);
}
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
45
6.3.1.2- Mdulo frac011.h
void plota_eixo();
void plota_funcao(float x0,float y0,float x1,float y1,
float x2,float y2,int n);
void entra_dominio();
Este mtodo utiliza iteraes randmicas para gerar fractais utilizando o seguinte processo:
1- Defina as k transformaes Tk (como descrito na seo 6.3) que descrevem o objeto a ser gerado.
x0
2- Escolha um ponto arbitrrio .
y0
3- Escolha arbitrariamente uma das k transformaes e aplique no ponto escolhido:
x x
T 0 = 1
y 0 y1
4- Prossiga escolhendo aleatoriamente uma das k transformaes e aplique no ultimo ponto obtido:
x x
T n 1 = n
y n 1 y n
Este mdulo idntico ao mdulo frac010.cpp, com apenas duas linhas de alterao como descrito
abaixo:
M
#include <math.h>
#include "fract021.h"
M
void display()
{
M
plota_funcao(1.5,-1.8);
46
}
/* * * * * * * * * * * * * * * * * **/
/* Triangulo Sierpinski Monte Carlo */
/* fract021.cpp */
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
for(i=0;i<20000;i++) {
j = (int) (3.0 * ((float)rand())/ RAND_MAX);
j = ( j > 2) ? 2 : j;
funcao(&x0,&y0,e[j],f[j]);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(x0,y0);
glEnd();
}
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
47
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
M
#include "fract031.h"
M
void display()
{
int i;
float x[4] = {0.0,1.0,1.0,0.0};
float y[4] = {0.0,0.0,1.0,1.0};
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(x,y,8);
glFlush();
}
/* * * * * * * * * * * */
/* Fractal Fern */
/* fract031.cpp */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin = -0.2;
float ymin = -0.2;
float xmax = 2;
float ymax = 2;
48
xx = a11 * *x1 + a12 * *y1 + e;
yy = a21 * *x1 + a22 * *y1 + f;
*x1 = xx;
*y1 = yy;
}
if (n == 0) {
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x[0],y[0]);
glVertex2f(x[1],y[1]);
glVertex2f(x[2],y[2]);
glVertex2f(x[3],y[3]);
glEnd();
return;
}
else {
for(i=0;i<4;i++) {
T( 0.20,-0.26, 0.23, 0.22,0.400,
0.045,&(xx[0][i]),&(yy[0][i]));
T( 0.85, 0.04,-0.04, 0.85,0.075,
0.180,&(xx[1][i]),&(yy[1][i]));
T( 0.00, 0.00, 0.00, 0.16,0.500,
0.000,&(xx[2][i]),&(yy[2][i]));
T(-0.15, 0.28, 0.26, 0.24,0.575,-
0.086,&(xx[3][i]),&(yy[3][i]));
}
plota_funcao(xx[0],yy[0],n-1);
plota_funcao(xx[1],yy[1],n-1);
plota_funcao(xx[2],yy[2],n-1);
plota_funcao(xx[3],yy[3],n-1);
}
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
49
6.3.4- Curva de Koch
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include "fract041.h"
void display()
{
int i;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
for(i=0;i<7;i++) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(-1.0,1.0,1.0,1.0,i);
plota_funcao( 1.0,1.0,0.0,-1.0,i);
plota_funcao(0.0,-1.0,-1.0,1.0,i);
glFlush();
glutSwapBuffers();
getch();
}
glFlush();
glutSwapBuffers();
}
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xp[0] = x;
yp[0] = y;
st = 0;
printf("down %d %d ",x,y);
break;
case GLUT_UP:
xp[1] = x;
yp[1] = y;
printf("up %d %d ",x,y);
50
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)xp[1] / tamx;
xmax1 = xmin + t * (xmax-xmin);
xmin = xmin1;
xmax = xmax1;
t = (float)yp[1] / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
ymin = ymin1;
ymax = ymax1;
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
display();
break;
}
break;
}
}
void mov_mouse(int x, int y)
{
float t;
float xmin1,xmax1,ymin1,ymax1;
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)x / tamx;
xmax1 = xmin + t * (xmax-xmin);
t = (float)y / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
display();
glDrawBuffer(GL_FRONT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_STRIP);
glVertex2f(xmin1,ymin1);
glVertex2f(xmin1,ymax1);
glVertex2f(xmax1,ymax1);
glVertex2f(xmax1,ymin1);
glVertex2f(xmin1,ymin1);
glEnd();
glDrawBuffer(GL_BACK);
glFlush();
}
/* * * * * * * * * * * */
51
/* Fractal Curva Koch */
/* fract041.cpp */
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
52
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
53
CAPTULO III VISUALIZAO E APLICAES GRFICAS 3D .............................2
1- TRANSFORMAES DE VISUALIZAO .................................................................2
1.1 - Comandos de Auxlio........................................................................................................2
1.2- Exemplo: cubo unitrio ..........................................................................................................3
1.3 - Transformaes de Modelagem e Visualizao...................................................................4
1.3.1- Translao ........................................................................................................................................ 4
1.3.2- Rotao............................................................................................................................................. 4
1.3.3- Escala ............................................................................................................................................... 5
1.3.4-Exemplo ............................................................................................................................................ 5
1.4- Projeo Ortogrfica ..............................................................................................................6
1.5- ngulos de Euler.....................................................................................................................6
1.6 - Criando um Ambiente de Visualizao 3D..........................................................................8
1.6.1- Mdulo Bsico de Visualizao....................................................................................................... 8
1.6.2- Alterando os ngulos de Euler ......................................................................................................... 9
1.7 Visualizao de grfico de funes z = f ( x, y ) ...............................................................10
1.7.1 Mdulo funcao3D010.cpp..................................................................................................... 11
1.7.2 - Mdulo funcao3D011.cpp ..................................................................................................... 13
1.7.3 - Mdulo funcao3D010.h ................................................................................................................ 14
2- ILUMINAO ................................................................................................................15
2.1 Criando Fontes de Luz.........................................................................................................15
2.1.1 Cor................................................................................................................................................. 15
2.1.2 Posio........................................................................................................................................... 16
2.2 Selecionando o Modelo de Iluminao ...............................................................................16
2.2.1- Luz Ambiente Global ..................................................................................................................... 16
2.2.2 Posio do observador local ou no infinito................................................................................... 16
2.2.3 Iluminao nos dois lados das faces ............................................................................................. 17
2.2.4 Habilitando a iluminao.............................................................................................................. 17
2.3 Selecionando as Propriedades do Material ........................................................................17
2.4 Exemplo.................................................................................................................................17
2.4.1- Mdulo Ilumina_main.cpp.................................................................................................... 17
2.4.2 Mdulo ilumina_funcao.cpp ............................................................................................. 22
2.4.3- Mdulo ilumina_set.cpp ...................................................................................................... 25
2.4.4 Mdulo ilumina_funcao.h .................................................................................................. 26
2.4.5 Mdulo ilumina_set.h ......................................................................................................... 26
3- SUPERFCIES PARAMETRIZADAS...........................................................................27
3.1 Visualizao de superfcies na forma paramtrica ...........................................................27
3.2 Exerccios ..............................................................................................................................33
4- INTERPOLAO ...........................................................................................................34
4 .1 Interpolao Utilizando o Mtodo de Shepard.................................................................34
4 .2 Propriedades do Mtodo de Shepard ................................................................................34
4 .3 Programa Interpolao Mtodo de Shepard ....................................................................35
1
CAPTULO III VISUALIZAO E APLICAES
GRFICAS 3D
1- TRANSFORMAES DE VISUALIZAO
Nosso objetivo nesta seo descrever a gerao de uma imagem bi-dimensional partindo de um objeto tri-
dimensional. De forma geral podemos dividir as operaes necessrias em trs grupos:
- Transformaes (representadas por multiplicao de matrizes) incluindo operaes de projeo,
visualizao e modelagem. Estas operaes incluem rotaes, escalas, translaes, reflexes, projees
ortogrficas e perspectivas.
- Operaes de Clipping so responsveis pela eliminao de objetos que esto fora da janela de
visualizao.
- Transformaes que estabeleam a correspondncia entre as coordenadas e a dimenso da tela (Viewport
transformation).
Para especificar uma transformao o OpenGL constri uma matriz 4x4 que representa a transformao
desejada. Esta matriz ento multiplicada pelas coordenadas de cada vrtice na cena. As transformaes de
Modelagem e Visualizao so combinadas em uma nica matriz denominada MODELVIEW matrix. A
transformao de projeo armazenada na PROJECTION matrix.
GlMatrixMode(Glenum tipo);
Este comando especifica a matriz a ser alterada. Existem trs argumentos conforme o tipo da matriz:
1) GL_MODELVIEW
2) GL_PROJECTION
3) GL_TEXTURE
As transformaes subsequentes afetam a matriz especificada. Observe que somente uma matriz pode ser
alterada por vez.
GlLoadIdentity(void);
Este comando carrega a matriz identidade na matriz corrente especificada anteriormente pelo
GlMatrixMode. O objetivo limpar qualquer alterao anterior realizada sobre a matriz.
2
GlLoadMatrix(const TYPE *M);
Quando voc deseja especificar uma matriz M particular para ser a matriz corrente, utilize o
glLoadMatrix(M).
V0 = {0,0,0}
V1 = {1,0,0}
V2 = {1,1,0}
V3 = {0,1,0}
V4 = {0,0,1}
V5 = {1,0,1}
V6 = {1,1,1}
V7 = {0,1,1}
#include <gl\glut.h>
void draw_cubo()
{
glBegin(GL_LINE_LOOP);
glVertex3f(0.0,0.0,0.0);
glVertex3f(1.0,0.0,0.0);
glVertex3f(1.0,1.0,0.0);
glVertex3f(0.0,1.0,0.0);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(0.0,0.0,1.0);
glVertex3f(1.0,0.0,1.0);
glVertex3f(1.0,1.0,1.0);
glVertex3f(0.0,1.0,1.0);
glEnd();
glBegin(GL_LINES);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.0,0.0,1.0);
glVertex3f(1.0,0.0,0.0);
glVertex3f(1.0,0.0,1.0);
glVertex3f(1.0,1.0,0.0);
glVertex3f(1.0,1.0,1.0);
glVertex3f(0.0,1.0,0.0);
glVertex3f(0.0,1.0,1.0);
glEnd();
}
void display()
3
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_cubo();
glFlush();
}
void inicia_config()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(45,0.0,1.0,0.0);
glRotatef(45.0,0.0,0.0,1.0);
}
1.3.1- Translao
void glTranslatef(float x, float y, float z);
x
Este comando multiplica a matriz corrente por uma matriz que translada o objeto conforme o vetor y .
z
1.3.2- Rotao
void glRotatef(float theta, float x, float y, float z);
Multiplica a matriz corrente por uma matriz que rotaciona o objeto no sentido anti-horrio de theta graus,
x
na direo do eixo dado pelo vetor y .
z
1.3.3- Escala
void glScalef(float x, float y, float z);
Este comando realiza transformaes de escala e reflexo. Cada ponto x, y e z do objeto multiplicado pelo
correspondente argumento x,y e z.
4
1.3.4-Exemplo
Como exemplo vamos apresentar um programa que executa as trs transformaes citadas acima. Partindo de
um tringulo, desenhamos este tringulo quatro vezes sendo que:
- O tringulo vermelho desenhado sem nenhuma transformao.
- O tringulo verde sofreu uma translao.
- O tringulo azul sofreu uma rotao.
- O tringulo amarelo sofreu uma transformao de escala.
#include <gl\glut.h>
#include <stdio.h>
void draw_triangulo()
{
glBegin(GL_LINE_LOOP);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.25,0.43,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
draw_triangulo();
glColor3f(0.0,1.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef( 0.5, 0.5,0.0);
draw_triangulo();
glColor3f(0.0,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(45,0.0,0.0,1.0);
draw_triangulo();
glColor3f(1.0,1.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(0.5, 0.5,0.5);
draw_triangulo();
glFlush();
}
5
1.4- Projeo Ortogrfica
Em uma projeo ortogrfica, ns estabelecemos um volume de visualizao (que corresponde a um
paraleleppedo retngulo). O objeto s ser visualizado se ele estiver contido neste volume. O comando
utilizado :
A seqncia inicia rotacionando o sistema de coordenadas xyz por um ngulo no sentido anti-horrio em
torno do eixo z.
6
Em seguida o sistema de coordenadas resultante rotacionado em torno do eixo y de graus.
Por fim o sistema de coordenadas sofre uma nova rotao de em torno do eixo z.
#include <gl\glut.h>
#include <stdio.h>
float gamma=90.0,phi=45.0,theta=135.0;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
7glVertex3f(0.0,0.0,0.0);
7
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_eixos();
glFlush();
}
void inicia_config()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
#include <gl\glut.h>
#include <stdio.h>
int xm,xb,ym,yb;
float gamma=90.0,phi=45.0,theta=135.0;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
8
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_eixos();
glFlush();
}
void inicia_config()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
#include <gl\glut.h>
#include <stdio.h>
#include "funcao3D010.h"
extern float ptx,pty;
extern float xmin,xmax,ymin,ymax;
int xb,yb,xm,ym;
float gamma=90.0,phi=45.0,theta=135.0;
float scale = 1.0;
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_eixos();
draw_funcao();
glFlush();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(scale,scale,scale);
glRotatef(gamma,0.0,0.0,1.0);
10
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
}
void botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
void mov_mouse(int x, int y)
{
xm = x;
ym = y;
theta = theta + xm - xb;
phi = phi - ym + yb ;
inicia_config();
theta = theta - xm + xb;
phi = phi + ym - yb;
display();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case '+':
scale+=0.2;
inicia_config();
display();
break;
case '-':
scale-=0.2;
inicia_config();
display();
break;
}
}
void main(int argc, char **argv)
{
printf("\nxmin = ");
scanf("%f",&xmin);
printf("\nxmax = ");
scanf("%f",&xmax);
11
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\nPontos em x = ");
scanf("%f",&ptx);
printf("\nPontos em y = ");
scanf("%f",&pty);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cubo 3D");
glutDisplayFunc(display);
inicia_config();
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
glutKeyboardFunc(le_tecla);
glutMainLoop();
}
#include <gl/glut.h>
#include <math.h>
float xmin,xmax,ymin,ymax;
float ptx,pty;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void draw_funcao()
{
float x,y;
float stepx,stepy;
float z0,z1,z2,z3;
12
stepx = (xmax-xmin)/ptx;
stepy = (ymax-ymin)/pty;
glColor3f(1.0,1.0,1.0);
for(x=xmin;x<=xmax;x+=stepx)
{
for(y=ymin;y<=ymax;y+=stepy)
{
z0 = funcao(x,y);
z1 = funcao(x+stepx,y);
z2 = funcao(x+stepx,y+stepy);
z3 = funcao(x,y+stepy);
glBegin(GL_LINE_LOOP);
glVertex3f(x,y,z0);
glVertex3f(x+stepx,y,z1);
glVertex3f(x+stepx,y+stepy,z2);
glVertex3f(x,y+stepy,z3);
glEnd();
}
}
}
void draw_eixos();
void draw_funcao();
void plota_curvas_nivel(float ci,float cf);
void triangulo(float x1,float y1,float x2,float y2,float x3,float y3);
void plota_curva_nivel();
13
2- ILUMINAO
Para definir o seu modelo de iluminao so necessrias trs etapas bsicas:
1) Definir as fontes de luz (posio, cor, direo, etc.);
2) Definir a iluminao.
3) Definir o tipo de material do objeto.
O modelo de iluminao do OPENGL considera que a iluminao pode ser dividida em quatro componentes
independentes: emitida, ambiente, difusa e especular.
- Luz Emitida: a componente que se origina de um objeto e inalterada pelas fontes de luz.
- Luz Ambiente: a luz proveniente de uma fonte dispersa tal que sua direo no pode ser determinada.
- Luz Difusa: a luz proveniente de uma nica direo.
- Luz Especular: a luz proveniente de uma direo particular e tende a refletir em uma direo
preferencial.
O parmetro luz indica apenas qual fonte de luz estamos trabalhando. Existem no mximo oito fontes que so:
GL_LIGHT0, GL_LIGHT1, ... , GL_LIGHT7. Por default a luz GL_LIGHT0 inicia com a cor
branca e as sete luzes restantes ficam apagadas (luz preta).
2.1.1 Cor
2.1.2 Posio
- Direcional: quando a fonte de luz considerada no infinito. Neste caso os raios de luz incidem
paralelos ao objeto. Para obter, por exemplo, uma fonte de luz branca voc deve utilizar o seguinte
cdigo:
- Posicional : Se o ltimo valor do vetor luz_posicao[] for diferente de zero, a luz posicional e
sua localizao definida pelo vetor luz_posicao[4]={x , y, z, 1.0}.
Cada fonte de luz pode contribuir com uma parcela da luz ambiente. Alm disso possvel adicionar uma
outra parcela de luz ambiente que no dependa das fontes de iluminao. Para isso utiliza-se o comando:
Observe que neste caso, mesmo que todas as fontes de luz estejam desligadas ainda assim ser possvel ver os
objetos na cena.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
O clculo da iluminao feito para todos os polgonos. possvel considerar diferentes iluminaes nos dois
lados de um polgono. Para isso utilize:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
No OpenGL voc precisa explicitamente habilitar a iluminao. Para isso utilize o comando:
glEnable(GL_LIGHTING);
glDisable(GL_LIGHTING);
15
2.3 Selecionando as Propriedades do Material
Para definir as propriedades do material do objeto em cena utilizamos os seguinte comando:
2.4 Exemplo
O exemplo abaixo altera o programa funcao3D, e permite que o usurio altere algumas propriedades da
iluminao. O programa esta dividido em trs mdulos: Ilumina_funcao.cpp,
Ilumina_main.cpp, ilumina_set.cpp.
#include <gl\glut.h>
#include <stdio.h>
#include "ilumina_funcao.h"
#include "ilumina_set.h"
int type_light = 0;
int xb,yb,xm,ym;
float gamma=90.0,phi=45.0,theta=135.0;
float scale = 1.0;
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_NORMALIZE);
glColor3f(1.0,1.0,0.0);
draw_eixos();
16
draw_funcao();
glFlush();
glutSwapBuffers();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, light[2]);
glScalef(scale,scale,scale);
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
}
void botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
void mov_mouse(int x, int y)
{
xm = x;
ym = y;
theta = theta + xm - xb;
phi = phi - ym + yb ;
inicia_config();
theta = theta - xm + xb;
phi = phi + ym - yb;
display();
}
}
}
#include <gl/glut.h>
#include <math.h>
#include "ilumina_set.h"
float xmin,xmax,ymin,ymax;
float ptx,pty;
float funcao(float x,float y)
{
// return(sqrt(x*x+y*y));
// return(y*y-x*x);
// return(x*x+y*y);
// return(-x-y+1);
return(sin(sqrt(x*x+y*y)));
}
20
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
v1[0] = dx ;
v1[1] = 0.0;
v1[2] = funcao(x+dx,y)-funcao(x,y);
v2[0] = 0.0;
v2[1] = dy;
v2[2] = funcao(x,y+dy)-funcao(x,y);
desabilita_lighting();
glColor3f(1.0,1.0,0.0);
z1 = dfx(x,y)/10.0; /* Derivada parcial com relacao a x */
z2 = dfy(x,y)/10.0; /* Derivada parcial com relacao a y */
z = funcao(x,y);
glBegin(GL_LINES);
glVertex3f(x,y,z);
glVertex3f(x-z1,y-z2,z+0.1);
glEnd();
habilita_lighting();
}
21
void draw_funcao()
{
float x,y;
float stepx,stepy;
float z0,z1,z2,z3;
float v[3];
stepx = (xmax-xmin)/ptx;
stepy = (ymax-ymin)/pty;
habilita_lighting();
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(1.0,1.0,0.0);
glColorMaterial(GL_BACK , GL_DIFFUSE);
glColor3f(1.0,0.0,0.2);
for(x=xmin;x<=xmax;x+=stepx)
{
for(y=ymin;y<=ymax;y+=stepy)
{
z0 = funcao(x,y);
z1 = funcao(x+stepx,y);
z2 = funcao(x+stepx,y+stepy);
z3 = funcao(x,y+stepy);
glBegin(GL_QUADS);
normalv(v,x,y,stepx,stepy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x,y,z0);
normalv(v,x+stepx,y,stepx,stepy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+stepx,y,z1);
normalv(v,x+stepx,y+stepy,stepx,stepy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+stepx,y+stepy,z2);
normalv(v,x,y+stepy,stepx,stepy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x,y+stepy,z3);
glEnd();
draw_normal(x,y);
}
}
desabilita_lighting();
}
#include <gl\glut.h>
#include <stdio.h>
/*---------------------------------------------------------------*/
void desabilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHT0);
}
/*---------------------------------------------------------------*/
void habilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glShadeModel(GL_FLAT);
glEnable(GL_NORMALIZE);
glLightfv(GL_LIGHT0, GL_AMBIENT , light[0]);
glLightfv(GL_LIGHT0, GL_DIFFUSE , light[1]);
glLightfv(GL_LIGHT0, GL_POSITION , light[2]);
glLightfv(GL_LIGHT0, GL_SPECULAR , light[3]);
glLightf (GL_LIGHT0, GL_SPOT_CUTOFF , spot_cutoff);
glLightf (GL_LIGHT0, GL_SPOT_EXPONENT , spot_exponent);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION , spot_direction);
glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION , c_attenuation);
glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION , l_attenuation);
glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION , q_attenuation);
glEnable(GL_LIGHT0);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE , GL_TRUE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light[7]);
glEnable(GL_LIGHTING);
23
3- SUPERFCIES PARAMETRIZADAS
Para compreender a idia de uma superfcie parametrizada, considere D uma regio do plano, cujas variveis
so denotadas por (u , v) . A cada par (u , v ) de D vamos associar um ponto (u , v ) no espao tri-
dimensional, o qual pode ser escrito em termos de suas funes coordenadas por:
/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Superficies Parametrizadas */
/* */
/* Modulo: Sup_main.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include "Sup_param.h"
int type_light = 0;
24
int xb,yb,xm,ym;
float gamma=90.0,phi=45.0,theta=135.0;
float scale = 1.0;
/*---------------------------------------------------------------*/
void desabilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
glDisable(GL_LIGHT2);
}
/*---------------------------------------------------------------*/
void habilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glShadeModel(GL_SMOOTH);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE , GL_TRUE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light[7]);
glEnable(GL_LIGHTING);
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_NORMALIZE);
glColor3f(1.0,1.0,0.0);
draw_eixos();
draw_superficie();
glFlush();
glutSwapBuffers();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLightfv(GL_LIGHT0, GL_POSITION, light[2]);
glScalef(scale,scale,scale);
26
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
}
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Superficies Parametrizadas */
/* */
/* Modulo: Sup_param.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */
#include <gl/glut.h>
#include <math.h>
#include "Sup_param.h"
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
parametrizacao(u,v,&x1,&y1,&z1);
parametrizacao(u,v+dy,&x2,&y2,&z2);
parametrizacao(u+dx,v,&x3,&y3,&z3);
v1[0] = x2-x1 ;
v1[1] = y2-y1;
v1[2] = z2-z1;
v2[0] = x3-x1;
v2[1] = y3-y1;
v2[2] = z3-z1;
void draw_superficie()
{
float x,y,z;
float u,v;
float stepu,stepv;
float z0,z1,z2,z3;
float n[3];
stepu = (umax-umin)/ptx;
stepv = (vmax-vmin)/pty;
habilita_lighting();
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(1.0,1.0,0.0);
glColorMaterial(GL_BACK , GL_DIFFUSE);
glColor3f(1.0,0.0,0.2);
for(u=umin;u<=umax;u+=stepu)
{
for(v=vmin;v<=vmax;v+=stepv)
{
glBegin(GL_QUADS);
parametrizacao(u,v,&x,&y,&z);
normalv(n,u,v,stepu,stepv);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(x,y,z);
parametrizacao(u+stepu,v,&x,&y,&z);
normalv(n,u+stepu,v,stepu,stepv);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(x,y,z);
parametrizacao(u+stepu,v+stepv,&x,&y,&z);
normalv(n,u+stepu,v+stepv,stepu,stepv);
glNormal3f(n[0],n[1],n[2]);
29
glVertex3f(x,y,z);
parametrizacao(u,v+stepv,&x,&y,&z);
normalv(n,u,v+stepv,stepu,stepv);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(x,y,z);
glEnd();
}
}
desabilita_lighting();
}
3.2 Exerccios
1) Utilizando o programa anterior, visualize as seguintes superfcies e identifique-as:
a) b) c) d)
x = sen( ) cos( ) x = 2u cos( ) x = 2u cos( ) x = cos( )
y = sen( ) sen( ) y = 2u sen( ) y = 2u sen( ) y = sen( )
z = cos( ) z = 2u z = 4u 2 z=u
0 0u4 0 u 1 0u4
0 2 0 2 0 2 0 2
e) f) g)
x = 2u cos( ) u
x = cos(u ) + v cos( 2 ) cos(u )
x=u
y = 2u sen( ) u
y = sen(u ) + v cos( ) sen(u ) y=v
z = 2u 2 z = u 2 + v 2
u
z = v sen( )
0u4 2
0 u 1
0.2 v 0.2
0 2 0 u 2 0 v 1
30
4- INTERPOLAO
Considere o seguinte problema:
- Dados n pontos distintos no plano ( xi , yi ) com os respectivos valores z i associados, determine uma
funo f tal que:
f ( xi , y i ) = z i i = 0,K , n 1
n 1
f ( x, y ) = z i v i ( x, y )
i =0
onde
1
wi ( x, y ) wi = q
vi ( x, y ) = n 1 e ri
wk ( x, y) ri = ( x xi ) + ( y yi ) 2
k =0
2
n 1
r
j =0 , j i
j
q
v i ( x, y ) = n 1 n 1
( r
k =0 j = 0, j k
q
j )
n 1
1) Desde que v i ( x, y ) 0 e v
k =0
k ( x, y ) = 1 ento
min z i f ( x, y ) max z i
i i
2) Se z i 0 , i = 0, K, n 1 f ( x, y ) 0
3) Se z i = c , i = 0, K , n 1 f ( x, y ) = c
31
4 .3 Programa Interpolao Mtodo de Shepard
/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Interpolao */
/* */
/* Modulo: interp.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include "interp.h"
int xb,yb,xm,ym;
float gamma=90.0,phi=45.0,theta=135.0;
float scale = 1.0;
int type_light = 0;
int N;
float *xp;
float *yp;
float *zp;
/*---------------------------------------------------------------*/
void desabilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
}
/*---------------------------------------------------------------*/
void habilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
// glShadeModel(GL_FLAT);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE , GL_TRUE);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, visgl_lmodel_ambient);
glEnable(GL_LIGHTING);
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_NORMALIZE);
glColor3f(1.0,1.0,0.0);
draw_eixos();
draw_funcao();
draw_points();
glFlush();
glutSwapBuffers();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(scale,scale,scale);
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
}
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
33
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
}
}
for(i=0;i<N;i++) {
printf("\n x,y,z = ");
scanf("%f,%f,%f",&xp[i],&yp[i],&zp[i]);
}
glutInit(&argc,argv);
34
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cubo 3D");
glutDisplayFunc(display);
inicia_config();
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
glutKeyboardFunc(le_tecla);
glutMainLoop();
}
/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Interpolao */
/* */
/* Modulo: Interp_f.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "interp.h"
extern int N;
extern float *xp;
extern float *yp;
extern float *zp;
int q = 1.0;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
p = (float *)malloc(N*sizeof(float));
for(j=0;j<N;j++) {
p[j] = 1.0;
for(i=0;i<N;i++) {
if (i != j)
p[j] *= pow(sqrt((xx-xp[i])*(xx-xp[i])+(yy-yp[i])*(yy-
yp[i])),q);
}
}
for(j=0;j<N;j++)
sv += p[j];
for(i=0;i<N;i++)
s+=zp[i]*p[i]/sv;
free(p);
return(s);
}
v1[0] = dx ;
v1[1] = 0.0;
v1[2] = interp(x+dx,y)-interp(x,y);
v2[0] = 0.0;
v2[1] = dy;
v2[2] = interp(x,y+dy)-interp(x,y);
desabilita_lighting();
glColor3f(1.0,1.0,0.0);
normalv(v,x,y,dx,dy);
z = interp(x,y);
glBegin(GL_LINES);
glVertex3f(x,y,z);
glVertex3f(x+v[0],y+v[1],z+v[2]);
glEnd();
habilita_lighting();
}
void draw_funcao()
{
36
int i;
float v[3];
float dx,dy;
float px = 20;
float py = 20;
float x,y;
float xmin = -2.0;
float ymin = -2.0;
float xmax = 2.0;
float ymax = 2.0;
dx = (xmax - xmin)/px;
dy = (ymax - ymin)/py;
habilita_lighting();
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(1.0,0.0,0.0);
glColorMaterial(GL_BACK, GL_DIFFUSE);
glColor3f(0.0,0.0,1.0);
for(x=xmin;x<xmax;x+=dx)
{
for(y=ymin;y<ymax;y+=dy)
{
glBegin(GL_QUADS);
normalv(v,x,y,dx,dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x ,y ,interp(x ,y ));
normalv(v,x+dx,y,dx,dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+dx,y ,interp(x+dx,y ));
normalv(v,x+dx,y+dy,dx,dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+dx,y+dy,interp(x+dx,y+dy));
normalv(v,x,y+dy,dx,dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x ,y+dy,interp(x ,y+dy));
glEnd();
draw_normal(x,y,dx,dy);
glColor3f(1.0,0.0,0.0);
}
}
desabilita_lighting();
for(i=0;i<N;i++)
printf("z[%d]=%f, zcalc=%f\n",i,zp[i],interp(xp[i],yp[i]));
}
void draw_points()
{
int i;
glColor3f(0.0,0.0,1.0);
glPointSize(3.0);
glBegin(GL_POINTS);
for(i=0;i<N;i++)
glVertex3f(xp[i],yp[i],zp[i]);
glEnd();
}
37
1
Captulo I Introduo a Linguagem C++ ____________________________________ 3
1. ESTRUTURA BSICA DE UM PROGRAMA EM C++ __________________________ 3
1.1 - Primeiro Programa______________________________________________________________ 3
1.2 - Variveis _____________________________________________________________________ 4
1.2.1 - Constantes ________________________________________________________________ 4
1.3 - Operadores____________________________________________________________________ 5
1.4 - Comentrios___________________________________________________________________ 6
1.5 - Fluxo de Controle ______________________________________________________________ 7
1.5.1 - Comando if () {} _______________________________________________________ 7
1.5.2 - Comando for( ; ; ) {} _________________________________________________ 8
1.5.3 - Comando while() {} e do { } while();______________________________ 11
1.5.4 - Comando break e continue ______________________________________________ 14
1.6 - Funes _____________________________________________________________________ 15
1.6.1 Referncia _______________________________________________________________ 17
2 - VETORES E MATRIZES __________________________________________________ 19
2.1 - Vetores______________________________________________________________________ 19
2.1.1 - Declarao _______________________________________________________________ 19
2.1.2 Exemplo: Mtodo de Ordenao______________________________________________ 20
2.2 - Matrizes _____________________________________________________________________ 21
3 - PONTEIROS ____________________________________________________________ 22
3.1 - Introduo ___________________________________________________________________ 22
3.2 Principais Aplicaes de Ponteiros________________________________________________ 22
3.3 Armazenando o Endereo das Variveis ___________________________________________ 22
3.4 Acessando o contedo de um endereo ____________________________________________ 23
3.5 Ponteiros com Vetores _________________________________________________________ 24
3.6 Alocao de Vetores Dinamicamente______________________________________________ 25
3.7 Alocao de Matrizes Dinamicamente _____________________________________________ 26
4 OBJETOS E CLASSES ___________________________________________________ 27
4.1 Membros da Classe ____________________________________________________________ 27
4.2 Construtores _________________________________________________________________ 28
4.3 Controle de Acesso aos Campos e Funes _________________________________________ 30
4.3.1 - Seo Pblica_____________________________________________________________ 30
4.3.2 - Seo Privada_____________________________________________________________ 30
Exemplo 1: ____________________________________________________________________ 30
Exemplo 2: ____________________________________________________________________ 30
4.3 Funes Membros_____________________________________________________________ 31
4.3.1 - Introduo _______________________________________________________________ 31
4.3.2 Acesso as variveis da classe ________________________________________________ 31
4.3.4 Exemplo de uma Classe Vetor _______________________________________________ 35
2
Captulo I Introduo a Linguagem C++
C++ uma linguagem de programao orientada a objeto desenvolvida por Bjarne
Stroustrup.
Hello.cpp
//====================================================================
// Name : Hello.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//====================================================================
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!!!" << endl; // prints Hello World!!!
return 0;
}
Os programas em C++ sempre iniciam pela funo main() (o termo funo ser
explicado depois), Seguindo o nome da funo seguem as chaves {} que delimitam o
incio e o fim da funo.
Neste exemplo o cout e return so os dois nicos comandos da funo main(). O
comando cout imprime mensagens na tela padro e como ser visto mais tarde, tambm
imprime o contedo de variveis. Observe que aps todo comando dentro de uma funo
segue um ponto e vrgula ( ; ). O comando return indica o fim da funo e neste
exemplo que o valor 0 retornado como resultado da execuo da funo main.
Os caracteres em branco so invisveis para o compilador. Assim o programa acima
tambm poderia ser (O cometrio precisa ser retirado para que funcione):
#include <iostream>
using namespace std;
int main() { cout << "Hello World!!!" << endl; return 0; }
3
1.2 - Variveis
O programa a seguir exibe como feita a declarao de algumas variveis e sua utilizao.
Variveis.cpp
#include <iostream>
using namespace std;
int main() {
int n = 1;
float a = 2.3e10f;
double b = 34.5e200;
cout << "n = " << n << " a = " << a << " b = " << b << endl;
}
int n;
Tipo da varivel Nome da varivel
n = 1;
1.2.1 - Constantes
Uma constante um valor constante que definido no programa de forma que no ser
alterado durante toda a execuo. Para declararmos uma constante utilizamos o prefixo
const, como no exemplo:
Variaveis.cpp
#include <iostream>
int main() {
const int a = 1;
etc
}
4
1.3 - Operadores
i = i + 1;
i++;
Como exemplo dos operadores, o programa abaixo calcula as razes reais de um polinmio
de segundo grau:
Raizes.cpp
#include <iostream>
#include <cmath>
int main() {
double a, b, c;
double x1, x2;
a = 1;
b = -5;
c = 6;
x1 = (-b + sqrt(b * b - 4* a * c)) / (2 * a);
x2 = (-b - sqrt(b * b - 4* a * c)) / (2 * a);
std::cout << "x1 = " << x1 << " x2 = " << x2;
}
5
1.4 - Comentrios
Formato 1:
/* Comentario pode prosseguir por varias
linhas e so termina ao encontar a marca de fim de
comentario */
Format 2:
// Comentario somente at o final da linha
#include <iostream>
#include <cmath>
int main() {
std::cout << "x1 = " << x1 << " x2 = " << x2;
}
6
1.5 - Fluxo de Controle
for( ; ;) { }
while() {}
do { } while();
1.5.1 - Comando if () {}
Atravs deste comando o fluxo do programa pode ser desviado para executar ou no um
conjunto de comandos. Considere o exemplo abaixo:
ParImpar.cpp
#include <iostream>
using namespace std;
int i, n;
i = n % 2;
if (i == 0) {
cout << n << " e um numero par\n";
} else {
cout << n << " e um numero impar\n";
}
}
Neste exemplo a varivel i armazena o resto da diviso de n por 2. Caso seja zero, ento o
programa passa a execuo do comando cout << n << " e um numero par\n". Se a
condio falha, o comando else indica que o programa deve executar o comando cout
<< n << " e um numero impar\n". Observe que o else um comando opcional.
Caso voc no o inclua, o programa segue para o prximo comando aps o if.
Os testes utilizam os seguintes operadores relacionais:
< Menor
> Maior
<= Menor ou igual
>= Maior ou igual
== Igual
!= Diferente
&& e
! negao
|| ou
7
1.5.2 - Comando for( ; ; ) {}
Fibonacci.cpp
#include <iostream>
#include <cmath>
using namespace std;
O resultado ser:
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
10: 55
8
O comando for composto de trs argumentos:
for( n=0 ; n<= 10 ; n++ )
Expresso de inicializao Expresso de teste Incremento
Expresso de inicializao
Inicializa a varivel do lao. A inicializao feita uma nica vez quando o lao inicia.
Expresso de teste
Esta expresso testa (a cada vez que o conjunto de comandos no interior do for finaliza), se
o lao deve ser encerrado. Enquanto a expresso for verdadeira o lao repetido. Para
realizar teste utilizamos os operadores relacionais.
Expresso de incremento
A cada repetio do lao, o terceiro argumento (n++) incrementa a varivel n.
PontoEsquerda.cpp
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int i;
int n;
double x, dx;
double a, b;
double soma;
cout.precision(20);
soma = 0.0;
dx = (b - a) / n;
9
x = a;
for (i = 0; i < n; i++) {
soma = soma + 2* sqrt(1 - x * x) * dx;
x = x + dx;
}
cout << "\n Integral = " << soma ;
cout << "\n Pi = " << M_PI;
cout << "\n Erro = " << (soma - M_PI);
}
MonteCarlo.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
double x, y, f;
int cont = 0;
const int points = 500000;
srand(1);
cout.precision(20);
#define PI 3.14159265358979323846264338327950288419716939937510
10
int main() {
int n;
double x, dx;
double a, b;
double soma;
cout.precision(20);
Este segundo tipo de lao adequado para situaes onde no sabemos ao certo quantas
vezes o lao deve ser repetido.
while (condio) {
...
comandos
...
}
do {
...
comandos
...
11
} while (condio);
utilizando o mtodo de Newton, ou seja, dada uma condio inicial e um erro mximo, a
seqncia abaixo pode convergir para uma das solues:
#include <iostream>
#include <cmath>
using namespace std;
/* Metodo de Newton */
int main() {
double xn, xn_1;
double erro;
xn = 2; // Condicao inicial
erro = 1e-10; // Erro maximo
cout.precision(20);
do {
xn_1 = xn;
xn = xn_1 - (xn_1 * xn_1 - 2) / (2 * xn_1);
cout << "Solucao parcial = " << xn << endl;
} while (fabs(xn - xn_1) > erro);
12
Exemplo: Mtodo da Bisseo
Bissecao.cpp
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a,b,c;
double fa,fb,fc;
const double erro = 0.0000001;
cout.precision(20);
cout << "Entre com o extremo a: ";
cin >> a;
cout << "Entre com o extremo b: ";
cin >> b;
fa = a*a - 2;
fb = b*b - 2;
if (fa * fc < 0) {
b = c;
}
else {
if (fb * fc < 0)
a = c;
else
break;
}
cout << "Solucao parcial = " << c << endl;
}
cout << "Solucao obtida = " << c << endl;
cout << "Raiz 2 = " << M_SQRT2 << endl;
}
13
1.5.4 - Comando break e continue
Estes dois comando servem para auxiliar na interrupo do lao, cumprindo diferentes
tarefas:
Exemplobreak.cpp
#include <iostream>
using namespace std;
int main() {
int n = 0;
n = 0
n = 1
n = 2
n = 3
n = 4
Fim do programa
14
1.6 - Funes
As funes cumprem como primeiro papel evitar repeties desnecessrias de cdigo. Nos
exemplos anteriores foi necessrio calcular o valor y = x*x-2 em diversas partes do
programa. Se desejssemos trocar a funo, seria necessrio alterar vrias partes do cdigo.
Para evitar isso, podemos utilizar uma funo como no exemplo abaixo:
Bissecao.cpp
#include <iostream>
#include <cmath>
using namespace std;
float f(float x)
{
float y;
y = x*x-2;
return(y);
}
int main() {
double a,b,c;
double fa,fb,fc;
const double erro = 0.0000001;
cout.precision(20);
cout << "Entre com o extremo a: ";
cin >> a;
cout << "Entre com o extremo b: ";
cin >> b;
fa = f(a);
fb = f(b);
if (fa * fc < 0)
b = c;
else {
if (fb * fc < 0)
a = c;
else
break;
}
cout << "Solucao parcial = " << c << endl;
}
cout << "Solucao obtida = " << c << endl;
cout << "Raiz 2 = " << M_SQRT2 << endl;
}
15
Vamos examinar alguns detalhes da funo introduzida:
float f (float
x)
Define o tipo Nome Parmetro de
que ser da entrada
retornado funo
{
float y;
y = x * x - 2;
return(y);
Valor a ser
retornado
}
Uma observao importante que as variveis dentro da funo no so conhecidas fora da
funo e vice-versa. Considere o seguinte programa:
Funcao.cpp
#include <iostream>
using namespace std;
int teste(int k)
{
k = k + 20;
cout << "Dentro da funcao k = " << k << endl;
return(k);
}
int main()
{
int i,j;
i = 1;
cout << "Fora da funcao i = " << i << endl;
j = teste(i);
cout << "Fora da funcao i = " << i << endl;
cout << "Fora da funcao j = " << j << endl;
}
O resultado ser:
Fora da funcao i = 1
Dentro da funcao k = 21
Fora da funcao i = 1
Fora da funcao j = 21
16
Observe que o valor da varivel i no tem seu contedo alterado pela funo. Isto ocorre
porque quando uma funo chamada durante o programa, o parmetro de entrada
(varivel i) tem seu contedo copiado para uma nova varivel declarada na funo
(varivel k). Observe que a varivel i e j no so conhecidas dentro da funo teste().
1.6.1 Referncia
Muitas vezes gostaramos que os argumentos de entrada da funo pudessem ter seus
valores alterados quando a funo finalizasse. Para isso utilizamos uma referncia para o
parmetro de entrada como ilustra o exemplo abaixo:
Referencia.cpp
#include <iostream>
using namespace std;
int teste(int& k)
{
k = k + 20;
cout << "Dentro da funcao k = " << k << endl;
return(k);
}
int main()
{
int i,j;
i = 1;
cout << "Fora da funcao i = " << i << endl;
j = teste(i);
cout << "Fora da funcao i = " << i << endl;
cout << "Fora da funcao j = " << j << endl;
}
O resultado ser:
Fora da funcao i = 1
Dentro da funcao k = 21
Fora da funcao i = 21
Fora da funcao j = 21
Quando o parmetro da funo declarado com o smbolo & antes do nome da varivel,
ento qualquer alterao no corpo da funo do parmetro de entrada, acessa o argumento
de entrada utilizado na chamada da funo. Nesse caso o parmetro de entrada uma
referncia.
17
Exemplo: Vamos construir uma funo cujo objetivo permutar os valores de duas
variveis dadas. No seria possvel permutar os dois valores atravs de uma funo como
abaixo:
Nao_Permuta.cpp
/* Este programa NO consegue permutar os valores */
#include <iostream>
auxiliar = x;
x = y;
y = auxiliar;
}
int main()
{
float x = 1.2f;
float y = 56.89f;
troca(x,y);
std::cout << "x = " << x << " e y = " << y << std::endl;
}
#include <iostream>
auxiliar = x;
x = y;
y = auxiliar;
}
int main()
{
float x = 1.2f;
float y = 56.89f;
troca(x,y);
std::cout << "x = " << x << " e y = " << y << std::endl;
}
O uso comum de argumentos do tipo referncia ocorre em funes que devem retornar mais
de um valor. No exemplo acima, a funo retornou dois valores.
18
2 - VETORES E MATRIZES
2.1 - Vetores
Quando voc deseja representar uma coleo de dados semelhantes, pode ser muito
inconveniente utilizar um nome de varivel diferente para cada dado.
Para ilustrar vamos considerar o seguinte exemplo: Montar um programa que armazena as
notas de 5 alunos e calcula a mdia obtida pela turma. As notas sero armazenadas em uma
varivel do tipo float, porm ao invs de criarmos 5 variveis, utilizamos uma varivel do
tipo vetor, definida como abaixo:
float notas[5];
Exemplo:
Notas.cpp
#include <iostream>
using namespace std;
int main() {
int i;
float media;
float soma;
float notas[5];
soma = 0;
for (i = 0; i < 5; i++)
soma = soma + notas[i];
media = soma / 5;
cout << " A media final : " << media;
}
2.1.1 - Declarao
int n[5];
reserva o espao de 5 variveis do tipo inteira, onde cada varivel pode ser referenciada
conforme abaixo:
19
n[0] n[1] n[2] n[3] n[4]
IMPORTANTE: Observe que a declarao anterior cria cinco variveis, porm o primeiro
elemento n[0]. A declarao de vetor inicia com o ndice 0 e finaliza no ndice 4. Se
voc quer atribuir um valor a um dos componentes do vetor basta referenci-lo:
n[3] = 29;
resultando em:
29
n[0] n[1] n[2] n[3] n[4]
Assim como possvel atribuir valores a uma varivel na mesma linha da declarao, o
mesmo pode ser feito para vetores. Observe o exemplo abaixo:
Como exemplo vamos apresentar um programa que ordena uma seqncia de 10 nmeros
reais.
Ordenao.cpp
#include <iostream>
using namespace std;
int main() {
int i;
int flag;
float swap;
float x[10];
const int n = 10;
/* Entrada de Dados */
cout << "Entre com os numeros para ordenacao \n";
for (i = 0; i < n; i++) {
cout << "\n numero[" << i << "] = ";
cin >> x[i];
}
20
x[i] = x[i + 1];
x[i + 1] = swap;
flag = 1;
}
}
}
2.2 - Matrizes
Para representar uma matriz 3x4 (3 linha e 4 colunas) de nmeros reais utilizamos a
seguinte declarao:
float A[3][4];
int main() {
int i, j;
float A[3][3] = { { 1.0, 1.5, 2.1 },
{ 3.4, 2.2, 9.1 },
{-1.2, -3.4, 0.9 }};
float v[3] = { 2.0, 1.0, 0.5 };
float p[3];
21
cout << "\n p["<< i << "] = " << p[i];
}
3 - PONTEIROS
3.1 - Introduo
Um ponteiro uma varivel que contm o endereo de memria de outra varivel. Todas as
variveis so alocadas em algum espao de memria do computador. O ponteiro fornece
um mecanismo para obter e armazenar este endereo de memria. Considere o exemplo:
Ponteiro01.cpp
#include <iostream>
using namespace std;
int main()
{
int i;
Para armazenar o endereo de uma varivel (por exemplo &i) em outra varivel,
necessrio criar um tipo especial de varivel denominada apontador. Exemplo:
Ponteiro02.cpp
#include <iostream>
int main()
{
int i ;
int *pi;
pi = &i;
22
std::cout << "Endereco de i = " << &i << " ou " << pi;
}
A varivel pi uma varivel do tipo ponteiro para inteiro (ou seja, ela recebe o endereo
de uma varivel do tipo inteiro). Para informar que esta varivel do tipo apontador
colocamos um asterisco (*) na frente da varivel no momento da sua declarao:
int * pi;
Tipo de Indica Nome
ponteiro pontei da
ro variv
el
Ponteiro03.cpp
#include <iostream>
using namespace std;
int main()
{
int i, j;
int *pi;
pi = &i;
i = 25;
j = *pi + 8; /* equivalente a j = i + 8 */
O operador unrio * trata seu operando como um endereo e acessa este endereo para
buscar o contedo da varivel. Observe que o * tem dupla funo:
1. Em uma declarao de varivel, indica que a varivel do tipo ponteiro.
2. Durante uma atribuio, acessa o contedo do endereo armazenado pela varivel
ponteiro.
No nosso exemplo, para alterar o valor da varivel i, temos duas alternativas (totalmente
equivalentes) :
i = 5;
*pi = 5;
23
3.5 Ponteiros com Vetores
#include <iostream>
using namespace std;
auxiliar = x;
x = y;
y = auxiliar;
}
while (flag == 1) {
flag = 0;
for (int i = 0; i < (elementos - 1); i++) {
if (v[i] > v[i + 1]) {
troca(v[i],v[i+1]);
flag = 1;
}
}
}
}
int main() {
float x[10];
const int n = 10;
// Entrada de Dados
cout << "Entre com os numeros para ordenacao \n";
for (int i = 0; i < n; i++) {
cout << "\n numero[" << i << "] = ";
cin >> x[i];
}
ordena(x,n);
24
for (int i = 0; i < n; i++)
cout << x[i] << endl;
}
Como o programa sabe que estamos nos referenciando a um vetor e no a uma simples
varivel ? Na verdade v uma varivel ponteiro para um float. Ela recebe o endereo do
primeiro elemento do vetor. Assim equivalente a chamar a funo ordena como:
ordena(&x[0],n);
Como os vetores so alocados sequencialmente na memria do computador, ento a
referncia x[5], acessa o sexto contedo em sequncia na memria. Quando o nome de
um vetor passado para uma funo, o que passado o endereo do incio do vetor.
#include <iostream>
using namespace std;
void main()
{
int i,n;
float *v;
cout << "Entre com a dimensao do vetor desejada = " << endl;
cin >> n;
v = new float[n];
delete[] v;
}
Para efetuar a alocao dinmica observe as etapas do programa:
1. O vetor que ser alocado foi declarado como um ponteiro: float *v;
2. O comando new float[n] reserva n espaos de memria, cada um do tamanho de um
float.
25
3. A funo new retorna o endereo do primeiro elemento do vetor.
4. A funo delete[] libera o espao de memria reservado para o vetor.
void main()
{
int i,j,n,m;
float **A;
A = new float*[n];
A[0] = new float[n*m];
for(i=1;i<n;i++)
A[i] = &A[0][i*m];
for(i=0;i<n;i++)
for(j=0;j<m;j++)
cin >> A[i][j];
for(i=0;i<n;i++) {
cout << endl;
for(j=0;j<m;j++)
cout << "A["<<i<<"]["<< j << "]= " << A[i][j];
}
delete [] A[0];
delete [] A;
}
26
4 OBJETOS E CLASSES
Vamos iniciar com um exemplo, definindo um crculo com duas funes membros e trs
variveis membros:
Circulo.hpp
class Circulo {
public:
Circulo(); // Funcao membro
double area(); // Funcao membro
private:
double raio; // Variavel membro
double centrox,centroy; // Variavel membro
};
As funes membros foram declaradas mas no implementadas. Isso ser feito em outro
mdulo:
Circulo.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include "Circulo.hpp"
Circulo::Circulo() {
raio = 1.0;
centrox = 0.0;
centroy = 0.0;
}
double Circulo::area()
{
return(M_PI * raio * raio);
}
27
O programa abaixo utiliza a classe circulo:
main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;
int main() {
Circulo A;
4.2 Construtores
Circulo A;
cria o objeto crculo, chamando a funo Circulo(). Esta funo, em particular, tem
propriedades especiais pois responsvel pela criao de um novo objeto e por essa razo
denominada construtor.
Um construtor pode ser identificado na definio de uma classe por ser a nica funo cujo
nome coincide exatamente com o nome da classe. Algumas caractersticas importantes do
construtor:
1) Tem sempre o mesmo nome da classe
2) Pode ou no ter argumentos
3) No retorna nenhum campo (ou seja, no possui return).
#include <iostream>
class Circulo {
public:
Circulo(); // Construtor
double area(); // Funcao membro
private:
double raio; // Campos
double centrox,centroy;
}
Um construtor, ao contrrio de uma funo membro usual, no tem um tipo. Por exemplo: a
funo double area() retorna um double, enquanto o construtor Circulo(), no
tem nenhum tipo como prefixo.
28
O objetivo principal do construtor garantir que todo objeto criado possa ter seus campos
inicializados. Muitas vezes gostaramos de definir como os campos devem ser iniciados e
possivelmente executar alguns comandos especficos na criao do objeto. Neste caso
utilizamos os construtores.
Uma classe pode ter vrios construtores diferentes conforme os parmetros de entrada. Por
exemplo:
Circulo.hpp
class Circulo {
public:
Circulo(); // Construtor
Circulo(double r,double cx, double cy); // Construtor
double area(); // Funcao membro
private:
double raio; // Campos
double centrox,centroy;
};
Circulo::Circulo() {
raio = 1.0;
centrox = 0.0;
centroy = 0.0;
}
double Circulo::area()
{
return(M_PI * raio * raio);
}
main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;
int main() {
Circulo A;
Circulo B(2.5,1.0,1.0);
29
possvel definir uma classe sem construtores. Nesse caso as variveis membro so criadas
mas no inicializadas. Para alterar os campos ser necessrio criar funes membro que
modifiquem os valores dos campos.
Exemplo 1:
Se os campos da classe Crculo fossem definidas como pblicas, ento no main,
poderamos acessar as variveis do objeto e alter-lo. Veja o exemplo:
Circulo.hpp
class Circulo {
public:
Circulo(); // Construtor
double area(); // Funcao membro
main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;
int main() {
Circulo A;
A.raio = 2;
A.centrox = 0.2;
Exemplo 2:
Os elementos da seo private no podem ser acessados fora da classe. Assim o exemplo
abaixo causaria erros de compilao nas linhas indicadas:
Circulo.hpp
30
class Circulo {
public:
Circulo(); // Construtor
double area(); // Funcao membro
private:
double raio; // Campos
double centrox,centroy;
};
main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;
int main() {
Circulo A;
cout << "Raio do Circulo A = " << A.raio << endl; // ERRO !
cout << "Area do Circulo A = " << A.area() << endl;
}
Neste caso, para alterar as variveis da classe precisamos definir funes na classe que
faam essa tarefa.
4.3.1 - Introduo
Uma funo membro da classe uma rotina (cdigo) que atua sobre o objeto, como por
exemplo, alterando seus campos, respondendo propriedades sobre o objeto, etc. No nosso
exemplo, implementamos um mtodo que responde a rea do objeto crculo.
31
Circulo.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include "Circulo.hpp"
Circulo::Circulo() {
raio = 1.0;
centrox = 0.0;
centroy = 0.0;
}
double Circulo::get_centrox()
{
return(centrox);
}
double Circulo::get_centroy()
{
return(centroy);
}
double Circulo::area()
{
return(M_PI * raio * raio);
}
main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;
int main() {
Circulo A;
A.translacao(2,3);
cout << "Centro do Circulo A = (" << A.get_centrox() << "," <<
A.get_centroy() << ")" << endl;
cout << "Area do Circulo A = " << A.area() << endl;
}
32
4.3.3 Exemplo de uma Classe para Representar Nmeros Racionais
Racional.cpp
#include "Racional.h"
#include <math.h>
#include <iostream>
using namespace std;
void Racional::simplifica()
{
int r;
int b = p;
int a = q;
do {
r = b % a;
b = a;
a = r;
} while(r != 0);
p = p / b;
q = q / b;
}
33
dif.p = z.q * p - z.p * q;
dif.q = z.q * q;
dif.simplifica();
return(dif);
}
void Racional::show()
{
if (q == 1)
cout << p;
else
if ( q == -1)
cout << -p;
else
cout << p << "/" << q;
}
main.cpp
#include "Racional.h"
#include <iostream>
using namespace std;
int main()
{
for(int i = 1;i<8;i++) {
Racional x(i,i+2);
Racional u(i+1,i);
x.show();
cout << " + ";
u.show();
cout << " = ";
(x.soma(u)).show();
cout << endl;
x.show();
cout << " - ";
u.show();
cout << " = ";
(x.subtrai(u)).show();
cout << endl;
x.show();
cout << " . ";
u.show();
cout << " = ";
(x.multiplica(u)).show();
cout << endl;
}
}
34
4.3.4 Exemplo de uma Classe Vetor
Vetor.cpp
#include "Vetor.h"
Vetor::Vetor(int n) {
dim = n;
v = new double[n];
}
Vetor::Vetor(Vetor& C) {
dim = C.get_dim();
v = new double[dim];
for(int j=0;j<dim;j++)
v[j] = C.get(j);
}
Vetor::~Vetor() {
delete [] v;
}
double Vetor::get(int i) {
if ((i >= 0) && (i<dim))
return (v[i]);
else return 0;
}
int Vetor::get_dim() {
return(dim);
}
35
main.cpp
#include <iostream>
using namespace std;
#include "Vetor.h"
int main()
{
int i,n;
Vetor A(n);
for(i=0;i<n;i++)
cout << " A["<<i<<"]= " << A.get(i) << endl;
}
Soma de vetores
Vetor.h
class Vetor
{
double *v ; // Os primeiros campos sao private
int dim;
public:
Vetor(int n); // Construtor
Vetor(Vetor& W); // Construtor
~Vetor(); // Destruidor
36
Vetor.cpp
#include "Vetor.h"
.
.
.
Vetor Vetor::soma(Vetor b)
{
if (dim != b.dim)
return 0;
Vetor soma(dim);
return soma;
}
main.cpp
#include <iostream>
using namespace std;
#include "Vetor.h"
int main()
{
int i,n;
Vetor A(n);
Vetor B(n);
Vetor C = A.soma(B);
for(i=0;i<n;i++)
cout << " v["<<i<<"]= " << A.get(i) << endl;
for(i=0;i<n;i++)
cout << " w["<<i<<"]= " << B.get(i) << endl;
for(i=0;i<n;i++)
cout << " soma["<<i<<"]= " << C.get(i) << endl;
}
37
Sobrecarga de Operadores
Em C++ podemos redefinir operadores que permitem realizar operaes entre objetos. Um
exemplo somar vetores usando o smbolo +. Outro exemplo na classe Vetor seria
definir um operador [ ] para acessarmos o elemento v[i] (substituindo o comando A.get(i) e
A.set(i)).
Vetor.h
class Vetor
{
double *v ; // Os primeiros campos sao private
int dim;
public:
Vetor(int n); // Construtor
Vetor(Vetor& W); // Construtor
~Vetor(); // Destruidor
double& operator[] (int i); // Funcoes de acesso e modificadores
int get_dim();
};
Vetor.cpp
#include "Vetor.h"
Vetor::Vetor(int n) {
dim = n;
v = new double[n];
}
Vetor::Vetor(Vetor& C) {
dim = C.get_dim();
v = new double[dim];
for(int j=0;j<dim;j++)
v[j] = C[j];
}
Vetor::~Vetor() {
delete [] v;
}
double& Vetor::operator[](int i) {
if ((i < 0) || (i >= dim)) {
std::cout << "Indice fora de dimensao \n";
exit(0);
}
return v[i];
}
int Vetor::get_dim() {
return(dim);
}
38
main.cpp
#include <iostream>
using namespace std;
#include "Vetor.h"
int main()
{
int i,n;
Vetor A(n);
for(i=0;i<n;i++)
cout << " A["<<i<<"]= " << A[i] << endl;
}
class Racional {
private:
int p,q;
void simplifica();
public:
Racional(int a = 0,int b = 1) { p = a; q = b; simplifica(); };
Racional(Racional &R) { p = R.p; q = R.q; };
Racional.cpp
#include "Racional.h"
39
dif.q = z.q * q;
dif.simplifica();
return(dif);
}
void Racional::simplifica()
{
int r;
int b = p;
int a = q;
do {
r = b % a;
b = a;
a = r;
} while(r != 0);
p = p / b;
q = q / b;
}
return(s);
s.p = z.p * p;
s.q = z.q * q;
s.simplifica();
return(s);
}
40
bool operator== (const Racional& r,const Racional& s)
{
return(r.p * s.q == r.q * s.p);
}
main.cpp
#include "Racional.h"
int main()
{
Racional a(6,3);
Racional b(3,4);
Racional c = a + b;
cout << c;
for(int i = 1;i<10;i++) {
Racional x(i,i+2);
Racional u(i+1,i);
cout << x << " + " << u << " = " << x + u << endl;
cout << x << " * " << u << " = " << x * u << endl;
cout << x << " - " << u << " = " << x - u << endl;
if (x == b)
cout << "Igual" << endl;
}
}
41
1
1. PONTOS E RETAS NO OPENGL......................................................................................... 3
1.1 Sistemas Grficos ............................................................................................................................3
1.2 Cores.......................................................................................................................................................3
1.3 Introduo ao OpenGL ..................................................................................................................4
1.4 Funes Bsicas...............................................................................................................................4
1.5 gluOrtho2D...........................................................................................................................................6
1.6 Exemplo: Plotar uma reta unindo dois pontos...................................................................7
1.6.1 Algoritmo ingnuo .....................................................................................................................................7
1.6.2 Retas no Opengl ........................................................................................................................................8
1.7 Exemplo: Plotar o grfico de uma funo............................................................................9
1.8 Fontes ..................................................................................................................................................11
2. TECLADO E MOUSE(Callbacks) .......................................................................................13
2.1 Introduo..........................................................................................................................................13
2.2 Teclado................................................................................................................................................13
2.2.1 Exemplo: Utilizao do teclado no programa funes........................................................13
2.3 Mouse ..................................................................................................................................................14
2.3.1 Interrupes a partir do mouse .......................................................................................................14
2.3.2 Aplicaes: Realizando o zoom do grfico............................................................................17
2.3.3 Aplicaes: Pilha.....................................................................................................................................22
3. RETAS E POLGONOS NO OPENGL ...............................................................................28
3.1 Primitivas............................................................................................................................................28
3.2 Exemplo: Visualizao de Mtodos Numricos de Integrao .............................29
4. CURVAS PARAMTRICAS..................................................................................................32
4.1 Introduo..........................................................................................................................................32
4.2 Exemplo: Visualizao de Curvas Paramtricas ..........................................................32
4.3 Curvas na forma Polar ................................................................................................................36
4.4 Exemplo: Visualizao de Curvas Polares ......................................................................37
5. CURVAS IMPLCITAS ............................................................................................................39
5.1 Introduo..........................................................................................................................................39
5.2 Visualizao de Curvas Implcitas ........................................................................................39
5.3 Programa Curva Implcita..........................................................................................................40
2
Captulo II Aplicaes Grficas 2D
1. PONTOS E RETAS NO OPENGL
1.1 Sistemas Grficos
Uma imagem grfica formada por uma matriz de elementos denominados pixels. Os pixels so
armazenados em uma poro da memria denominada Frame Buffer.
A resoluo do frame buffer corresponde ao nmero de pixels que ele representa e varia conforme a placa
grfica disponvel. As resolues bsicas encontradas so:
640 x 480
800 x 600
1024 x 768
1280 x 1024
1.2 Cores
A profundidade do frame buffer corresponde ao nmero de bits presentes para cada pixel e atravs do
qual fica estabelecido, por exemplo, o nmero de cores que podem ser representados em cada pixel. O
nmero de cores possveis varia conforme o hardware. Cada pixel tem uma mesma quantidade de
memria para armazenar suas cores.
O buffer de cores (Color Buffer) uma poro da memria reservada para armazenar as cores em cada
pixel. Um buffer de 8 bits pode exibir 256 cores diferentes simultaneamente. Conforme a capacidade da
placa grfica podemos ter:
Existem duas formas bsicas de acessar as cores no OpenGL: RGB e Modo Indexado. Trabalharemos
sempre em formato RGB. No formato RGB voc deve informar as intensidades de Vermelho, Verde e
Azul. Estas intensidades devem variar entre 0,0 a 1.0. A tabela abaixo mostra como obter as cores
bsicas:
Cores R G B
Vermelho 1.0 0.0 0.0
Verde 0.0 1.0 0.0
Azul 0.0 0.0 1.0
Amarelo 1.0 1.0 0.0
Cyan 0.0 1.0 1.0
Magenta 1.0 0.0 1.0
Branco 1.0 1.0 1.0
Preto 0.0 0.0 0.0
3
1.3 Introduo ao OpenGL
O sistema grfico OpenGL (GL significa Graphics Library) uma biblioteca (de aproximadamente 350
funes) para aplicaes grficas. O OpenGL foi desenvolvido pela Silicon Graphics (SGI) voltado para
aplicaes de computao grfica 3D, embora possa ser usado tambm em 2D. As funes permitem a
gerao de primitivas (pontos, linhas, polgonos, etc.) e utilizar recursos de iluminao.
O OpenGL independente do sistema de janelas, ou seja, suas funes no especificam como manipular
janelas. Isto permite que o OpenGL possa ser implementado para diferentes sistemas: Linux, Windows,
Mac OS X, etc.
void display()
{
}
1) glutInit(&argc,argv);
Esta funo utilizada para iniciar a biblioteca GLUT.
2) glutCreateWindow("Ponto");
Cria uma janela para o OpenGL com o nome: Ponto
3) glutDisplayFunc(display);
Esta funo registra que a funo void display() ser a funo a ser chamada sempre que a
janela grfica necessita ser atualizada.
4) glutMainLoop();
Inicia o gerenciamento de eventos, aguardando que algum evento seja acionado.
O prximo passo gerar uma primeira sada grfica. Para isso, precisamos implementar o cdigo
desejado na funo display(). No exemplo, ilustramos como acender o pixel central na cor vermelha.
#include <gl\glut.h>
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(0.0,0.0);
glEnd();
glFlush();
glutSwapBuffers();
}
4
Quando a funo display chamada temos o seguinte resultado:
glClearColor(0.0,0.0,0.0,0.0);
Indica a cor para ser utilizada no fundo da janela.
glClear(GL_COLOR_BUFFER_BIT);
Limpa o buffer indicado com a cor do glClearColor()
glColor3f(1.0,0.0,0.0);
Define o vermelho como cor atual.
glBegin(GL_POINTS);
glVertex2f(0.0, 0.0);
glEnd();
Inicialmente a janela grfica est definida para valores no intervalo [-1,1], tanto em x quanto em y.
Assim a funo glVertex2f(0.0, 0.0) acende o pixel na posio do centro
glFlush();
Envia uma solicitao que o contedo do Frame Buffer seja exibido.
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(0.0,0.0);
glEnd();
glFlush();
glutSwapBuffers();
}
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
Quando uma janela criada, seu tipo determinado pelo Display Mode. O tipo da janela inclui um
conjunto de caractersticas desejadas. Neste caso temos trs:
glutInitWindowSize(400,400);
Indica o tamanho da janela a ser aberta (em pixels).
glutInitWindowPosition(1,1);
Indica a posio inicial da janela.
glutSwapBuffers();
Troca os buffers (duplo buffer)
5
Exerccios:
1) Comente as seguintes linhas na funo display e veja o resultado:
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
void display()
{
static int i = 0;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
glFlush();
cout << i++ << endl;
}
3) Comente a seguinte linha do cdigo e veja o resultado.
glutDisplayFunc(display);
1.5 gluOrtho2D
Na maioria de nossas aplicaes desejamos nos referenciar a um ponto na janela, no por coordenadas
correspondendo as dimenses informadas na funo glutInitWindowSize(), mas sim levando-se
em conta o domnio de visualizao relacionado ao problema. Para isso, a funo gluOrtho2D()
realiza a mudana para o sistema de coordenadas desejado.
Esta tarefa realizada fazendo a correspondncia entre os intervalos em questo:
Assim:
e segue que
6
void display()
{
converte(xmin,xmax,ymin,ymax,x,y);
cout << "x= " << x << " y= " <<y << endl;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
glFlush();
glutSwapBuffers();
}
A primeira idia de como resolver este problema proposto pelo programa abaixo. Este um exemplo
ingnuo de como desenhar a reta que passa por dois pontos dados. Vamos discutir a seguir os principais
problemas deste programa e as possveis solues.
* -------------------------------------------------------------- */
/* Exemplo ingenuo de como plotar a reta definida por dois pontos */
/* -------------------------------------------------------------- */
#include <gl\glut.h>
#include <iostream>
using namespace std;
float x0,y0,x1,y1;
void display()
{
7
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
for (x = x0;x <= x1;x+=0.001) {
y = (y1-y0)/(x1-x0)*(x-x0) +y0;
glVertex2f(x,y);
}
glEnd();
glFlush();
glutSwapBuffers();
}
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Reta");
gluOrtho2D(-3,3,-3,3);
glutDisplayFunc(display);
glutMainLoop();
}
1) Este mtodo requer operaes em ponto flutuante (float ou double) para cada pixel. Isto acarreta
em um algoritmo lento, se comparado a um algoritmo que opera somente com nmeros inteiros.
Para o caso da reta, existe um tal algoritmo que utiliza somente aritmtica com nmeros inteiros.
Este algoritmo foi desenvolvido por Jack E. Bresenham na dcada de 60 e ser descrito adiante.
2) O usurio estabelece o nmero de pontos da reta a serem plotados entre os dois pontos. Podem
ocorrer dois casos: faltarem pontos (a reta fica pontilhada), sobrarem pontos (neste caso o
algoritmo faz contas desnecessrias). O ideal o prprio programa se encarregar de determinar o
nmero de pontos necessrios e suficientes para resolver o problema.
3) O caso particular da reta vertical (onde K constante) no pode ser plotado.
O OpenGL dispe em sua biblioteca interna de uma funo que plota uma reta por dois pontos dados.
Esta funo descrita abaixo:
8
void display()
{
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex2f(x0,y0);
glVertex2f(x1,y1);
glEnd();
glFlush();
}
#include <gl\glut.h>
float funcao(float x)
{
return(x*x);
}
void display()
{
float x,y,dx;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
dx = 0.02;
x = -1;
for(int i = 0;i < 100;i++)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
x += dx;
}
glutSwapBuffers();
}
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
gluOrtho2D(-1,1,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
9
Em seguida vamos definir a classe funo:
funcao.h
#include <cmath>
class funcao {
int pontos;
float xmin,xmax,ymin,ymax;
public:
void dominio();
void plota_funcao();
};
funcao.cpp
#include <gl\glut.h>
#include "funcao.h"
#include <iostream>
using namespace std;
void funcao::dominio() {
cout << "xmin = ";
cin >> xmin;
cout << "xmax = ";
cin >> xmax;
}
void funcao::plota_funcao() {
float dx;
float x, y;
dx = (xmax - xmin)/pontos;
glColor3f (1.0, 0.0, 0.0);
x = xmin;
for (int i = 0; i < pontos; i++) {
y = f(x);
glBegin ( GL_POINTS);
glVertex2f (x,y);
glEnd();
x = x + dx;
}
}
10
main.cpp
#include <gl\glut.h>
#include <cmath>
#include "funcao.h"
float L = -5;
float R = 5;
float B = -5;
float T = 5;
funcao f(400,L,R);
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (L,0);
glVertex2f (R,0);
glVertex2f (0,B);
glVertex2f (0,T);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
f.plota_funcao();
glFlush();
glutSwapBuffers();
}
1.8 Fontes
Utilizando o glut possvel incluir textos na visualizao do grficos. Para isso precisamos de duas
funes:
11
Assim podemos, no exemplo do grfico, incluir variveis que indiquem os eixos e pontos no nosso
grfico.
main.cpp
void display_fontes(float x,float y,void *tipo_fonte,char *texto)
// font = GLUT_BITMAP_9_BY_15
// GLUT_BITMAP_8_BY_13
// GLUT_BITMAP_HELVETICA_10
// GLUT_BITMAP_HELVETICA_14
{
glRasterPos2f(x, y);
for (int i = 0; texto[i] != '\0'; i++) {
glutBitmapCharacter((tipo_fonte, texto[i]);
}
}
void plota_eixo()
{
glColor3f (1, 1, 1);
display_fontes(4.7,-0.3,GLUT_BITMAP_HELVETICA_12,"x");
display_fontes(0.1, 4.7,GLUT_BITMAP_HELVETICA_12,"y");
display_fontes(0.1,-0.3,GLUT_BITMAP_HELVETICA_12,"0");
glBegin (GL_LINES);
glVertex2f (0,w.getB());
glVertex2f (0,w.getT());
glEnd();
}
.
.
.
12
2. TECLADO E MOUSE(Callbacks)
2.1 Introduo
O usurio pode interagir com o programa de duas formas principais: atravs do Mouse ou Teclado. Para
isso o GLUT dispe de dois tipos de funes (que denominamos Callbacks) especficas para habilitar a
utilizao do teclado e do mouse. Vamos descrev-las a seguir.
2.2 Teclado
Para registrar ocorrncias no teclado o GLUT dispe da funo:
Esta funo determina que quando uma tecla for pressionada, o controle do programa deve passar a
funo definida no campo (*func) e esta funo receber como parmetros de entrada, a tecla
pressionada (unsigned char key), e a posio do mouse (int x, int y). O exemplo abaixo
exemplifica uma aplicao para o programa funes.
main.cpp
#include <gl\glut.h>
#include <cmath>
#include "funcao.h"
#include <iostream>
using namespace std;
float L = -5;
float R = 5;
float B = -5;
float T = 5;
funcao f(400,L,R);
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (L,0);
glVertex2f (R,0);
glVertex2f (0,B);
glVertex2f (0,T);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
f.plota_funcao();
glFlush();
glutSwapBuffers();
}
13
{
switch(key)
{
case 'D':
case 'd':
f.dominio();
glutPostRedisplay();
break;
case 'W':
case 'w':
cout << "L = "; cin >> L;
cout << "R = "; cin >> R;
cout << "B = "; cin >> B;
cout << "T = "; cin >> T;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
glutPostRedisplay();
break;
}
}
2.3 Mouse
O GLUT capaz de obter trs tipos de ocorrncias diferentes a partir do mouse. Vamos descrev-las em
seguida e discutir uma interessante aplicao para o estudo de grficos de funes.
a) glutMouseFunc
void glutMouseFunc(void (*func)(int button, int state, int x, int y))
Este evento detecta quando algum boto do mouse foi pressionado. Quando isto ocorre, o programa
executa a rotina definida em void (*func). Os parmetros desta rotina podem receber os seguintes
valores:
- button : informa qual boto do mouse foi pressionado, sendo atribudo com um dos seguintes
valores: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON.
- state: informa quando o boto foi pressionado e quando o boto foi solto, sendo atribudo com
dois possveis valores: GLUT_DOWN ou GLUT_UP.
- x,y: informa a posio do mouse quando o boto foi pressionado.
Para ilustrar essa interrupo, alteramos o main.cpp e acrescentamos outra forma de interrupo para
alterar o domnio. Assim se o usurio pressionar o boto direito do mouse, o programa solicita no console
o novo domnio de visualizao. Se pressionar o boto esquerdo, o programa informa em qual coordenada
da tela o mouse se encontra.
14
#include <gl\glut.h>
#include <cmath>
#include "funcao.h"
#include <iostream>
using namespace std;
float L = -5;
float R = 5;
float B = -5;
float T = 5;
funcao f(400);
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (L,0);
glVertex2f (R,0);
glVertex2f (0,B);
glVertex2f (0,T);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
f.plota_funcao();
glFlush();
glutSwapBuffers();
}
void window_dimension()
{
cout << "L = "; cin >> L;
cout << "R = "; cin >> R;
cout << "B = "; cin >> B;
cout << "T = "; cin >> T;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
}
15
}
}
b) glutMotionFunc
Este evento detecta o movimento do mouse enquanto algum boto do mouse est pressionado. Quando
isto ocorre, o programa executa a rotina definida em void (*func) e informa em x,y a posio do
mouse na janela.
No exemplo abaixo, a rotina botao_movimento_mouse(int x, int y) imprime a posio do
mouse enquanto mantemos um de seus botes pressionados.
.
.
.
c) glutPassiveMotionFunc
Este evento detecta o movimento do mouse quanto nenhum boto do mouse est pressionado. Quando
isto ocorre, o programa executa a rotina definida em void (*func) e informa em x,y a posio do
mouse na janela.
No exemplo abaixo, a rotina movimento_mouse(int x, int y) imprime a posio do mouse
quando movimentamos o mouse dentro da janela OpenGL.
16
.
.
.
No processo de visualizao das funes, ou mesmo da integrao numrica, muitas vezes desejamos
alterar o domnio do nosso grfico. Para isso selecionamos a tecla D e d como uma interrupo do
teclado para que pudssemos informar o novo domnio. Uma forma mais gil seria selecionar com o
mouse interativamente um retngulo que gostaramos de visualizar. o que faremos no prximo
programa.
Para isso utilizaremos as interrupes do mouse para selecionarmos a regio desejada. Quando o boto
direito do mouse pressionado, marcamos o ponto inicial da regio. Enquanto o mouse est em
movimento (com o boto direito pressionado), desenhamos o retngulo desejado. Quando o boto do
mouse solto, obtemos o ponto final da regio e atualizamos o domnio da funo.
Observe que as coordenadas obtidas pelos eventos do mouse precisam ser convertidas para o sistma de
coordendas indicado nos parmetros da janela de visualizao. Para isso, basta considerarmos a
transformao inversa a aplicada na seo 1.5:
e segue que
funcao.h
#include <cmath>
class funcao {
int pontos;
float xmin,xmax;
public:
17
float get_xmin() { return xmin; }
float get_xmax() { return xmax; }
void dominio();
void plota_funcao();
};
funcao.cpp
#include <gl\glut.h>
#include "funcao.h"
#include <iostream>
using namespace std;
void funcao::dominio()
{
cout << "xmin = ";
cin >> xmin;
cout << "xmax = ";
cin >> xmax;
}
void funcao::plota_funcao()
{
float dx;
float x, y;
dx = (xmax - xmin)/pontos;
glColor3f (1.0, 0.0, 0.0);
x = xmin;
glBegin ( GL_POINTS);
for (int i = 0; i < pontos; i++) {
y = f(x);
glVertex2f (x,y);
x = x + dx;
}
glEnd();
}
window.h
class window {
float L,R,B,T;
public:
window(float L = -1,float R = 1,float B = -1,float T = 1);
18
float getL() { return(L); }
float getR() { return(R); }
float getB() { return(B); }
float getT() { return(T); }
void set();
void set_window (int xv_1,int yv_1,int xv_2,int yv_2,int
DIMX,int DIMY) ;
void plota_retangulo(int xv0,int yv0,int xv1,int yv1,int
DIMX,int DIMY);
};
window.cpp
#include <gl\glut.h>
#include <iostream>
using namespace std;
#include "window.h"
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
xmin1 = converte(xv_1,L,R,DIMX);
xmax1 = converte(xv_2,L,R,DIMX);
L = xmin1;
R = xmax1;
ymin1 = converte(yv_2,T,B,DIMY);
ymax1 = converte(yv_1,T,B,DIMY);
B = ymin1;
T = ymax1;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
}
void window::set()
{
cout << "L = "; cin >> L;
cout << "R = "; cin >> R;
cout << "B = "; cin >> B;
cout << "T = "; cin >> T;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
}
19
void window::plota_retangulo(int xv0,int yv0,int xv1,int yv1,
int DIMX,int DIMY)
{
float t;
float retxmin,retxmax,retymin,retymax;
retxmin = converte(xv1,L,R,DIMX);
retxmax = converte(xv0,L,R,DIMX);
retymin = converte(yv0,T,B,DIMY);
retymax = converte(yv1,T,B,DIMY);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(retxmin,retymin);
glVertex2f(retxmin,retymax);
glVertex2f(retxmax,retymax);
glVertex2f(retxmax,retymin);
glEnd();
}
main.cpp
#include <gl\glut.h>
#include <cmath>
#include "funcao.h"
#include "window.h"
#include <iostream>
using namespace std;
window w(-5,5,-5,5);
funcao f(400,w.getL(),w.getR());
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (w.getL(),0);
glVertex2f (w.getR(),0);
glVertex2f (0,w.getB());
glVertex2f (0,w.getT());
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
f.plota_funcao();
if (mov == 1)
w.plota_retangulo(xv1,yv1,xv2,yv2,DIMX,DIMY);
glFlush();
glutSwapBuffers();
}
20
void teclado(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
f.dominio();
glutPostRedisplay();
break;
case 'W':
case 'w':
w.set();
glutPostRedisplay();
break;
}
}
21
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(DIMX,DIMY);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
glutKeyboardFunc(teclado);
glutMouseFunc(botao_mouse);
glutMotionFunc(botao_movimento_mouse);
glutReshapeFunc(window_size);
gluOrtho2D(w.getL(),w.getR(),w.getB(),w.getT());
glutMainLoop();
}
Em uma segunda verso gostariamos de voltarmos ao domnio original. Para isso, precisamos armazenar
as alteraes anteriores do domnio. Uma estrutura adequada para esta situao seria montar uma pilha. O
exemplo abaixo ilustra a implementao de uma classe Pilha e sua aplicao no exemplo de zoom.
Stack.h
#ifndef STACK_H
#define STACK_H
#include "window.h"
#include <cstdlib>
struct Node {
window a ;
Node* next;
};
class Stack {
Node* top;
public:
Stack();
void push(window& b);
window pop();
bool Empty();
int size();
window peek();
};
#endif
Stack.cpp
#include "Stack.h"
#include <cstdio>
Stack::Stack()
{
top = NULL;
}
void Stack::push(window& b) {
Node* new_top = new Node;
new_top->a = b;
22
new_top->next = top;
top = new_top;
}
window Stack::pop() {
Node *remove;
window a = top->a;
remove = top;
top = top->next;
delete remove;
return a;
}
bool Stack::Empty() {
if (top == NULL)
return (true);
else
return(false);
}
int Stack::size()
{
int i = 0;
Node *n;
for(n = top; n != NULL; n = n->next)
i++;
return(i);
}
window Stack::peek() {
return (top->a);
}
Na classe window foram includas funes para auxiliar no empilhamento das coordenadas.
window.h
#ifndef WINDOW_H
#define WINDOW_H
class window {
float L,R,B,T;
public:
window(float L = -1,float R = 1,float B = -1,float T = 1);
window(window& a);
23
};
#endif
window.cpp
#include <gl\glut.h>
#include <iostream>
using namespace std;
#include "window.h"
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
xmin1 = converte(xv_1,L,R,DIMX);
xmax1 = converte(xv_2,L,R,DIMX);
L = xmin1;
R = xmax1;
ymin1 = converte(yv_2,T,B,DIMY);
ymax1 = converte(yv_1,T,B,DIMY);
B = ymin1;
T = ymax1;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
}
24
void window::set_window()
{
cout << "L = "; cin >> L;
cout << "R = "; cin >> R;
cout << "B = "; cin >> B;
cout << "T = "; cin >> T;
glLoadIdentity();
gluOrtho2D(L,R,B,T);
}
retxmin = converte(xv1,L,R,DIMX);
retxmax = converte(xv0,L,R,DIMX);
retymin = converte(yv0,T,B,DIMY);
retymax = converte(yv1,T,B,DIMY);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(retxmin,retymin);
glVertex2f(retxmin,retymax);
glVertex2f(retxmax,retymax);
glVertex2f(retxmax,retymin);
glEnd();
}
No main.cpp armazena-se a cada mudana de janela, o novo dominio. Tambm preciso inserir na
interrupo do boto esquerdo do mouse, a funo que retorna o dominio anterior.
main.cpp
#include <gl\glut.h>
#include "funcao.h"
#include "window.h"
#include "Stack.h"
#include <iostream>
using namespace std;
window w(-5,5,-5,5);
funcao f(400,w.getL(),w.getR());
Stack P;
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (w.getL(),0);
25
glVertex2f (w.getR(),0);
glVertex2f (0,w.getB());
glVertex2f (0,w.getT());
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
f.plota_funcao();
if (mov == 1)
w.plota_retangulo(xv1,yv1,xv2,yv2,DIMX,DIMY);
glFlush();
glutSwapBuffers();
}
26
w.set_window(P.pop());
f.set_dominio(w.getL(),w.getR());
}
glutPostRedisplay();
}
else
if (state == GLUT_UP)
cout << "Botao esquerdo solto em: x = " << x << " y = "
<< y << endl;
break;
}
}
27
3. RETAS E POLGONOS NO OPENGL
3.1 Primitivas
Alm de pontos e retas, o OpenGL possui no total 10 tipos de primitivas teis. Todos os modelos da
tabela abaixo devem ser utilizados iniciando com glBegin(...) e finalizando com glEnd(...),
por exemplo para o GL_LINES temos:
glBegin(GL_LINES);
glVertex2f(1.0,1.0);
glVertex2f(1.0,2.0);
glVertex2f(2.0,-2.0);
...
glEnd();
28
3.2 Exemplo: Visualizao de Mtodos Numricos de Integrao
Como exemplo de aplicao dos novos objetos vamos visualizar o mtodos numrico de integrao do
ponto a esquerda, apresentado no captulo 1. Partindo do cdigo j implementado para visualizao de
funes, foram acrescentados a classe integral e o cdigo main.cpp foi alterado para incluir a nova classe.
Integral.h
#include "funcao.h"
class integral {
float a;
float b;
funcao f;
int particao;
int metodo; // 0 - ponto a esquerda
// 1 - trapezio
// 2 - Simpson
public:
integral(float xi,float xf,funcao g,int part = 10,int met = 0) {
a = xi;
b = xf;
f = g;
particao = part;
metodo = met ;
}
void inc_particao() { particao++; }
void dec_particao() {
particao = (particao == 1) ? 1 : --particao; }
void plota_integral_esquerda();
float integral_esquerda();
};
Integral.cpp
#include <gl/glut.h>
#include "integral.h"
void integral::plota_integral_esquerda()
{
float x,y;
float dx;
dx = (b-a)/particao;
x = a;
for(int i=0; i < particao; i++)
{
29
y = f.f(x);
glColor3f(0.0f,0.0f,1.0f);
glBegin(GL_POLYGON);
glVertex2f(x,y);
glVertex2f(x+dx,y);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
glColor3f(1.0f,1.0f,0.0f);
glBegin(GL_LINE_LOOP);
glVertex2f(x,y);
glVertex2f(x+dx,y);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
x = x+dx;
}
}
float integral::integral_esquerda()
{
float x;
float dx;
float soma;
dx = (b-a)/particao;
x = a;
soma = 0;
for(int i=0; i < particao; i++)
{
soma += f.f(x) * dx;
x = x+dx;
}
return(soma);
}
main.cpp
#include <gl\glut.h>
#include "funcao.h"
#include "integral.h"
#include "window.h"
#include "Stack.h"
#include <iostream>
using namespace std;
window w(-5,5,-5,5);
funcao f(400,w.getL(),w.getR());
integral h(-2,2,f);
Stack P;
.
.
.
void display()
30
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT );
plota_eixo();
h.plota_integral_esquerda();
cout << "Integral = " << h.integral_esquerda() << endl;
f.plota_funcao();
if (mov == 1)
w.plota_retangulo(xv1,yv1,xv2,yv2,DIMX,DIMY);
glFlush();
glutSwapBuffers();
}
31
4. CURVAS PARAMTRICAS
4.1 Introduo
Considere uma curva C representando a trajetria de uma partcula P, de tal forma que a posio P(x,y)
da partcula conhecida em cada instante de tempo t.
Assim as coordenadas x e y so conhecidas como funes da varivel t de modo que:
x = x(t)
y = y(t)
x = cos(t)
y = sen(t) onde 0 <= t <= 2*Pi
b) Ciclide (curva traada por um ponto da circunferncia quando o crculo rola sobre uma reta):
x = t - sen(t)
y = 1 - cos(t)
class curva {
int pontos;
float tmin,tmax;
public:
curva(int p = 300,float tm = 0,float tM = 1);
void dominio();
void plota_curva();
};
curva.cpp
#include <gl\glut.h>
#include <cmath>
#include "curva.h"
#include <iostream>
using namespace std;
32
void curva::dominio()
{
cout << "tmin = ";
cin >> tmin;
cout << "tmax = ";
cin >> tmax;
}
void curva::plota_curva()
{
float t,dt,v[2];
dt = (tmax - tmin)/pontos;
glColor3f (1.0, 0.0, 0.0);
t = tmin;
glBegin ( GL_POINTS);
for (int i = 0; i < pontos; i++) {
c(t,v);
glVertex2f (v[0],v[1]);
t = t + dt;
}
glEnd();
}
main.cpp
#include <gl\glut.h>
#include "curva.h"
#include "window.h"
#include "Stack.h"
#include <iostream>
using namespace std;
33
window w(-5,5,-5,5);
curva c(400,0,6.29);
Stack P;
void plota_eixo()
{
glColor3f (0.0, 1.0, 0.0);
glBegin (GL_LINES);
glVertex2f (w.getL(),0);
glVertex2f (w.getR(),0);
glVertex2f (0,w.getB());
glVertex2f (0,w.getT());
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
c.plota_curva();
if (mov == 1)
w.plota_retangulo(xv1,yv1,xv2,yv2,DIMX,DIMY);
glFlush();
glutSwapBuffers();
}
34
yv2 = y;
mov = 0;
if ((xv1 != xv2) && (yv1 != yv2)) {
P.push(w);
w.set_window(xv1,yv1,xv2,yv2,DIMX,DIMY);
glutPostRedisplay();
}
}
break;
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
cout << "Botao esquerdo pressionado em: x = " << x << " y =
" << y << endl;
if (!P.Empty()) {
w.set_window(P.pop());
glutPostRedisplay();
}
}
else
if (state == GLUT_UP)
cout << "Botao esquerdo solto em: x = " << x << " y = " << y
<< endl;
break;
}
}
Exerccio
35
2) x(t) = cos(2*t), y(t)= sin(2*t) (0 <= t <= 2*PI) (Qual a diferena para a
curva do programa ?)
3) x(t) = cos(t), y(t)= sin(2*t)
4) x(t) = 2 * cos(t), y(t)= 3 * sin(t) (0 <= t <= 2*PI) .
5) Como voc poderia visualizar grficos de funes em uma varivel y = f(x) com este programa
? Visualize y=x*x, y = sin(x), y = ln(x).
6) Visualize o vetor tangente em alguns pontos da curva.
As coordenadas polares podem ser relacionadas com as coordenadas retangulares (ou cartesianas) atravs
das expresses abaixo:
r = 1
d) Cardiide
e) Espiral
f) Roscea
36
4.4 Exemplo: Visualizao de Curvas Polares
Para visualizar as curvas polares, podemos utilizar o mesmo programa das curvas paramtricas. Para isso,
considere uma curva dada na forma polar:
Assim temos uma curva na forma paramtrica. Como exemplo vamos visualizar a curva do cardiide,
alterando apenas a classe curva do programa anterior:
.
.
.
float curva::r(float theta)
{
float r;
r = 1 + cos(theta);
return(r);
}
Exerccios
1) Como exerccio visualize as demais curvas dadas em coordenadas polares.
2) Visualize a curva dada em coordenadas polares por r = sec(theta).
3) Faa o grafico das seguintes curvas:
(a)
(b)
(c)
(d)
(e)
(f)
37
38
5. CURVAS IMPLCITAS
5.1 Introduo
J aprendemos na seo 3 como representar curvas na forma paramtrica. Vamos discutir agora outro tipo
de representao muito utilizada para curvas: a representao implcita.
A equao implcita de uma curva descreve uma relao entre as coordenadas x e y dos pontos que
pertencem a curva. Assim no plano xy a equao implcita de uma curva tem a forma :
Como exemplo a representao implcita de uma circunferncia de raio 1 centrado na origem dado por:
Qual das duas representaes mais vantajosa em termos computacionais ? Na verdade ambas
representaes tm vantagens e desvantagens em comparao uma com a outra. Por exemplo, muito
simples determinar se um ponto dado pertence ou no a uma curva dada na forma implcita.
J na forma paramtrica simples determinar pontos que pertenam a curva, para que se possa fazer uma
representao grfica da curva (como foi feito na seo anterior). Vamos agora resolver este ltimo
problema para uma curva dada na forma implcita, ou seja, vamos representar graficamente a curva
implcita.
Observe que no simples exibir um conjunto de pontos que pertenam a esta curva. Vamos definir uma
funo de duas variveis utilizando a equao acima, da seguinte forma:
- Para cada tringulo, observamos os sinais = sinal( ) obtidos em cada vrtice e temos as
seguintes situaes:
- Se V1 * V2 < 0, ento a funo se anula em um ponto entre V1 e V2. Este ponto pode ser
aproximado linearmente.
39
- Se V2 * V3 < 0, ento a funo se anula em um ponto entre V2 e V3.
curva_implicita.h
#include <cmath>
class curva_implicita {
int pontos;
float xmin,xmax,ymin,ymax;
public:
void dominio();
void plota_curva();
};
curva_implicita.cpp
#include <gl\glut.h>
#include <cmath>
#include "curva_implicita.h"
#include <iostream>
using namespace std;
void curva_implicita::dominio()
{
cout << "xmin = ";
cin >> xmin;
cout << "xmax = ";
cin >> xmax;
40
cout << "ymin = ";
cin >> ymin;
cout << "ymax = ";
cin >> ymax;
}
glColor3f(0,0,1);
glBegin(GL_LINE_LOOP);
glVertex2f(xf[0],yf[0]);
glVertex2f(xf[1],yf[1]);
glVertex2f(xf[2],yf[2]);
glEnd();
for(j=0;j<3;j++)
s[j] = f(xf[j],yf[j]);
for(j=0;j<3;j++) {
if (s[j] == 0) {
x[i] = xf[j];
y[i] = yf[j];
i++;
}
}
41
if (i == 2) {
glLineWidth(2.0f);
glColor3f(1.0f,0.0f,0.0f);
glBegin(GL_LINES);
glVertex2f(x[0],y[0]);
glVertex2f(x[1],y[1]);
glEnd();
glLineWidth(1.0f);
}
}
void curva_implicita::plota_curva()
{
float tx[3];
float ty[3];
float x,y;
float dx = (xmax - xmin)/pontos;
float dy = (ymax - ymin)/pontos;
glColor3f(1.0f,0.0f,0.0f);
x = xmin;
for(int i=0;i<pontos;i++)
{
y = ymin;
for(int j=0;j<pontos;j++)
{
tx[0] = x; tx[1] = x + dx; tx[2] = x;
ty[0] = y; ty[1] = y; ty[2] = y + dy;
calcula_curva(tx,ty);
tx[0] = x + dx; tx[1] = x; tx[2] = x + dx;
ty[0] = y + dy; ty[1] = y + dy; ty[2] = y;
calcula_curva(tx,ty);
y += dy;
}
x += dx;
}
}
Exerccio
1) Como exerccio implemente as seguintes curvas implcitas:
a) . c) .
b) . d)
2) Implemente no programa uma rotina que imprima simultaneamente varias curvas de nivel de uma
mesma funo , ou seja . Por exemplo, .
42
Captulo III Aplicaes Grficas 3D........................................................................... 2
1- TRANSFORMAES DE VISUALIZAO ...........................................................................2
1.1 - Introduo ......................................................................................................................................... 2
1.2 Transformaes .............................................................................................................................. 5
1.3 - Comandos de Auxlio ...................................................................................................................... 5
1.4- Exemplo: cubo unitrio .................................................................................................................... 6
1.5 - Transformaes de Modelagem e Visualizao......................................................................... 8
1.6- Projeo Ortogrfica ...................................................................................................................... 10
1.7- ngulos de Euler............................................................................................................................. 10
1.8 - Criando um Ambiente de Visualizao 3D ................................................................................ 11
1.9 Comando glLookAt ........................................................................................................................ 14
1.10 Visualizao de grfico de funes ......................................................................................... 15
2- ILUMINAO ..........................................................................................................................18
2.1 Introduo ...................................................................................................................................... 18
2.2 Criando Fontes de Luz................................................................................................................. 22
2.3 Selecionando o Modelo de Iluminao ...................................................................................... 23
2.4 Selecionando as Propriedades do Material............................................................................... 24
2.5 Visualizando as normais.............................................................................................................. 27
3-SUPERFCIES PARAMTRICAS...........................................................................................28
4- SUPERFCIES IMPLCITAS .................................................................................................32
4.1 Introduo ...................................................................................................................................... 32
4.2 Visualizao de Superfcies Implcitas ...................................................................................... 32
4.3 Implementao.............................................................................................................................. 34
5- TEXTURA .................................................................................................................................41
5.1 Introduo ...................................................................................................................................... 41
5.2 Parmetros Bsicos ..................................................................................................................... 41
5.3 Aplicao em Superfcies Paramtricas ................................................................................... 43
6- Curvas de Bezier........................................................................................................................50
6.1 Introduo ...................................................................................................................................... 50
1
Captulo III Aplicaes Grficas 3D
1- TRANSFORMAES DE VISUALIZAO
1.1 - Introduo
Nosso objetivo nesta seo descrever a gerao de uma imagem bi-dimensional partindo de um objeto tri-
dimensional. Para isso vamos partir de um exemplo: um cubo. A idia construir algum tipo de visualizao
deste cubo, que nos transmita a sensao de estar visualizando um objeto 3-dimensional.
Vamos considerar o cubo da figura abaixo:
v0 (0,0,0) v4 (0,0,1)
v1 (1,0,0) v5 (1,0,1)
v2 (1,1,0) v6 (1,1,1)
v3 (0,1,0) v7 (0,1,1)
Para visualizar este modelo, uma primeira estratgia seria definir uma projeo de nosso modelo 3D para o bi-
dimensional.
Cubo.h
/* * * * * * * * * * * * * * * * */
/* Modulo: cubo.h */
/* * * * * * * * * * * * * * * * */
class cubo {
float P[8][3];
public:
cubo();
void inicializa();
void rotaciona_x(double t);
void rotaciona_y(double t);
void rotaciona_z(double t);
void draw_cube();
};
Cubo.cpp
/* * * * * * * * * * * * * * * * */
/* Modulo: cubo.cpp */
/* * * * * * * * * * * * * * * * */
#include "cubo.h"
#include <gl\glut.h>
#include <math.h>
#define PI 3.1415926535897932384626433832795
/* -------------------------------- */
cubo::cubo()
/* -------------------------------- */
{
inicializa();
}
2
void cubo::inicializa()
{
P[0][0] = 0; P[4][0] = 0;
P[0][1] = 0; P[4][1] = 0;
P[0][2] = 0; P[4][2] = 1;
P[1][0] = 1; P[5][0] = 1;
P[1][1] = 0; P[5][1] = 0;
P[1][2] = 0; P[5][2] = 1;
P[2][0] = 1; P[6][0] = 1;
P[2][1] = 1; P[6][1] = 1;
P[2][2] = 0; P[6][2] = 1;
P[3][0] = 0; P[7][0] = 0;
P[3][1] = 1; P[7][1] = 1;
P[3][2] = 0; P[7][2] = 1;
}
/* -------------------------------- */
void cubo::rotaciona_x(double t)
/* -------------------------------- */
{
float y,z;
for(int i =0; i < 8 ;i++) {
y = P[i][1] * cos(t) - P[i][2] * sin(t);
z = P[i][1] * sin(t) + P[i][2] * cos(t);
P[i][1] = y; P[i][2] = z;
}
}
/* -------------------------------- */
void cubo::rotaciona_y(double t)
/* -------------------------------- */
{
float x,z;
for(int i =0; i < 8 ;i++) {
x = P[i][0] * (float) cos(t) - P[i][2] * (float) sin(t);
z = P[i][0] * (float) sin(t) + P[i][2] * (float) cos(t);
P[i][0] = x; P[i][2] = z;
}
/* -------------------------------- */
void cubo::rotaciona_z(double t)
/* -------------------------------- */
{
float x,y;
for(int i =0; i < 8 ;i++) {
x = P[i][0] * (float) cos(t) - P[i][1] * (float) sin(t);
y = P[i][0] * (float) sin(t) + P[i][1] * (float) cos(t);
P[i][0] = x; P[i][1] = y;
}
}
/* -------------------------------- */
3
void cubo::draw_cube()
/* -------------------------------- */
{
inicializa();
rotaciona_z(PI / 4);
rotaciona_y(PI / 4);
rotaciona_z(PI / 6);
glBegin(GL_LINE_LOOP);
glVertex2f(P[0][0],P[0][1]);
glVertex2f(P[1][0],P[1][1]);
glVertex2f(P[2][0],P[2][1]);
glVertex2f(P[3][0],P[3][1]);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(P[4][0],P[4][1]);
glVertex2f(P[5][0],P[5][1]);
glVertex2f(P[6][0],P[6][1]);
glVertex2f(P[7][0],P[7][1]);
glEnd();
glBegin(GL_LINES);
glVertex2f(P[0][0],P[0][1]);
glVertex2f(P[4][0],P[4][1]);
glVertex2f(P[1][0],P[1][1]);
glVertex2f(P[5][0],P[5][1]);
glVertex2f(P[2][0],P[2][1]);
glVertex2f(P[6][0],P[6][1]);
glVertex2f(P[3][0],P[3][1]);
glVertex2f(P[7][0],P[7][1]);
glEnd();
}
Main.cpp
/* * * * * * * * * * * * * * * * * */
/* Modulo: Main.cpp */
/* * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include "cubo.h"
cubo p;
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
p.draw_cube();
glutSwapBuffers();
}
4
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cube");
glutDisplayFunc(redesenha);
glOrtho(-2,2,-2,2,-2,2);
glutMainLoop();
}
1.2 Transformaes
As transformaes necessrias para visualizao de uma cena podem ser comparadas ao processo de
fotografar uma cena real [OpenGL Guide pg. 65]:
Para especificar uma transformao o OpenGL constri uma matriz 4x4 que representa a transformao
desejada. Esta matriz ento multiplicada pelas coordenadas de cada vrtice na cena. As transformaes de
Modelagem e Visualizao so combinadas em uma nica matriz denominada MODELVIEW matrix. A
transformao de projeo armazenada na PROJECTION matrix.
GlMatrixMode(Glenum tipo);
5
Este comando especifica a matriz a ser alterada. Existem trs argumentos conforme o tipo da matriz:
1) GL_MODELVIEW
2) GL_PROJECTION
3) GL_TEXTURE
As transformaes subsequentes afetam a matriz especificada. Observe que somente uma matriz pode ser
alterada por vez.
GlLoadIdentity(void);
Este comando carrega a matriz identidade na matriz corrente especificada anteriormente pelo
GlMatrixMode. O objetivo limpar qualquer alterao anterior realizada sobre a matriz.
Quando voc deseja especificar uma matriz M particular para ser a matriz corrente, utilize o
glLoadMatrix(M).
cubo.cpp
/* * * * * * * * * * * * * * * * */
/* Modulo: cubo.cpp */
/* * * * * * * * * * * * * * * * */
#include "cubo.h"
#include <gl\glut.h>
/* -------------------------------- */
cubo::cubo()
/* -------------------------------- */
{
inicializa();
}
void cubo::inicializa()
{
P[0][0] = 0; P[4][0] = 0;
P[0][1] = 0; P[4][1] = 0;
6
P[0][2] = 0; P[4][2] = 1;
P[1][0] = 1; P[5][0] = 1;
P[1][1] = 0; P[5][1] = 0;
P[1][2] = 0; P[5][2] = 1;
P[2][0] = 1; P[6][0] = 1;
P[2][1] = 1; P[6][1] = 1;
P[2][2] = 0; P[6][2] = 1;
P[3][0] = 0; P[7][0] = 0;
P[3][1] = 1; P[7][1] = 1;
P[3][2] = 0; P[7][2] = 1;
}
/* -------------------------------- */
void cubo::draw_cube()
/* -------------------------------- */
{
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex3f(P[0][0],P[0][1],P[0][2]);
glVertex3f(P[1][0],P[1][1],P[1][2]);
glVertex3f(P[2][0],P[2][1],P[2][2]);
glVertex3f(P[3][0],P[3][1],P[3][2]);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(P[4][0],P[4][1],P[4][2]);
glVertex3f(P[5][0],P[5][1],P[5][2]);
glVertex3f(P[6][0],P[6][1],P[6][2]);
glVertex3f(P[7][0],P[7][1],P[7][2]);
glEnd();
glBegin(GL_LINES);
glVertex3f(P[0][0],P[0][1],P[0][2]);
glVertex3f(P[4][0],P[4][1],P[4][2]);
glVertex3f(P[1][0],P[1][1],P[1][2]);
glVertex3f(P[5][0],P[5][1],P[5][2]);
glVertex3f(P[2][0],P[2][1],P[2][2]);
glVertex3f(P[6][0],P[6][1],P[6][2]);
glVertex3f(P[3][0],P[3][1],P[3][2]);
glVertex3f(P[7][0],P[7][1],P[7][2]);
glEnd();
}
Main.cpp
/* * * * * * * * * * * * * * * * * */
/* Modulo: Main.cpp */
/* * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include "cubo.h"
cubo p;
void inicia_config()
7
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2,2,-2,2,-2,2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gama,0,0,1); // eixo x
glRotatef(phi,1,0,0); // eixo z
glRotatef(theta,0,0,1); // eixo x
}
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
p.draw_cube();
glutSwapBuffers();
}
1.5.1- Translao
Este comando multiplica a matriz corrente por uma matriz que translada o objeto conforme o vetor .
1.5.2- Rotao
Multiplica a matriz corrente por uma matriz que rotaciona o objeto no sentido anti-horrio de theta graus,
8
1.5.3- Escala
1.5.4-Exemplo
Como exemplo vamos apresentar um programa que executa as trs transformaes citadas acima. Partindo de
um tringulo, desenhamos este tringulo quatro vezes sendo que:
- O tringulo vermelho desenhado sem nenhuma transformao.
- O tringulo verde sofreu uma translao.
- O tringulo azul sofreu uma rotao.
- O tringulo amarelo sofreu uma transformao de escala.
#include <gl\glut.h>
void draw_triangulo()
{
glBegin(GL_LINE_LOOP);
glVertex3f(0.0,0.0,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.25,0.43,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
draw_triangulo();
glColor3f(0.0,1.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef( 0.5, 0.5,0.0);
draw_triangulo();
glColor3f(0.0,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(45,0.0,0.0,1.0);
draw_triangulo();
glColor3f(1.0,1.0,0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(0.5, 0.5,0.5);
draw_triangulo();
glFlush();
}
A seqncia inicia rotacionando o sistema de coordenadas xyz por um ngulo no sentido anti-horrio em
torno do eixo z.
10
Em seguida o sistema de coordenadas resultante rotacionado em torno do eixo y de graus.
Por fim o sistema de coordenadas sofre uma nova rotao de em torno do eixo z.
Como primeiro passo vamos desenhar os trs eixos de referencia, mantendo a seguinte escala de cores:
- Eixo x: vermelho
- Eixo y: verde
- Eixo z: azul
Uma posio inicial para a visualizao pode ser obtida utilizando-se os ngulos theta = 135, phi = 45,
gamma=90.
11
Main.cpp
#include <gl\glut.h>
float gamma=90.0,phi=45.0,theta=135.0;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_eixos();
glFlush();
}
void inicia_config()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
}
12
1.8.2- Alterando os ngulos de Euler
Vamos agora acrescentar a possibilidade de alterar os ngulos com auxlio do mouse. Com o boto Esquerdo
do mouse pressionado, quando o mouse anda na direo horizontal, alteramos theta, quando o mouse anda na
direo vertical alteramos phi.
#include <gl\glut.h>
int xm,xb,ym,yb;
float gamma=90.0,phi=45.0,theta=135.0;
void draw_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,1.0,0.0);
draw_eixos();
glFlush();
}
void inicia_config()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-10.0,10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
}
switch(b) {
13
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xb = x;
yb = y;
break;
case GLUT_UP:
theta = theta + xm - xb;
phi = phi - ym + yb ;
break;
}
break;
}
}
14
1.10 Visualizao de grfico de funes
Main.cpp
#include <gl\glut.h>
#include "funcao.h"
void plota_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void inicia_config()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-20.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glScalef(scale,scale,scale);
}
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixos();
f.plota_funcao();
glutSwapBuffers();
}
15
void keyboard(unsigned char key, int x, int y)
{
switch(key)
{
case 'S':
scale += 0.2;
inicia_config();
redesenha();
break;
case 's':
scale -= 0.2;
inicia_config();
redesenha();
break;
}
}
funcao.h
class funcao {
float xmin,xmax,ymin,ymax;
int points;
public:
funcao(float xm = -1,float xM = 1,float ym = -1,float yM =
1,int p = 10) {
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
points = p ;
}
void plota_funcao();
};
funcao.cpp
#include <gl/glut.h>
#include "funcao.h"
void funcao::plota_funcao() {
float x,y;
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
17
2- ILUMINAO
2.1 Introduo
Para adicionar iluminao so necessrias quatro etapas bsicas:
O modelo de iluminao do OPENGL considera que a iluminao pode ser dividida em trs componentes
independentes: ambiente, difusa e especular.
- Luz Ambiente: a luz proveniente de uma fonte dispersa tal que sua direo no pode ser determinada.
- Luz Difusa: uma luz proveniente de uma nica direo que quando incide sobre o objeto no mantm
uma direo preferencial, e se divide em componentes em todas as direes.
- Luz Especular: a luz proveniente de uma direo particular e tende a refletir em uma direo
preferencial.
A cor de uma fonte de luz caracterizada pela intensidade de cada uma de suas componentes: vermelho,
verde e azul.
O material da superfcie caracterizado pela quantidade de luz refletida ou absorvida. Um material verde,
refle a luz verde e absorve as outras componentes, por exemplo. O material tem as mesmas caractersticas de
uma fonte de luz, sendo necessrio definir qual o seu comportamento relativo luz ambiente, difusa e
especular.
Para determinar a iluminao de cada face de um objeto, um elemento essencial deve ser introduzido agora: o
vetor normal em cada vrtice. Assim, a cada vrtice introduzido via glVertex3f(x,y,z), corresponde
um vetor normal definido por glNormal3f(vx,vy,vz). A normal deve ser especificada antes do vrtice,
ou seja, a sequncia de comandos deve ser:
.
.
.
glNormal3f(vx,vy,vz);
glVertex3f(x,y,z);
.
.
.
Vamos iniciar com um simples exemplo, ilustrando as dificuldades de se estabelecer uma boa iluminao.
Nosso primeiro exemplo um toro, gerado pelo comando glutSolidTorus, onde se estabeleceu uma
iluminao bsica, porm no satisfatria ainda. A classe iluminao foi definida com alguns parmetros
bsicos.
18
iluminacao.h
class iluminacao {
float mat_specular[4];
float mat_shininess;
float light_position[4];
public:
iluminacao();
void light_on();
void render_light();
void light_off();
};
iluminao.cpp
#include <gl/glut.h>
#include "iluminacao.h"
iluminacao::iluminacao() {
mat_specular[0] = 1.0f;
mat_specular[1] = 1.0f;
mat_specular[2] = 1.0f;
mat_specular[3] = 1.0f;
mat_shininess = 50.0f;
light_position[0] = 2.0f;
light_position[1] = 2.0f;
light_position[2] = 2.0f;
light_position[3] = 1.0f;
}
void iluminacao::light_on() {
glShadeModel (GL_FLAT); // GL_SMOOTH or GL_FLAT
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_NORMALIZE);
}
void iluminacao::render_light() {
glColor3f(1,0,0);
glPointSize(8);
glBegin(GL_POINTS);
glVertex3f(light_position[0],
light_position[1],
light_position[2]);
glEnd();
}
void iluminacao::light_off() {
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
}
19
main.cpp
include <gl\glut.h>
#include "iluminacao.h"
void plota_eixos()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-20.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glScalef(scale,scale,scale);
}
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixos();
I.light_on();
glColor3f(1,1,0);
glutSolidTorus(0.5,1, 20, 10);
I.render_light();
I.light_off();
glutSwapBuffers();
}
21
2.2 Criando Fontes de Luz
.
As fontes de luz tm certas propriedades que devem ser definidas (Cor, direo, posio, etc.). O comando
para especificar essas propriedades :
O parmetro luz indica apenas qual fonte de luz estamos trabalhando. Existem no mximo oito fontes que so:
GL_LIGHT0, GL_LIGHT1, ... , GL_LIGHT7. Por default a luz GL_LIGHT0 inicia com a cor
branca e as sete luzes restantes ficam apagadas (luz preta).
2.2.1 Cor
Para cada fonte de luz existem trs parmetros principais relacionados a cor:
- Luz Ambiente: a luz proveniente de uma fonte dispersa tal que sua direo no pode ser determinada.
- Luz Difusa: a luz proveniente de uma nica direo que ao incidir sobre a superfcie do material, se
reflete em todas as direes. Define a luz que naturalmente definiramos como a cor da luz.
- Luz Especular: a luz proveniente de uma direo particular e tende a refletir em uma direo
preferencial. Se voc quer criar efeitos realsticos, mantenha a luz especular com os mesmos parmetros
da luz difusa.
Cada um desses parmetros defindo pelos 4 atributos: R,G,B,A. Por exemplo, para alterar a luz ambiente
utiliza-se o seguinte cdigo:
22
2.2.2 Posio
- Direcional: quando a fonte de luz considerada no infinito. Neste caso os raios de luz incidem
paralelos ao objeto. Para obter, por exemplo, uma fonte de luz branca voc deve utilizar o seguinte
cdigo:
- Posicional : Se o ltimo valor do vetor luz_posicao[] for diferente de zero, a luz posicional e
sua localizao definida pelo vetor:
Cada fonte de luz pode contribuir com uma parcela da luz ambiente. Alm disso, possvel adicionar uma
outra parcela de luz ambiente que no dependa das fontes de iluminao. Para isso utiliza-se os comandos:
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, luz_ambiente_modelo);
Observe que neste caso, mesmo que todas as fontes de luz estejam desligadas ainda assim ser possvel ver os
objetos na cena.
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
O clculo da iluminao feito para todos os polgonos. possvel considerar diferentes iluminaes nos dois
lados de um polgono. Para isso utilize:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
No OpenGL voc precisa explicitamente habilitar a iluminao. Para isso utilize o comando:
glEnable(GL_LIGHTING);
glDisable(GL_LIGHTING);
23
2.4 Selecionando as Propriedades do Material
Para definir as propriedades do material do objeto em cena utilizamos o seguinte comando:
iluminacao.h
class iluminacao {
float mat_specular[4];
float mat_shininess;
float light_position[4];
float light_diffuse[4];
public:
iluminacao();
void light_on();
void render_light();
void light_off();
};
iluminacao.cpp
#include <gl/glut.h>
#include "iluminacao.h"
iluminacao::iluminacao() {
mat_specular[0] = 1.0f;
mat_specular[1] = 1.0f;
mat_specular[2] = 0.0f;
mat_specular[3] = 1.0f;
mat_shininess = 50.0f;
light_position[0] = 2.0f;
light_position[1] = 2.0f;
light_position[2] = 2.0f;
light_position[3] = 1.0f;
light_diffuse[0] = 1.0f;
light_diffuse[1] = 0.0f;
light_diffuse[2] = 0.0f;
light_diffuse[3] = 1.0f;
24
void iluminacao::light_on() {
glShadeModel (GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialf(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
glEnable(GL_NORMALIZE);
}
void iluminacao::render_light() {
glColor3f(1,0,0);
glPointSize(8);
glBegin(GL_POINTS);
glVertex3f(light_position[0],
light_position[1],
light_position[2]);
glEnd();
}
void iluminacao::light_off() {
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_DEPTH_TEST);
}
funcao.h
#include <cmath>
class funcao {
float xmin,xmax,ymin,ymax;
int points;
public:
funcao(float xm=-1,float xM=1,float ym=-1,float yM=1,int p=10) {
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
points = p ;
}
float f(float x,float y) {
return(x*x-y*y);
//return(cos(sqrt(x*x+y*y)));
}
float dfx(float x,float y) {
return(2*x);
//return((-sin(sqrt(x*x+y*y))*x/sqrt(x*x+y*y)));
}
float dfy(float x,float y) {
return(-2*y);
//return((float)(-sin(sqrt(x*x+y*y))*y/sqrt(x*x+y*y)) );
}
void normal(float *v,float x,float y);
void plota_funcao_01();
void plota_funcao_02();
};
25
funcao.cpp
#include <gl/glut.h>
#include "funcao.h"
void funcao::normal(float *v,float x,float y) {
v[0] = -dfx(x,y);
v[1] = -dfy(x,y);
v[2] = 1;
}
void funcao::plota_funcao_01() {
float x,y;
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
glColor3f (1.0f, 1.0f, 1.0f);
x = xmin;
for(int i=0;i<points;i++) {
y = ymin;
for(int j=0;j<points;j++){
glBegin(GL_LINE_LOOP);
glVertex3f(x ,y ,f(x ,y) );
glVertex3f(x+dx,y ,f(x+dx,y) );
glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
glVertex3f(x ,y+dy,f(x ,y+dy));
glEnd();
y += dy;
}
x += dx;
}
}
void funcao::plota_funcao_02() {
float x,y,v[3];
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
x = xmin;
for(int i=0;i<points;i++) {
y = ymin;
for(int j=0;j<points;j++){
glBegin(GL_QUADS);
normal(v,x,y);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x ,y ,f(x ,y) );
normal(v,x+dx,y);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+dx,y ,f(x+dx,y) );
normal(v,x+dx,y+dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
normal(v,x,y+dy);
glNormal3f(v[0],v[1],v[2]);
glVertex3f(x ,y+dy,f(x ,y+dy));
glEnd();
y += dy;
}
x += dx;
}
}
26
2.5 Visualizando as normais
Podemos acrescentar um novo metodo para visualizarmos as normais sobre a superfcie.
funcao.cpp
.
.
.
void funcao::plota_normal() {
float x,y,v[3];
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
float n = 10;
normal(v,x+dx,y);
glVertex3f(x+dx,y ,f(x+dx,y) );
glVertex3f(x+dx+v[0]/n,y+v[1]/n,f(x+dx,y)+v[2]/n);
normal(v,x+dx,y+dy);
glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
glVertex3f(x+dx+v[0]/n,y+dy+v[1]/n,f(x+dx,y+dy)+v[2]/n);
normal(v,x,y+dy);
glVertex3f(x ,y+dy,f(x ,y+dy));
glVertex3f(x+v[0]/n,y+dy+v[1]/n,f(x,y+dy)+v[2]/n);
glEnd();
y += dy;
}
x += dx;
}
}
27
3-SUPERFCIES PARAMTRICAS
Considere D uma regio do plano. A cada par de D vamos associar um ponto no espao tri-
dimensional, o qual pode ser escrito em termos de suas funes coordenadas por:
void superficie::plota_superficie_01() {
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
float r[3],n[3];
s(r,u+du,v);
glVertex3f(r[0],r[1],r[2]);
s(r,u+du,v+dv);
glVertex3f(r[0],r[1],r[2]);
s(r,u,v+dv);
glVertex3f(r[0],r[1],r[2]);
glEnd();
v += dv;
}
u += du;
}
}
void superficie::plota_superficie_02() {
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
float r[3],n[3];
float p1[3];
float p2[3];
float p3[3];
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
s(p1,u,v);
s(p2,u,v+dv);
s(p3,u+du,v);
v1[0] = p2[0]-p1[0] ;
v1[1] = p2[1]-p1[1];
v1[2] = p2[2]-p1[2];
v2[0] = p3[0]-p1[0];
v2[1] = p3[1]-p1[1];
v2[2] = p3[2]-p1[2];
void superficie::plota_normal() {
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
float r[3],n[3];
Exerccios
1) Utilizando o programa anterior, visualize as seguintes superfcies e identifique-as:
a) b) c) d)
e) f) g)
31
4- SUPERFCIES IMPLCITAS
4.1 Introduo
Na seo de curva implcita, vimos que na forma implcita uma curva representada pela equao:
Por exemplo:
Nossa estratgia semelhante ao algoritmo de curvas implcitas, porm, agora temos uma dimenso a mais.
Assim, nosso domnio ser [xmin, xmax] x [ymin,ymax] x [zmin,zmax]. Ao invs de quadrados, teremos
cubos, e ao invs de tringulos, teremos tetraedros. No algoritmo de curvas implcitas, buscamos obter o
segmento de reta em cada tringulo que pertencia a curva, agora estamos buscando obter uma face em cada
tetraedro analisado.
- A cada cubo, obtemos seis tetraedros: Partindo de um cubo, a construo feita da seguinte forma: 1)
enumerar os vrtices do cubo, como na figura; 2) trace uma diagonal do cubo unindo v0 e v7; 2) Projete
esta diagonal em cada uma das seis faces do cubo; 3) os tetraedros sero obtidos selecionando os vrtices
que esto conectados, iniciando em v0 e terminando em v7. Assim por exemplo, considere os vrtices do
cubo {v0,v1,v2,v3,v4,v5,v6,v7}, ento teremos os tetraedros:
T1 = {v0,v2,v6,v7}
T2 = {v0,v4,v6,v7}
T3 = {v0,v1,v5,v7}
T4 = {v0,v1,v3,v7}
T5 = {v0,v4,v5,v7}
T6 = {v0,v2,v3,v7}
32
O resultado ser um grid, com seis tetraedros em cada cubo, como na figura abaixo:
- Para cada tetraedro temos quatro vrtices (Vi, i=0,1,2,3) e observamos os sinais = sinal(Vi) obtidos
em cada vrtice. Analisando cada uma das seis arestas do tetraedro, teremos:
- Se S1 * S2 < 0, ento a funo se anula em um ponto entre V1 e V2. Este ponto pode ser aproximado
linearmente.
33
- Se S1 * S3 < 0, ento a funo se anula em um ponto entre V1 e V3.
- Considerando que exatamente trs ou quatro das condies acima se verificaram simultaneamente,
aproximamos a superfcies nesse tetraedro, gerando um tringulo com os trs pontos (a figura abaixo
ilustra esse caso), ou um quadriltero com os quatro pontos (no algoritmo optamos por triangular esse
quadriltero, gerando dois tringulos).
4.3 Implementao
Main.cpp
#include <gl\glut.h>
#include "implicito.h"
void plota_eixos()
{
34
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex3f(10.0,0.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex3f(0.0,10.0,0.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINES);
glVertex3f(0.0,0.0,10.0);
glVertex3f(0.0,0.0,0.0);
glEnd();
}
void inicia_config()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0,2.0,-2.0,2.0,-20.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gamma,0.0,0.0,1.0);
glRotatef(phi,0.0,1.0,0.0);
glRotatef(theta,0.0,0.0,1.0);
glScalef(scale,scale,scale);
}
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixos();
glColor3f(1,1,0);
S.plota_superficie();
glutSwapBuffers();
}
implcito.h
class implicito {
float xmin,xmax,ymin,ymax,zmin,zmax;
int pontos;
public:
implicito(float xm = -1, float xM = 1, float ym = -1, float yM =
1, float zm = -1, float zM = 1, int p = 10)
{
xmin = xm; xmax = xM;
ymin = ym; ymax = yM;
zmin = zm; zmax = zM;
pontos = p;
}
int get_pontos() {
36
return pontos;
}
void set_pontos(int p) {
pontos = p;
}
};
implcito.cpp
#include <gl/glut.h>
#include <cmath>
#include "implicito.h"
w0 = f(v0[0],v0[1],v0[2]);
w1 = f(v1[0],v1[1],v1[2]);
w2 = f(v2[0],v2[1],v2[2]);
w3 = f(v3[0],v3[1],v3[2]);
if (w0 * w1 < 0) {
t = -w0/(w1-w0);
for(i=0;i<3;i++)
p[n][i] = v0[i] + t * (v1[i] - v0[i]);
n++;
}
if (w1 * w3 < 0) {
t = -w1/(w3-w1);
for(i=0;i<3;i++)
p[n][i] = v1[i] + t * (v3[i] - v1[i]);
n++;
}
if (w0 * w3 < 0) {
t = -w0/(w3-w0);
37
for(i=0;i<3;i++)
p[n][i] = v0[i] + t * (v3[i] - v0[i]);
n++;
}
if (w2 * w3 < 0) {
t = -w2/(w3-w2);
for(i=0;i<3;i++)
p[n][i] = v2[i] + t * (v3[i] - v2[i]);
n++;
}
if (w0 * w2 < 0) {
t = -w0/(w2-w0);
for(i=0;i<3;i++)
p[n][i] = v0[i] + t * (v2[i] - v0[i]);
n++;
}
if (w1 * w2 < 0) {
t = -w1/(w2-w1);
for(i=0;i<3;i++)
p[n][i] = v1[i] + t * (v2[i] - v1[i]);
n++;
}
if (n == 3) { // Triangulo
#if TETRA
glColor3f(0,0,1);
glBegin(GL_LINE_LOOP);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v2);
glEnd();
glBegin(GL_LINES);
glVertex3fv(v0);
glVertex3fv(v3);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
glVertex3fv(v3);
glEnd();
#endif
// glBegin(GL_LINE_LOOP);
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(p[0][0],p[0][1],p[0][2]);
glVertex3f(p[1][0],p[1][1],p[1][2]);
glVertex3f(p[2][0],p[2][1],p[2][2]);
glEnd();
glLineWidth(3);
glBegin(GL_LINE_LOOP);
glColor3f(1,1,1);
glVertex3f(p[0][0],p[0][1],p[0][2]);
glVertex3f(p[1][0],p[1][1],p[1][2]);
glVertex3f(p[2][0],p[2][1],p[2][2]);
glEnd();
glLineWidth(1);
}
if (n == 4) { // QUADS
#if TETRA
38
glColor3f(0,0,1);
glBegin(GL_LINE_LOOP);
glVertex3fv(v0);
glVertex3fv(v1);
glVertex3fv(v2);
glEnd();
glBegin(GL_LINES);
glVertex3fv(v0);
glVertex3fv(v3);
glVertex3fv(v1);
glVertex3fv(v3);
glVertex3fv(v2);
glVertex3fv(v3);
glEnd();
#endif
glColor3f(1,1,1);
glLineWidth(3);
glBegin(GL_LINE_LOOP);
glVertex3f(p[0][0],p[0][1],p[0][2]);
glVertex3f(p[1][0],p[1][1],p[1][2]);
glVertex3f(p[2][0],p[2][1],p[2][2]);
glVertex3f(p[3][0],p[3][1],p[3][2]);
glEnd();
glLineWidth(1);
glColor3f(0,1,0);
glBegin(GL_QUADS);
glVertex3f(p[0][0],p[0][1],p[0][2]);
glVertex3f(p[1][0],p[1][1],p[1][2]);
glVertex3f(p[2][0],p[2][1],p[2][2]);
glVertex3f(p[3][0],p[3][1],p[3][2]);
glEnd();
}
}
void implicito::plota_superficie()
{
int i,j,k;
float x,y,z;
float dx,dy,dz;
float z0,z1,z2,z3;
float v[8][3];
dx = (xmax-xmin)/pontos;
dy = (ymax-ymin)/pontos;
dz = (zmax-zmin)/pontos;
glColor3f(1.0,1.0,1.0);
x = xmin;
for(i=0;i < pontos; i++)
{
y = ymin;
for(j=0 ; j < pontos; j++)
{
z = zmin;
for(k=0; k< pontos; k++)
{
v[0][0] = x ; v[1][0] = x+dx; v[2][0] = x ;
39
v[3][0] = x+dx;
v[0][1] = y ; v[1][1] = y ; v[2][1] = y+dy;
v[3][1] = y+dy;
v[0][2] = z ; v[1][2] = z ; v[2][2] = z ;
v[3][2] = z ;
tetraedro(v[0],v[1],v[3],v[7]);
tetraedro(v[0],v[1],v[5],v[7]);
tetraedro(v[0],v[2],v[3],v[7]);
tetraedro(v[0],v[2],v[6],v[7]);
tetraedro(v[0],v[4],v[5],v[7]);
tetraedro(v[0],v[4],v[6],v[7]);
z += dz;
}
y += dy;
}
x += dx;
}
40
5- TEXTURA
5.1 Introduo
Texturas permitem que imagens sejam aplicadas sobre as faces de um objeto. Por exemplo, podemos
copiar uma imagem de um piso nos polginos que representam o cho de uma sala. No OpenGL, uma textura
pode ser unidimendional, bidimensional ou at tridimensional, embora o caso bidimensional seja o principal.
Para usar uma textura no OpenGL podemos destacar quatro etapas bsicas [The OpenGL Programming
Guide - The Redbook]:
1. Criar uma textura
2. Indicar como a textura ser aplicada em cada pixel.
3. Habilitar o modo textura.
4. Definir os parmetros da textura no modelo geomtrico.
O comando glGenTextures serve apenas para retornar um inteiro ainda no usado para nomear uma
textura. O inteiro retornado na varivel textureNames.
Exemplo:
GLuint nameTex;
glGenTextures(1, &nameTex);
Etapa 2:
A textura pode ser reduzida ou ampliada sobre a superfcie.
41
(Figura extrada de: The OpenGL Programming Guide - The Redbook - 5th Edition The Official Guide to Learning
OpenGL Version 2.1)
Para definir os parmetros que controlam essas transformaes temos, por exemplo:
GLenum target:
GL_TEXTURE_1D
GL_TEXTURE_2D
GLenum pname,:
GL_TEXTURE_MAG_FILTER
GL_TEXTURE_MIN_FILTER
GLint param
1. Para GL_TEXTURE_MAG_FILTER:
o GL_NEAREST: retorna o valor do texel que estiver mais prximo.
o GL_LINEAR: retorna a media dos 4 elementos ao redor do pixel mais
prximo.
2. Para GL_TEXTURE_MIN_FILTER:
o GL_NEAREST
o GL_LINEAR
o GL_NEAREST_MIPMAP_NEAREST
o GL_NEAREST_MIPMAP_LINEAR
Exemplo:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
Define como a textura ir ser associada a cor do objeto. Temos 4 exemplos principais para o modelo
RGB:
42
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
Substitui a cor pela cor da textura.
Se voce deseja que uma unica textura seja distribuida sob a superfcie, preciso subdividi-la. Por exemplo em
uma superfcie parametrizada 10 x 10, a cada quad teremos:
class Textura {
GLuint texName;
unsigned char *imagem;
int dimx,dimy;
public:
Textura(char *s) ;
void init();
void texture_on();
void texture_off();
void draw_imagem();
};
43
Textura.cpp
#include <gl/glut.h>
#include <cstdio>
#include "textura.h"
// #define RGB
Textura::Textura(char *file)
{
FILE *fp;
int i,j,k,ind;
int g;
fp = fopen(file,"rb");
fscanf(fp,"%d %d %d",&dimx,&dimy,&i);
ind = 0;
for(i=0;i<dimx;i++) {
for(j=0;j<dimy;j++) {
#if RGB
for(k=0;k<3;k++) {
fscanf(fp,"%d",&g);
imagem[ind] = (unsigned char) g;
ind++;
#else
fscanf(fp,"%d",&g);
imagem[ind] = (unsigned char) g;
imagem[ind+1] = imagem[ind+2] = imagem[ind];
ind = ind + 3;
#endif
}
}
fclose(fp);
void Textura::init()
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1,&texName);
glBindTexture(GL_TEXTURE_2D, texName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// GL_REPEAT ou GL_CLAMP
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// GL_LINEAR ou GL_NEAREST
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// GL_BLEND , GL_REPLACE, GL_MODULATE GL_DECAL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, dimx,dimy, 0,
GL_RGB, GL_UNSIGNED_BYTE,imagem);
}
void Textura::texture_on()
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName);
}
void Textura::texture_off()
{
glDisable(GL_TEXTURE_2D);
44
}
void Textura::draw_imagem()
{
int ind = 0;
for(int i=0;i<dimx;i++)
for(int j = 0;j<dimy;j++) {
glColor3f(imagem[ind]/255.,imagem[ind+1]/255.,imagem[ind+2]/255.);
// Nao RGB
glBegin(GL_POINTS);
glVertex3i(i,j,0);
glEnd();
ind += 3;
}
}
main.cpp
#include<gl\glut.h>
#include "ilumina.h"
#include "parametrico.h"
#include "textura.h"
#include <iostream>
using namespace std;
int m = 0;
float phi = 0; //235
float theta = 0; //42
float gama = 0;
ilumina I;
int xi,yi,xf,yf;
void eixos()
{
glColor3f(1,0,0);
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glEnd();
glColor3f(0,1,0);
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(0,1,0);
glEnd();
glColor3f(0,0,1);
glBegin(GL_LINES);
glVertex3f(0,0,0);
glVertex3f(0,0,1);
glEnd();
void inicia()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
45
glLoadIdentity();
glOrtho(-2,2,-2,2,-2,2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gama,0,0,1);
glRotatef(phi,1,0,0);
glRotatef(theta,0,0,1);
void display()
{
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
eixos();
// I.light_on();
glColor3f(1,0,0);
T.texture_on();
p.draw_parametrico_textura1();
// T.draw_imagem();
// I.light_off();
T.texture_off();
glFlush();
glutSwapBuffers();
}
void rotaciona()
{
if (m == 1) {
I.rot_light(0.003);
glutPostRedisplay();
}
}
void botao(int b,int state,int x,int y)
{
if (b == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
xi = x;
yi = y;
}
}
}
glutIdleFunc(rotaciona);
glutKeyboardFunc(teclado);
glutMouseFunc(botao);
glutMotionFunc(botao_movimento);
glutMainLoop();
}
parametrico.h
class parametrico {
float umin,umax,vmin,vmax;
int pontos;
public:
parametrico(float um = -1, float uM = 1, float vm = -1, float vM = 1,
int p = 10)
{
umin = um; umax = uM;
vmin = vm; vmax = vM;
pontos = p;
}
void draw_parametrico();
void draw_parametrico_textura();
void draw_parametrico_textura1();
};
parametrico.cpp
#include <gl/glut.h>
#include <cmath>
#include "parametrico.h"
float p1[3];
float p2[3];
float p3[3];
p(u ,v ,p1);
p(u+du,v ,p2);
p(u ,v+dv,p3);
for(int i = 0;i<3;i++) {
d1[i] = p2[i] - p1[i];
d2[i] = p3[i] - p1[i];
}
n[0] = d1[1]*d2[2] - d1[2]*d2[1];
47
n[1] = -d1[0]*d2[2] + d1[2]*d2[0];
n[2] = d1[0]*d2[1] - d1[1]*d2[0];
}
void parametrico::draw_parametrico() {
float u,v;
float du,dv;
float f[3];
float n[3];
glColor3f(1,0,0);
u = umin;
for(int i = 0; i< pontos; i++) {
v = vmin;
for(int j = 0; j < pontos; j++) {
glBegin(GL_QUADS);
normal(u ,v ,n);
p (u ,v ,f);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u+du,v ,n);
p (u+du,v ,f);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u+du,v+dv,n);
p (u+du,v+dv,f);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u ,v+dv,n);
p (u ,v+dv,f);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
glEnd();
v += dv;
}
u += du;
}
glColor3f(0,1,0);
u = umin;
48
for(int i = 0; i< pontos; i++) {
v = vmin;
for(int j = 0; j < pontos; j++) {
glBegin(GL_LINES);
normal(u ,v ,n);
p (u ,v ,f);
float norma = 5*sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
n[0] = n[0] / norma;
n[1] = n[1] / norma;
n[2] = n[2] / norma;
glVertex3f(f[0],f[1],f[2]);
glVertex3f(f[0]+n[0],f[1]+n[1],f[2]+n[2]);
glEnd();
v += dv;
}
u += du;
}
}
void parametrico::draw_parametrico_textura()
{
glColor3f(1,0,0);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3f(0,0,0);
glTexCoord2f(1.0, 0.0);
glVertex3f(1,0,0);
glTexCoord2f(1.0, 1.0);
glVertex3f(1,1,0);
glTexCoord2f(0.0, 1.0);
glVertex3f(0,1,0);
glEnd();
}
void parametrico::draw_parametrico_textura1() {
float u,v;
float du,dv;
float f[3];
float n[3];
glColor3f(1,0,0);
u = umin;
for(int i = 0; i< pontos; i++) {
v = vmin;
for(int j = 0; j < pontos; j++) {
glBegin(GL_QUADS);
normal(u ,v ,n);
p (u ,v ,f);
// glTexCoord2f(0.0, 0.0);
// glTexCoord2f(u/umax, v/vmax);
glTexCoord2f(u, v);
49
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u+du,v ,n);
p (u+du,v ,f);
// glTexCoord2f(1.0, 0.0);
// glTexCoord2f((u+du)/umax, v/vmax);
glTexCoord2f((u+du), v);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u+du,v+dv,n);
p (u+du,v+dv,f);
// glTexCoord2f(1.0, 1.0);
// glTexCoord2f((u+du)/umax, (v+dv)/vmax);
glTexCoord2f((u+du), (v+dv));
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
normal(u ,v+dv,n);
p (u ,v+dv,f);
// glTexCoord2f(0.0, 1.0);
// glTexCoord2f(u/umax, (v+dv)/vmax);
glTexCoord2f(u, (v+dv));
glNormal3f(n[0],n[1],n[2]);
glVertex3f(f[0],f[1],f[2]);
glEnd();
v += dv;
}
u += du;
}
}
6- Curvas de Bezier
6.1 Introduo
Aproximadamente na dcada de 50, comearam a surgir as primeiras mquinas capazes de
confeccionar formas slidas de madeira ou ao partindo de um modelo. Para que isso fosse possvel, tornou-
se necessrio produzir uma descrio computacional desses modelos compatvel com as formas desejadas. Na
indstria automobilstica por exemplo, o cap de um carro no perfeitamente descrito por uma nica
superfcie paramtrica e nem sempre uma boa aproximao pode ser feita atravs de funes
conhecidas(Superfcies qudricas, cilindros,etc..) sem um grande esforo. Assim surgiu a necessidade de
curvas e superfcies que representassem com alguma facilidade formas livres. Foi na indstria automobilstica
que surgiu o primeiro modelo: As curvas de Bzier.
As curvas de Bzier foram desenvolvidas independentemente por P. de Casteljau na empresa
automobilstica Citren e por P. Bzier na Renault em torno de 1959. Enquanto Bzier usou diretamente os
polinmios de Bernstein, de Casteljau utilizou uma formulao recursiva, sendo que posteriormente provou-
se que as duas formulaes so equivalentes do ponto de vista matemtico. Entretanto os trabalhos de P. de
Casteljau s vieram a ser descobertos por W. Boehm em 1975, razo pela qual hoje o nome Bzier
extremamente difundido na nomenclatura de curvas e superfcies.
A partir da teoria das curvas de Bzier e mais tarde combinadas com os mtodos B-Splines (As
curvas B-Splines podem ser vistas de forma simplificada como generalizao das curvas de Bzier), o design
atravs da computaco grfica tomou grande fora, resultando nos avanados sistemas atuais em CAD/CAM.
A curva de Bzier uma alternativa para o design de formas livres. Apresentaremos em seguida a verso de
de Casteljau para a gerao da curva de Bzier. O algortmo descrito nesta seo considerado o algoritmo
fundamental no campo do design de curvas e superfcies. Sua principal caracterstica a construo
geomtrica associada.
50
Historicamente foi com este algoritmo que de Casteljau iniciou seu trabalho em 1959. Os nicos
registros sobre este assunto feitos por de Casteljau so de difcil acesso, e sua divulgao s foi possvel
quando W.Boehm obteve cpias destes registros em 1975.
Bezier.cpp
#include <gl/glut.h>
#include "bezier.h"
void bezier::draw_bezier()
{
float t;
float x,y;
float dt = 1.0/pontos;
if (n < 1) return;
t = 0;
glColor3f(1,0,0);
glBegin(GL_LINE_STRIP);
for (int i = 0;i <= pontos; i++)
{
x = 0;
y = 0;
for(int j=0; j <= n;j++)
{
x += p[j][0] * bernstein(n,j,t);
y += p[j][1] * bernstein(n,j,t);
}
glVertex3f(x,y,0);
t += dt;
}
glEnd();
}
51
void bezier::draw_casteljau()
{
float t;
float x,y;
float dt = 1.0/pontos;
if (n < 1) return;
t = 0.0;
glColor3f(1,0,0);
glBegin(GL_LINE_STRIP);
for (int i = 0;i <= pontos; i++)
{
x = casteljau(t,n,0,0);
y = casteljau(t,n,0,1);
glVertex3f(x,y,0);
t += dt;
}
glEnd();
void bezier::draw_method_casteljau()
{
float t;
float x1,y1,x2,y2;
int d = 5;
float dt = 1.0/d;
if (n < 1) return;
t = 0;
glColor3f(0,0,1);
glBegin(GL_LINES);
for(int k = 0; k <= d; k++) {
for(int r = 1; r <= n; r++)
{
for (int i = 0;i <= n-r; i++)
{
x1 = casteljau(t,r-1,i,0);
y1 = casteljau(t,r-1,i,1);
x2 = casteljau(t,r-1,i+1,0);
y2 = casteljau(t,r-1,i+1,1);
glVertex3f(x1,y1,0);
glVertex3f(x2,y2,0);
}
}
t += dt;
}
glEnd();
}
void bezier::draw_poligono()
{
glColor3f(1,1,0);
glPointSize(5.0);
glBegin(GL_POINTS);
for(int i =0;i <= n; i++)
glVertex3f(p[i][0],p[i][1],0);
glEnd();
glPointSize(1.0);
if (n < 1)
return;
glColor3f(0.7,0.7,0);
glBegin(GL_LINE_STRIP);
for(int i=0; i<= n;i++)
glVertex3f(p[i][0],p[i][1],0);
glEnd();
}
Bezier.h
class bezier {
float p[20][2];
int n ;
int pontos ;
public:
bezier(int p = 10)
{
n = -1;
pontos = p;
}
void draw_poligono();
void draw_method_casteljau();
};
main.cpp
#include<gl\glut.h>
#include "bezier.h"
#include <iostream>
using namespace std;
bezier C(20);
53
int m = 0;
float phi = 0; //235
float theta = 0; //42
float gama = 0;
int xi,yi,xf,yf;
void inicia()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5,5,-5,5,-5,5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gama,0,0,1);
glRotatef(phi,1,0,0);
glRotatef(theta,0,0,1);
void display()
{
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
C.draw_method_casteljau();
C.draw_poligono();
C.draw_casteljau();
glFlush();
glutSwapBuffers();
}
superficies
class bezier {
float p[20][2];
float S[20][20][3];
int n ;
int m ;
int pontos ;
public:
bezier(int p = 10)
{
n = -1;
m = -1;
pontos = p;
}
bezier(int p = 10,int i = -1,int j = -1)
{
n = i;
m = j;
pontos = p;
}
void draw_poligono();
void draw_poliedro();
void draw_method_casteljau();
};
55
#include <gl/glut.h>
#include "bezier.h"
void bezier::draw_bezier()
{
float t;
float x,y;
float dt = 1.0/pontos;
if (n < 1) return;
t = 0;
glColor3f(1,0,0);
glBegin(GL_LINE_STRIP);
for (int i = 0;i <= pontos; i++)
{
x = 0;
y = 0;
for(int j=0; j <= n;j++)
{
x += p[j][0] * bernstein(n,j,t);
y += p[j][1] * bernstein(n,j,t);
}
glVertex3f(x,y,0);
t += dt;
}
glEnd();
}
56
void bezier::draw_sup_bezier()
{
float u,v;
float x,y,z;
float du = 1.0/pontos;
float dv = 1.0/pontos;
if (n < 1) return;
glColor3f(1,0,0);
u = 0;
for (int a = 0; a <= pontos; a++)
{
v = 0;
glBegin(GL_LINE_STRIP);
for (int b = 0; b <= pontos; b++)
{
x = 0;
y = 0;
z = 0;
for(int i=0; i <= n; i++) {
for(int j=0; j <= m; j++)
{
float bu = bernstein(n,i,u);
float bv = bernstein(m,j,v);
x += S[i][j][0] * bu * bv;
y += S[i][j][1] * bu * bv;
z += S[i][j][2] * bu * bv;
}
}
glVertex3f(x,y,z);
v += dv;
}
glEnd();
u += du;
}
v = 0;
for (int a = 0; a <= pontos; a++)
{
u = 0;
glBegin(GL_LINE_STRIP);
for (int b = 0; b <= pontos; b++)
{
x = 0;
y = 0;
z = 0;
for(int i=0; i <= n; i++) {
for(int j=0; j <= m; j++)
{
float bu = bernstein(n,i,u);
float bv = bernstein(m,j,v);
x += S[i][j][0] * bu * bv;
y += S[i][j][1] * bu * bv;
z += S[i][j][2] * bu * bv;
}
}
glVertex3f(x,y,z);
57
u += du;
}
glEnd();
v += dv;
}
}
void bezier::draw_casteljau()
{
float t;
float x,y;
float dt = 1.0/pontos;
if (n < 1) return;
t = 0.0;
glColor3f(1,0,0);
glBegin(GL_LINE_STRIP);
for (int i = 0;i <= pontos; i++)
{
x = casteljau(t,n,0,0);
y = casteljau(t,n,0,1);
glVertex3f(x,y,0);
t += dt;
}
glEnd();
void bezier::draw_method_casteljau()
{
float t;
float x1,y1,x2,y2;
int d = 5;
float dt = 1.0/d;
if (n < 1) return;
t = 0;
glColor3f(0,0,1);
glBegin(GL_LINES);
for(int k = 0; k <= d; k++) {
for(int r = 1; r <= n; r++)
{
for (int i = 0;i <= n-r; i++)
{
x1 = casteljau(t,r-1,i,0);
y1 = casteljau(t,r-1,i,1);
x2 = casteljau(t,r-1,i+1,0);
y2 = casteljau(t,r-1,i+1,1);
glVertex3f(x1,y1,0);
glVertex3f(x2,y2,0);
}
}
t += dt;
}
glEnd();
}
58
float bezier::casteljau(float t,int r,int i,int j)
{
if (r == 0)
return( p[i][j] );
else
return((1-t) * casteljau(t,r-1,i ,j) + t * casteljau(t,r-
1,i+1,j));
}
void bezier::draw_poligono()
{
glColor3f(1,1,0);
glPointSize(5.0);
glBegin(GL_POINTS);
for(int i =0;i <= n; i++)
glVertex3f(p[i][0],p[i][1],0);
glEnd();
glPointSize(1.0);
if (n < 1)
return;
glColor3f(0.7,0.7,0);
glBegin(GL_LINE_STRIP);
for(int i=0; i<= n;i++)
glVertex3f(p[i][0],p[i][1],0);
glEnd();
}
void bezier::draw_poliedro()
{
glColor3f(1,1,0);
glPointSize(5.0);
glBegin(GL_POINTS);
for(int i =0;i <= n; i++)
for(int j =0;j <= m; j++)
glVertex3f(S[i][j][0],S[i][j][1],S[i][j][2]);
glEnd();
glPointSize(1.0);
if (n < 1)
return;
glColor3f(0.7,0.7,0);
for(int i =0;i <= n; i++) {
glBegin(GL_LINE_STRIP);
for(int j =0;j <= m; j++) {
glVertex3f(S[i][j][0],S[i][j][1],S[i][j][2]);
}
glEnd();
}
for(int j =0;j <= m; j++) {
glBegin(GL_LINE_STRIP);
for(int i =0;i <= n; i++) {
glVertex3f(S[i][j][0],S[i][j][1],S[i][j][2]);
}
glEnd();
}
}
59
#include<gl\glut.h>
#include "bezier.h"
#include <iostream>
using namespace std;
bezier S(20,3,2);
int m = 0;
float phi = 0; //235
float theta = 0; //42
float gama = 0;
int xi,yi,xf,yf;
void inicia()
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5,5,-5,5,-5,5);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(gama,0,0,1);
glRotatef(phi,1,0,0);
glRotatef(theta,0,0,1);
void display()
{
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1,0,0);
// C.draw_method_casteljau();
// C.draw_poligono();
// C.draw_casteljau();
S.draw_poliedro();
S.draw_sup_bezier();
glFlush();
glutSwapBuffers();
}
S.insert(1,1,0,0,1);
S.insert(2,1,2,1,1);
S.insert(3,1,0,2,1);
S.insert(4,1,1,3,1);
S.insert(1,2,1,0,2);
S.insert(2,3,3,1,2);
S.insert(3,2,2,2,2);
S.insert(4,2,1,3,2);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutCreateWindow("Bezier");
glutDisplayFunc(display);
inicia();
glutMouseFunc(botao);
glutMotionFunc(botao_movimento);
glutMainLoop();
}
61