Sunteți pe pagina 1din 266

1

Elementos Matemticos para Computao Grfica


Professor: Sinsio Pesco

Referncias:

1 Fundamentos de Matemtica para Computao Grfica


Autor: Sinsio Pesco
Hlio Lopes
Geovan Tavares
Apostila que ser disponibilizada no xerox da Taisho.
2 - C A linguagem de programao
Autor: Brian W. Kernighan
Dennis M. Ritchie
Editora: Campus LTDA.
3 The OpenGL Utility Toolkit (GLUT) Programming Interface
Autor: Mark J. Kilgard
Silicon Graphics, Inc.
Novembro 13, 1996.
4 Open GL Programming for the X Window System
Autor: Mark J. Kilgard
Editora: Addison-Wesley Developers Press.
5 Teach Yourself Visual C++ 4 in 21 days
Autor: Ori Gurewich and Nathan Gurewich
Editora: SAMS Publishing.
6 Mathematical Elements for Computer Graphics
Autor: David Rogers
J. Alan Adams
Editora: MacGraw-Hill1.

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");
}

Os programas em C sempre iniciam pelo main() . De forma geral os programas em C consistem de


funes (o termo funo ser explicado depois), e o main() consiste de uma funo. Seguindo o nome
da funo seguem as chaves {} que delimitam o incio e o fim da funo.
Neste exemplo o printf() o nico comando da funo main(). Este comando 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 ( ; ).
Os caracteres em branco so invisveis para o compilador. Assim o programa acima tambm poderia ser:

#include <stdio.h>

main(){ printf("Programa Inicial"); }

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);
}

A primeira linha do main() declara a varivel e o tipo:


Int num;
Tipo da varivel Nome da varivel

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;

Existem sete tipos principais de variveis:

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)

1.3 - A funo printf()


O printf() de fato uma funo assim como o main(). Os parnteses contm a sentena a ser
apresentada na tela. Esta sentena deve ser limitada por aspas ( ), e o contedo de variveis tambm podem
ser exibidas pelo printf conforme o exemplo abaixo:

#include <stdio.h>

main()
{
int a = 1;
char tipo = c;
float valor = 22.53;

printf("inteiro= %d char= %c float= %f \n",a,tipo,valor);


}

O resultado da execuo deste programa ser:

Inteiro= 1 char= c float= 22.530001

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
}

1.4 - A funo scanf()


Esta funo responsvel pela entrada de dados via teclado. Existem vrias funes de entrada e sada em C,
porm o printf e o scanf so as mais comuns. Examine o exemplo abaixo:

#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;

printf("i= %3d j= %3d \n",i,j);


printf("x= %.3f y= %.3f \n",x,y);
printf("a= %g b= %g \n",a,b);
}

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:

scanf( "%f" ,&x);


Tipo da varivel Endereo da varivel (voc deve colocar um & na frente da varivel

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;

freqentemente representado por:

i++;

Da mesma forma i = i-1; pode ser escrito como 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 */

Observe o exemplo abaixo:

/* * * * * * * * * * * * * * * * * * * * * * * * */
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);

/* Calculo das raizes */


x1=(-b+sqrt(b*b-4*a*c))/(2*a);
x2=(-b-sqrt(b*b-4*a*c))/(2*a);
/* Impressao dos dados finais */

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( ; ;) { }

2.1 - Comando for( ; ; ) {}


O for um comando apropriado quando queremos executar um conjunto de operaes um nmero fixo de
vezes. O exemplo abaixo imprime os nmeros de 0 at 9:

#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

O comando for composto de trs argumentos:


for( n=0 ; n<10 ; n++ )
Expresso de Expresso de Incremento
inicializao teste

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:

< Menor && e


> Maior ! negao
<= Menor ou igual || ou
>= Maior ou igual
== Igual
!= Diferente

Expresso de incremento
A cada repetio do lao, o terceiro argumento (n++) incrementa a varivel n.

2.2 - Exemplo: Mtodos numricos de integrao (ponto a esquerda)


Como aplicao do comando for o exemplo abaixo ilustra a implementao do mtodo do ponto a esquerda
para avaliar numericamente :
1

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.

2.4 - Exemplo: Mtodo de Newton


O programa abaixo determina as razes da funo:
y = x2 2 utilizando o mtodo de Newton, ou seja,
dada uma condio inicial x0, e um erro mximo E, a seqncia abaixo pode convergir para uma das razes:
f (xn )
xn +1 = xn
f ' ( xn )

/* * * * * * * * * * */
/* Metodo de Newton */

#include <stdio.h>
#include <math.h>

main()
{
int i ;
double xn, x0,xn_1;
double erro ;

printf(" Entre com a condicao inicial: ");


scanf("%lf",&x0);
printf("\n Erro maximo: ");
scanf("%lf",&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);
}

2.5 - Comando while() {};


Este ltimo tipo de lao muito semelhante ao anterior. Partindo do exemplo abaixo vamos observar a nica
diferena para o lao da seo anterior:
12
#include <stdio.h>
main()
{
int n;
n = 0;
while (n < 10){
printf("n = %d\n",n);
n++;
}
}

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.

2.6 - Comando break e continue


Para auxiliar nos laos contamos com dois comandos de interrupo do lao, cada um com objetivos
diferentes.
O comando break; interrompe o lao (Qualquer dos trs formatos apresentados) e o programa continua no
primeiro comando aps o lao. Exemplo:

#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);
}

O resultado deste programa ser:

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);

printf("\nEntre com o erro = ");


scanf("%f",&erro);

fa = a*a - 2;
fb = b*b - 2;

if ((fa * fb) > 0) {


printf("\nCondicao inicial nao contem raiz !\n");
exit(0);
}

while(fabs(a-b) > erro) {


c = (a+b)/2.0;
fc = c*c - 2.0;

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("Entre com os extremos do intervalo [a, b]: ");


scanf("%f,%f",&a,&b);

printf("\nErro: ");
scanf("%f",&erro);

fa = f(a);
fb = f(b);

if ((fa * fb) > 0) {


printf("Condicao inicial nao contem raiz !\n");
exit(0);
}
while(fabs(a-b) > erro) {
i++;
c = (a+b)/2.0;
fc = f(c) ;

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);
}

Vamos examinar alguns detalhes da funo introduzida:

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.

4.2 - Exemplo: Mtodos de Integrao Numrica (Ponto a esquerda, Trapzio e


Simpson)
Para ilustrar o conceito de funes, o exemplo seguinte calcula a integral numrica de uma funo definida na
funo float f(float x) .

/* * * * * * * * * * * * * * * * * * */
/* 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);
}

float Integra_Ponto_a_esquerda(float a,float b,int n)


{
int i ;
float soma ;
float dx ;
soma = 0.0;
dx = (b-a)/n;
for(i=1; i<= n; i++) {
soma = soma + f(a + (i-1)*dx) * dx;
printf("\nSoma parcial = %f ",soma);
}
return(soma);
}
float Integral_Trapezio(float a,float b,int n)
{
int i ;
float soma ;
float dx ;

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);
}

float Integral_Simpson(float a,float b,int n)


{
int i ;
float soma ;
float dx ;

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];

o programa completo seria:

#include <stdio.h>

main()
{
int i ;
float media ;
float soma ;
float notas[15];

for(i=0;i < 15;i++) {


printf("\n Aluno %2d ",i+1);
scanf("%f",&notas[i]);
}

for(i=0;i<15;i++)
soma = soma + notas[i];
media = soma / 15;

printf("\n A media final foi: %f",media);


}

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:

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 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]

5.3 - Inicializando vetores

19
Assim como possvel inicializar uma varivel simples na mesma linha da declarao, o mesmo pode ser
feito para vetores. Observe o exemplo abaixo:

int n[5] = {23, 3, -7, 288, 14};

5.4 Exemplo: Mtodo de Ordenao


Como exemplo vamos apresentar um programa que ordena um seqncia de 10 nmeros reais.

/* * * * * * * * * * * * * * * * * * * * * */
/* 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 */

printf("Entre com os numeros para ordenacao \n");


for(i=0;i<MAX;i++)
{
printf("\n numero %2d: ",i);
scanf("%f",&(n[i]));
}

/* Ordena a sequencia de numeros */

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 */

printf("\nSequencia ordenada : ");


for(i=0; i<MAX; i++)
printf("\n %10.5f ",n[i]);
printf("\n");
}

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];

Assim fica reservado um espao de memria conforme a figura abaixo:

A[0][0] A[0][1] A[0][2] A[0][3]

A[1][0] A[1][1] A[1][2] A[1][3]

A[2][0] A[2][1] A[2][2] A[2][3]

5.6 Exemplo: Produto de uma matriz por um vetor


Vamos montar um programa que multiplica um vetor por uma matriz.

/* * * * * * * * * * * * * * * * * * * * * * */
/* 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.

6.3 Principais Aplicaes de Ponteiros


Algumas situaes em que os ponteiros so teis:
1. Quando em uma funo desejamos retornar mais de um valor.
2. Para passar vetores e matrizes de forma mais conveniente como argumentos de funes.
3. Para manipular vetores e matrizes de forma mais eficiente.
4. Para manipular estruturas de dados mais complexas, tais como listas e rvores.
5. Na utilizao das funes calloc() e malloc() responsveis pela alocao de memria dinmica.

6.4 Armazenando o Endereos das Variveis


Para armazenar o endereo de uma varivel (por exemplo &i) em outra varivel, necessrio criar um tipo
especial de varivel denominada apontador. Exemplo:

#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

6.5 Acessando o contedo de um endereo

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;

6.6 Ponteiros e Argumentos de Funes


Como sabemos, uma funo no consegue alterar diretamente uma varivel utilizada como argumento. Com o
auxlio dos ponteiros podemos encontrar uma alternativa para esta situao. No exemplo do programa de
ordenao, foi preciso permutar dois elementos do vetor que estavam fora de ordem. No seria possivel
permutar dois valores atravs de uma funo como abaixo:

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);

O resultado deste programa seria:

x = 1.2 e y = 56.89

Utilizando ponteiros existe uma maneira de obter o efeito desejado:

/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Este programa permutar os valores das variaveis */

#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);


}

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.

6.7 Ponteiros com Vetores

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;
}

void ordena(float *px)


{
int i ;
int flag;
/* Ordena a sequencia de numeros */

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 */

printf("Entre com os numeros para ordenacao \n");


for(i=0;i<MAX;i++)
{
printf("\n numero %2d: ",i);
scanf("%f",&(n[i]));
}
ordena(n);

/* Imprime a sequencia de numeros ordenada */


printf("\nSequencia ordenada : ");
for(i=0; i<MAX; i++)
printf("\n %10.5f ",n[i]);
printf("\n");
}

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.

6.8 Alocao de Vetores Dinamicamente


Uma das restries do nosso programa de ordenao que o usurio no pode definir a princpio quantos
elementos ele pretende ordenar. Isto ocorre porque precisamos informar na declarao do vetor qual ser a sua
dimenso. Vamos retirar essa restrio. Para isso utilizaremos um novo comando: malloc(). Vamos
utilizar um exemplo:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void main()
{
int i;
int n;
float *v;

printf("Entre com a dimensao do vetor desejada = ");


scanf("%d",&n);

v = (float *) malloc(n * sizeof(float));


for(i=0;i<n;i++)
scanf("%f",&(v[i]));

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;

2. O comando malloc(n * sizeof(float)) reserva n espaos de memria, cada um do tamanho de


um float.

3. A funo malloc retorna o endereo do primeiro elemento do vetor: (float *) malloc()

4. A funo free, libera o espao de memria reservado para o vetor.

6.9 Alocao de Matrizes Dinamicamente


Para alocar matrizes observe o exemplo:

#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);
}

void matfree(float **A,int n,int m)


{
int i;
for(i=0;i<n;i++)
free(A[i]);
free(A);
}
void main()
{
int i;
int j;
int n;
int m;
float **A;

printf("Entre com a dimenso da matriz desejada = ");


scanf("%d, %d",&n,&m);
A = matalloc(n,m);

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);
}

6.10 Exemplo: Mtodo LU para resoluo de Sistemas Lineares


Um dos mtodos clssicos para se resolver um sistema linear da forma Ax=b, a decomposio LU. De
forma reduzida temos trs etapas:
1. Decompor A = LU
2. Resolver Lc = b
3. Resolver Ux = c

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

E para a ultima linha obtemos:

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.

A primeira operao elementar foi :

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

Voltando ao nosso exemplo, temos mais duas matrizes elementares:

1 0 0

L3 L3 + L1 0

1 0
1 0 1

1 0 0

L3 L3 + L2 0

1 0
0 1 1

Podemos ento representar as operaes elementares sobre a matriz A por:

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

141441 41440241 440 404431 1424274432 1044024413


0

L1


A

U

Se multiplicarmos pela inversa das matrizes elementares obtemos:


2 1 1 1 0 0 1 0 0 1 0 0 2 1 1


4 6 0 =

2 1 0 0 1 0 0 1 0 0 8 2 30
2
7 2 0 0 1 1 0 1 0 1 1 0 0 1
Multiplicando as matrizes elementares obtemos a decomposio LU:

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

Uma vez obtida a matriz L, resolvemos 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

Resolvemos agora o sistema Ux = b

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.

0,1 1,1 2,1

0,0 1,0 2,0

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:

8 bits 256 cores


(High Color) 16 bits 65.536 cores
(True Color) 24 bits 16.777.216 cores
(True Color) 32 bits 4.294.967.296 cores

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.

1.4 Exemplo: Plotar um ponto na tela utilizando as bibliotecas do OpenGl

#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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400); /* Antes do glutCreateWIndow */
glutInitWindowPosition(1,1);
glutCreateWindow("Ponto");
gluOrtho2D(0,399,399,0); /* Apos CreateWindow */
glutDisplayFunc(redesenha); /* Esta funcao e necessaria, caso
contrario o opengl nao consegue
criar a janela */
glutMainLoop();
}

Vamos comentar comando a comando:

glutInit(&argc,argv);
utilizado para iniciar a biblioteca GLUT.

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);


Quando uma janela criada, seu tipo determinado pelo Display Mode. O tipo da janela inclui um
conjunto de caractersticas desejadas. Neste caso temos trs:

GLUT_SINGLE: Buffer simples


GLUT_RGBA...: Utilizaremos o modo RGBA.
GLUT_DEPTH.: Buffer de profundidade (utilizado em remoo de superfcies escondidas).

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.

Quando a funo redesenha chamada temos o seguinte resultado:

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 );

2) Acrescente um contador para verificar quantas vezes a funo redesenha chamada.

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

1.5.1 Algoritmo ingnuo

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();
}

void main(int argc, char **argv)


{

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();
}

Algumas desvantagens do programa proposto:

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.

1.5.2 Algoritmo de Bresenham

Partindo da informao do pixel inicial (Ax,Ay) e do pixel final (Bx,By), o algoritmo de


Bresenham, para a reta, determina quais pixels devem ser acessos de (Ax,Ay) at (Bx,By) utilizando
para isso unicamente aritmtica inteira.
A idia fundamental do algoritmo que se restringirmos a reta para inclinaes entre 0 e 1 (de 0 a
45 graus), ento para cada pixel existem somente duas possibilidades como indica a figura abaixo:

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:

1) 0 m 1 com Ax < Bx.


2) 1 < m < com Ay < By.
3) 1 > m > com Ay < By.
4) 0 m 1 com Ax > Bx.
5) 0 m 1 com Ax > Bx.
6) 1 < m < com Ay > By.
7) 1 > m > com Ay > By.
8) 0 m 1 com Ax < Bx.

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.

Calculando P1 para o pixel inicial (Ax,Ay) obtemos:


P1 = 2 dY (Ax + 1) + 2 b dX 2 Ay dX dX
Para obter b, observe que de y = mx + b obtemos b = y mx, e no ponto (Ax,Ay) temos que
b=Ay-mAx = Ay dY/dX Ax. Substituindo em P1 obtemos:
P1 = 2 dY (Ax + 1) + 2 (Ay dY/dX Ax) dX 2 Ay dX dX
= 2 dY Ax + 2 dY + 2 Ay dX 2 dY Ax -2 Ay dX dX
= 2 dY dX

Concluso: como resultado final, o algoritmo se resume a:


o dX = Bx Ax

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.

O programa considerando as oito possibilidades dado abaixo:

#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).
//===================================================================

// EXTERNALLY DEFINED FRAMEBUFFER AND FRAMEBUFFER DIMENSIONS (WIDTH))


// extern int WIDTH;

//====================================================================
=
// 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)
//====================================================================

void BresLine(int Ax, int Ay, int Bx, int By)


{

//--------------------------------------------------------------
-
// 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

for (; dX>=0; dX--) // process each point in the line


// one at a time (just use dX)
{
glBegin(GL_POINTS);
glVertex2d(Ax, Ay); // plot the pixel
glEnd();
if (P > 0) // is the pixel going right AND up?
{
Ax+=Xincr; // increment independent variable
Ay+=Yincr; // increment dependent variable
P+=dPru; // increment decision (for up)
}
else // is the pixel just going right?
{
Ax+=Xincr; // increment independent variable
P+=dPr; // increment decision (for right)
}
}
}
else // if Y is the independent variable
{
int dPr = dX<<1; // amount to increment decision if
// right is chosen (always)
int dPru = dPr - (dY<<1); // amount to increment
// decision if up is chosen
int P = dPr - dY; // decision variable start value

for (; dY>=0; dY--) // process each point in the line


// one at a time (just use dY)
{
glBegin(GL_POINTS);
glVertex2d(Ax, Ay); // plot the pixel
glEnd();

if (P > 0) // is the pixel going up AND right?


{
Ax+=Xincr; // increment dependent variable
Ay+=Yincr; // increment independent variable
P+=dPru; // increment decision (for up)
}
else // is the pixel just going up?
{
Ay+=Yincr; // increment independent variable
P+=dPr; // increment decision (for right)
}
}
}
}

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();

void main(int argc, char **argv)


{

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();
}

1.5.3 Retas no Opengl

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();
}

1.6 Exemplo: Plotar o grfico de uma funo


Vamos comear com uma verso bem simplificada, para plotar o grfico de uma funo y=f(x).

#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();
}

void main(int argc, char **argv)


{

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();
}

Vamos melhorar este programa:

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(redesenha);
gluOrtho2D(-5,5,-5,5);
glutMainLoop();
}

12
/* * * * * * * * * * * * * */
/* Modulo: funcao02.cpp */
/* * * * * * * * * * * * * */

#include <stdio.h>
#include <math.h>
#include <gl\glut.h>

#define PI 3.1415926535897932384626433832795

float xmin = -5.0;


float xmax = 5.0;
float ymin = -5.0;
float ymax = 5.0;
int pontos = 400;

/* -------------------------------- */
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 */

float funcao(float x);

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:

void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))

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.

2.3 Exemplo: Utilizao do teclado no programa funes.


Como exemplo vamos acrescentar no programa funes a possibilidade de alterarmos o domnio da
funo durante a execuo do programa. Assim podemos estabelecer que quando o usurio pressionar a
tecla D ou d, o programa interrompe e solicita na janela DOS as novas informaes sobre o domnio
da funo.
Vamos reorganizar o programa, modularizando as principais rotinas do programa em arquivos diferentes.
Nosso programa ter dois mdulos principais:
- funcao010.cpp: Mantm as rotinas de visualizao do OpenGL
- funcao011.cpp: Mantm as rotinas relativas ao desenho da funo.
Teremos ainda o mdulo:
- funcao011.h: Este mdulo deve ter apenas o cabealho das funes do programa
funcao011.cpp.
A seguir apresentamos o cdigo de cada um destes mdulos.

2.3.1 - Mdulo funcao011.h

/* * * * * * * * * * * * * * */
/* Modulo: funcao011.h */
/* * * * * * * * * * * * * * */

float funcao(float x);

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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
glutMainLoop();
}

2.3.3 - Mdulo funcao011.cpp

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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}

void le_botao_mouse(int b,int state,int x, int y)


{

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;
}
}

void main(int argc, char **argv)


{
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();
}

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();
}

void le_botao_movimento_mouse(int x, int y)


{
printf("Botao+movimento x = %d y = %d \n",x,y);
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Mouse");
glutDisplayFunc(display);
glutMotionFunc(le_botao_movimento_mouse);
glutMainLoop();
}

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();
}

void le_movimento_mouse(int x, int y)


{
printf("Movimento x = %d y = %d \n",x,y);
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Mouse");
glutDisplayFunc(display);
glutPassiveMotionFunc(le_movimento_mouse);
glutMainLoop();
}
3 CURVAS PARAMTRICAS
3.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)

Estas so as equaes paramtricas da curva C e t denominado parmetro. Como exemplo de curvas


temos:

a) Circunferncia de centro na origem e raio 1:

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.

3.2.1 Mdulo curvas010.cpp


Este mdulo idntico ao mdulo funcao010.cpp. A nica diferena que as chamadas so feitas para as
novas funes de desenho das curvas.

/* * * * * * * * * * * * * */
/* 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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}

void le_botao_mouse(int b,int state,int x, int y)


{

switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
entra_dominio();
display();
break;
case GLUT_UP:
break;
}
break;
}
}

void main(int argc, char **argv)


{

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();
}

3.2.2 Mdulo curvas011.cpp


Neste mdulo implementamos o desenho do grfico das curvas paramtricas. As funes plota_eixo
e entra_domnio no sofrem alteraes.

/* * * * * * * * * * * * * */
/* 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;
}

3.2.3 Mdulo curvas011.h


Float curva(float t,float *x,float *y);

Void plota_eixo();

Void plota_curva();

Void entra_dominio();

3.2.4 Exerccio

Como exerccio implemente:

1) Curva ciclide (t assume qualquer valor real).


2) x(t) = 3*t*t, y(t)=4*t*t*t (t assume qualquer valor real).
3) x(t) = cos(2*t), y(t)= sin(2*t) (0 <= t <= 2*PI) (Qual a diferena para a
curva do programa ?)
4) x(t) = cos(t), y(t)= sin(2*t)
5) x(t) = 2 * cos(t), y(t)= 3 * sin(t) (0 <= t <= 2*PI) .
6) 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).

3.3 Curvas na forma Polar


Para formar as coordenadas polares considere um ponto fixo O, denominado origem (ou polo) e um eixo
partindo de O, denominado eixo polar. A cada ponto P do plano podemos associar uma par de
coordenadas polares (r,theta) onde:

r: distncia orientada da origem ao ponto P.


theta: ngulo entre o eixo polar e o segmento OP.
.

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:

a) Circunferncia de centro na origem e raio 1:

r = 1

b) Reta passando na origem com coeficiente angular m:

=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 )

3.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:

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();

GL_POINTS Pontos individuais.


GL_LINES Reta entre dois pontos.
GL_POLYGON Polgono convexo .
GL_TRIANGLES Tripla de vrtices interpretado como um tringulo.
GL_QUADS Conjunto de quatro vrtices interpretado como
quadriltero.
GL_LINE_STRIP Sequncia de retas.
GL_LINE_LOOP Idntico ao anterior, porm com uma reta unindo o
primeiro e ltimo vrtice.
GL_TRIANGLE_STRIP Lista de tringulos.
GL_TRAINGLE_FAN Lista de tringulos com o primeiro vrtice em
comum.
GL_QUAD_STRIP Lista de quadrilteros.

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.

4.2.1 - Mdulo Intvis01.c

/* * * * * * * * * * * * * * */
/* Modulo: Intvis01.c */
/* * * * * * * * * * * * * * */

#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "Intvis02.h"
#include "Intvis03.h"

extern int tipo,visual;

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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
case 'I':
case 'i':
entra_limites();
display();

27
break;
case '0':
tipo = 0;
display();
break;
case '1':
tipo = 1;
display();
break;
}
}

void le_botao_mouse(int b,int state,int x, int y)


{

switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
visual = (visual + 1) % 2;
display();
break;
case GLUT_UP:

break;
}
break;
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
gluOrtho2D(-10.0,10.0,-10.0,10.0);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}

28
4.2.2 - Mdulo Intvis02.cpp

/* * * * * * * * * * * * * * */
/* Modulo: Intvis02.cpp */
/* * * * * * * * * * * * * * */

#include <stdio.h>
#include <math.h>
#include <gl\glut.h>

float xmin = -10.0;


float ymin = -10.0;
float xmax = 10.0;
float ymax = 10.0;
float incremento = 0.01;

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 */

int xv1,xv2,yv1,yv2; /* Domnio da nova janela */

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();
}

void le_botao_movimento_mouse(int x,int y)


{
xv2 = x;
yv2 = y;
redesenha();
}

void le_botao_mouse(int b,int state,int x,int y)


{
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xv1 = x;
yv1 = y;
mov = 1;
break;
case GLUT_UP:
mov = 0;
xv2 = x;
yv2 = y;
recalcula_dominio(xv1,yv1,xv2,yv2);
redesenha();
break;
}
break;
}
}
void le_tecla(unsigned char key, int x, int y)

32
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
redesenha();
break;
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(redesenha);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMotionFunc(le_botao_movimento_mouse);
glutMainLoop();
}

/* * * * * * * * * * * * * * * * */
/* Modulo: plota.cpp (com zoom) */
/* * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#include "funcao.h"

#define PI 3.1415926535897932384626433832795

float xmin = -1.0;


float ymin = -1.0;
float xmax = 1.0;
float ymax = 1.0;
int pontos = 400;

/* -------------------------------- */
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.

5.2 Visualizao de Curvas Implcitas


Vamos implementar um programa que visualize curvas implcitas. Partindo por exemplo da equao:
x2 y2
x2 + y2 + sen( xy ) = 0
x2 + y2
Observe que no simples exibir um conjunto de pontos que pertenam a esta curva. Vamos definir uma
funo de duas variveis z = f ( x, y ) utilizando a equao acima, da seguinte forma:
f : 2
x2 y2
f ( x, y ) = x 2 + y 2 + sen( xy )
x2 + y2

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.

- A cada trs pontos, definimos um tringulo como na figura abaixo.

- Para cada ponto Pij ( xij , y ij ) calculamos z ij = f ( xij , y ij ) .

- 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.

- Se V1 * V3 < 0, ento a funo se anula em um ponto entre V1 e V3.

- Se V2 * V3 < 0, ento a funo se anula em um ponto entre V2 e V3.

- Se V1 = 0, ento a funo se anula exatamente sobre o vrtice V1.

- Se V2 = 0, ento a funo se anula exatamente sobre o vrtice V2.

- Se V3 = 0, ento a funo se anula exatamente sobre o vrtice V3.

- Considerando que exatamente duas das condies acima se verificaram simultaneamente,


aproximamos a curva nesse tringulo por um segmento de reta unindo os dois pontos obtidos.

5.3 Programa Curva Implcita


O programa est dividido em dois mdulos principais:
- impl010.cpp: Mantm as rotinas de visualizao do OpenGL
- impl011.cpp: Mantm as rotinas relativas ao desenho da curva.
Temos ainda o mdulo:
- impl011.h: Este mdulo deve ter apenas a declarao das funes do programa impl011.cpp.

5.3.1 Mdulo impl010.cpp


Este mdulo idntico ao mdulo funcao010.cpp. A nica diferena que as chamadas so feitas para as
novas funes de desenho das curvas.

/* * * * * * * * * * * * * */
/* 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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}
void le_botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:

break;
case GLUT_UP:
printf(" x = %d y = %d \n",x,y);
break;
}
break;
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
gluOrtho2D(xmin,xmax,ymin,ymax);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}

5.3.2 Mdulo impl011.cpp


Neste mdulo implementamos o desenho do grfico das curvas implcitas. As funes plota_eixo e
entra_domnio no sofrem alteraes.

/* * * * * * * * * * * * * */
/* Modulo: impl011.cpp */
/* * * * * * * * * * * * * */

#include <stdio.h>
#include <math.h>
#include <gl\glut.h>

float xmin = -2.0;


float ymin = -2.0;
float xmax = 2.0;

37
float ymax = 2.0;
float incremento = 0.1;

float funcao(float x,float y)


{
return(sqrt(x*x+y*y)-((x*x-y*y)/(x*x+y*y))+sin(x*y));
}

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 * s2) < 0) {


t = -s1/(s2-s1);
x[i] = x1 + t * (x2-x1);
y[i] = y1;
i++;
}
if ((s1 * s3) < 0) {
t = -s1/(s3-s1);
x[i] = x1 ;
y[i] = y1 + t * (y3-y1);
i++;
}
if ((s2 * s3) < 0) {
t = -s2/(s3-s2);
x[i] = x2 + t * (x3-x2);
y[i] = y2 + t * (y3-y2);
i++;
}

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.3.3 Mdulo impl011.h


void plota_eixo();
void plota_curva_implicita();
void entra_dominio();

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

Definio: Um subconjunto fechado e limitado S 2 , dito ser auto-semelhante se pode ser


expresso na forma:
S = S1 S 2 S 3 L S k
onde S1 , S 2 , S 3 ,K , S k so conjuntos no sobrepostos e cada um deles congruente a S por mesmo
fator de escala s ( 0 < s < 1 ).

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.

Assim, considerando os exemplos anteriores teremos:


ln(4)
Exemplo 1: d H (S ) = =2
ln(2)
ln(3)
Exemplo 2: d H ( S ) = = 1.585K
ln(2)

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:

Definio: Um fractal um subconjunto do espao euclidiano cuja dimenso Hausdorff diferente da


dimenso topolgica.

6.3 Exemplos de fractais


Alguns dos principais exemplos que apresentaremos nesta seo foram gerados utilizando composio de
transformaes de rotao e escala seguido de uma possvel translao. O formato geral da funo dado
por:

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:

Assim temos trs funes, uma associada a cada tringulo:


x 0.5 0 x
T1 =
y 0 0.5 y
x 0.5 0 x 0.5
T2 = +
y 0 0.5 y 0
x 0.5 0 x 0
T3 = +
y 0 0.5 y 0.5

O programa est dividido em dois mdulos principais:


- frac010.cpp: Mantm as rotinas de visualizao do OpenGL
- frac011.cpp: Mantm as rotinas relativas a implementao do tringulo de Sierpinski.
Temos ainda o mdulo:
- frac011.h: Este mdulo deve ter apenas a declarao das funes do programa frac011.cpp.

6.3.1.1- Mdulo frac010.cpp

#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "fract011.h"

extern float xmax,xmin,ymax,ymin;


extern float incremento;

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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'I':
case 'i':
entra_dominio();
break;
}
}

void botao_mouse(int b,int state,int x, int y)


{
float t;
float xmin1,xmax1,ymin1,ymax1;

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();
}

6.3.1.2- Mdulo frac011.cpp

#include <stdio.h>
#include <math.h>
#include <gl\glut.h>

float xmin = -2;


float ymin = -2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;

int pontos = 1000;

void funcao(float *x,float *y,float e,float f)


{
*x = *x/2 + e;
*y = *y/2 + f;
}

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 funcao(float *x,float *y,float e,float f);

void plota_eixo();
void plota_funcao(float x0,float y0,float x1,float y1,
float x2,float y2,int n);
void entra_dominio();

6.3.2- Tringulo de Sierpinski utilizando Monte Carlo

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

O programa proposto est dividido em dois mdulos principais:


- frac020.cpp: Mantm as rotinas de visualizao do OpenGL
- frac021.cpp: Mantm as rotinas relativas a implementao do tringulo de Sierpinski.
Temos ainda o mdulo:
- frac021.h: Este mdulo deve ter apenas a declarao das funes do programa frac021.cpp.

6.3.2.1- Mdulo frac020.cpp

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
}

6.3.2.2- Mdulo frac021.cpp

/* * * * * * * * * * * * * * * * * **/
/* Triangulo Sierpinski Monte Carlo */
/* fract021.cpp */

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>

float xmin = -2;


float ymin = -2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;

int pontos = 1000;

void funcao(float *x,float *y,float e,float f)


{
*x = *x/2 + e;
*y = *y/2 + f;
}

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 x0,float y0)


{
int i,j;
float x[3][4],y[3][4];
float e[3] = {0.0, 0.5, 0.0};
float f[3] = {0.0, 0.0, 0.5};

srand( (unsigned)time( NULL ) );

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;
}

6.3.3- Fern utilizando Monte Carlo

6.3.3.1- Mdulo frac030.cpp

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();
}

6.3.3.2- Mdulo frac031.cpp

/* * * * * * * * * * * */
/* 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;

float incremento = 0.01;

int pontos = 1000;


void T(float a11,float a12,float a21,float a22,float e,float f,float
*x1,float *y1)
{
float xx;
float yy;

48
xx = a11 * *x1 + a12 * *y1 + e;
yy = a21 * *x1 + a22 * *y1 + f;
*x1 = xx;
*y1 = yy;
}

void plota_funcao(float *x,float *y,int n)


{
int i,j;
float xx[4][4],yy[4][4];
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
xx[i][j] = x[j];
yy[i][j] = y[j];
}

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

6.3.4.1- Mdulo frac040.cpp

#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include "fract041.h"

extern float xmax,xmin,ymax,ymin;


extern float incremento;
extern int pontos;
int xp[2],yp[2];
int tamx = 400;
int tamy = 400;
int st = -1;

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();
}

void le_tecla(unsigned char key, int x, int y)


{
switch(key)
{
case 'I':
case 'i':
entra_dominio();
break;
}
}

void botao_mouse(int b,int state,int x, int y)


{
float t;
float xmin1,xmax1,ymin1,ymax1;

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();
}

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();
}

6.3.4.2- Mdulo frac041.cpp

/* * * * * * * * * * * */

51
/* Fractal Curva Koch */
/* fract041.cpp */

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>

float xmin = -2;


float ymin = -2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;

int pontos = 1000;

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 x0,float y0,float x1,float y1,int n)


{
int i,j;
float v[2];
float xx0,yy0,xx1,yy1;

xx0 = x0+1.0/3*(x1 - x0);


yy0 = y0+1.0/3*(y1 - y0);
xx1 = x0+2.0/3*(x1 - x0);
yy1 = y0+2.0/3*(y1 - y0);
if (n == 0) {
glColor3f(1.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(x0,y0);
glVertex2f(x1,y1);
glEnd();
}
else {
v[0]=(y0-y1)/(2*sqrt(3.0));
v[1]=(x1-x0)/(2*sqrt(3.0));
plota_funcao(x0,y0,xx0,yy0,n-1);
plota_funcao(xx0,yy0,(x0+x1)/2.0+v[0],(y0+y1)/2.0+v[1],n-1);
plota_funcao((x0+x1)/2.0+v[0],(y0+y1)/2.0+v[1],xx1,yy1,n-1);
plota_funcao(xx1,yy1,x1,y1,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);

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).

De forma esquemtica podemos estabelecer:

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.

1.1 - Comandos de Auxlio


Antes de iniciar a descrio do mecanismo das transformaes acima, apresentaremos um conjunto de
comandos de carter geral. Os comandos a seguir sero teis durante todas as etapas do processo de
modelagem, visualizao e Projeo.

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).

GlMultMatrix(const TYPE *M);

Este comando multiplica a matriz definida por


m1 m5 m9 m13
m 2 m6 m10 m14
M =
m3 m7 m11 m15

m 4 m8 m12 m16

pela matriz corrente.

1.2- Exemplo: cubo unitrio


Antes de detalhar as transformaes principais, vamos apresentar um programa exemplo que visualiza um
objeto tri-dimensional: o cubo unitrio. As coordenadas do cubo so:

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);
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cubo 3D");
glutDisplayFunc(display);
inicia_config();
glutMainLoop();
}

1.3 - Transformaes de Modelagem e Visualizao


Existem trs tipos de comandos para transformaes de modelagem: glTranslate(), glRotate() e
glScale(). Vamos descrever abaixo cada uma dessas funes.

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Triangulo");
glutDisplayFunc(display);
glutMainLoop();
}

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 :

glOrtho(double left, double right, double bottom, double top,


double near, double far);

1.5- ngulos de Euler


Um sistema de referncia que ir nos auxiliar na montagem do ambiente 3D so ao ngulos de Euler. Os
ngulos de Euler so definidos como trs sucessivos ngulos de rotao atravs do qual definiremos um novo
sistema de coordenadas partindo das coordenadas cartesianas.
No Opengl o sistema de coordenadas est posicionado conforme o desenho abaixo, onde o eixo x est na
posio horizontal, o eixo y na posio vertical e o eixo z est apontando para fora da tela do computador.

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.

Estes trs ngulos definem os ngulos de Euler.

1.6 - Criando um Ambiente de Visualizao 3D


Vamos montar um ambiente para visualizao tri-dimensional, atravs do qual poderemos visualizar nossos
objetos 3D.

1.6.1- Mdulo Bsico de Visualizao


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.

#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);

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cubo 3D");
glutDisplayFunc(display);
inicia_config();
glutMainLoop();
}

1.6.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 muse anda na
direo vertical alteramos phi.

#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);

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;
9
theta = theta + xm - xb;
phi = phi - ym + yb ;
inicia_config();
theta = theta - xm + xb;
phi = phi + ym - yb;
display();
}

void main(int argc, char **argv)


{
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);
glutMainLoop();
}

1.7 Visualizao de grfico de funes z = f ( x, y )

A seguir apresentamos um programa exemplo para visualizao de grficos de funes f : 2 . O


programa est dividido em dois mdulos: funcao3D01.cpp e funcao3D01a.cpp.

1.7.1 Mdulo funcao3D010.cpp

#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();
}

1.7.2 - Mdulo funcao3D011.cpp

#include <gl/glut.h>
#include <math.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)));
}

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();
}
}
}

1.7.3 - Mdulo funcao3D010.h

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.

2.1 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 :

void glLightfv(GLenum luz, GLenum iluminao, GLenum param);

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).

Os parmetros da iluminao so:

Parmetro Valor default Significado


GL_AMBIENT (0.0, 0.0, 0.0, 1.0) Intensidade da luz
ambiente
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) Intensidade da luz difusa
GL_SPECULAR (1.0, 1.0, 1.0, 1.0) Intensidade da luz
especular
GL_POSITION (0.0, 0.0, 1.0, 0.0) posio da luz
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) direo da luz
GL_SPOT_EXPONENT 0.0 Parmetro que controla a
distribuio da luz.
GL_SPOT_CUTOFF 180.0 ngulo de abertura da luz
GL_CONSTANT_ATTENUATION 1.0
GL_LINEAR_ATTENUATION 0.0
GL_QUADRATIC_ATTENUATION 0.0

2.1.1 Cor

A caracterstica da luz definida pelo parmetro iluminao. 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. 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.

Por exemplo, para alterar a luz ambiente utiliza-se o seguinte cdigo:


14
GLfloat luz_ambiente[4] = { 0.0, 0.0, 0.0, 1.0 };

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambiente);

2.1.2 Posio

A posio da luz pode ser de dois tipos bsicos:

- 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:

GLfloat luz_posicao[4] = { 1.0, 1.0, 1.0, 0.0 };


glLightfv(GL_LIGHT0, GL_POSITION, luz_posicao);

- 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}.

2.2 Selecionando o Modelo de Iluminao

2.2.1- Luz Ambiente Global

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:

GLfloat luz_ambiente_modelo[4] = { 0.2, 0.2, 0.2, 1.0 };


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.

2.2.2 Posio do observador local ou no infinito

A localizao do observador pode ou no influenciar na iluminao. O default o observador no infinito. Para


mudar a configurao, considerando-se a iluminao conforme o observador utilize:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

2.2.3 Iluminao nos dois lados das faces

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);

2.2.4 Habilitando a iluminao

No OpenGL voc precisa explicitamente habilitar a iluminao. Para isso utilize o comando:

glEnable(GL_LIGHTING);

Para desabilitar basta utilizar o comando:

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:

void glMaterialfv(GLenum face, GLenum iluminacao, TYPE param);

O parmetro face pode ser: GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK.

Os parmetros da iluminao so:

Parmetro Valor default Significado


GL_AMBIENT (0.2, 0.2, 0.2, 1.0) Cor da luz ambiente do
material
GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) Cor da luz difusa do
material
GL_SPECULAR (0.0, 0.0, 0.0, 1.0) Especular cor do material
GL_SHININESS 0.0 ndice especular
GL_EMISSION (0.0, 0.0, 0.0, 1.0) Cor de emisso do
material

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.

2.4.1- Mdulo Ilumina_main.cpp

#include <gl\glut.h>
#include <stdio.h>
#include "ilumina_funcao.h"
#include "ilumina_set.h"

extern float ptx,pty;


extern float xmin,xmax,ymin,ymax;
extern float light[8][4];
extern GLfloat spot_direction[3] ;
extern GLfloat spot_cutoff ;
extern GLfloat spot_exponent ;
extern GLfloat c_attenuation ;
extern GLfloat l_attenuation ;
extern GLfloat q_attenuation ;
extern GLfloat material_shininess[1];

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();
}

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;
case ' ':
17
type_light = (type_light + 1 ) % 8 ;
switch(type_light)
{
case 0:
printf("Luz Ambiente \n");
printf("%f %f %f \n
",light[0][0],light[0][1],light[0][2]);
break;
case 1:
printf("Luz Difusa \n");
printf("%f %f %f \n
",light[1][0],light[1][1],light[1][2]);
break;
case 2:
printf("Posicao Luz \n");
printf("%f %f %f \n
",light[2][0],light[2][1],light[2][2]);
break;
case 3:
printf("Luz Especular \n");
printf("%f %f %f \n
",light[3][0],light[3][1],light[3][2]);
break;
case 4:
printf("Material Ambiente \n");
printf("%f %f %f \n
",light[4][0],light[4][1],light[4][2]);
break;
case 5:
printf("Material Difusa \n");
printf("%f %f %f \n
",light[5][0],light[5][1],light[5][2]);
break;
case 6:
printf("Material Especular \n");
printf("%f %f %f \n
",light[6][0],light[6][1],light[6][2]);
break;
case 7:
printf("Ambiente \n");
printf("%f %f %f \n
",light[7][0],light[7][1],light[7][2]);
break;
}
break;
case 'R':
light[type_light][0] += 0.1;
light[type_light][0] = (light[type_light][0] >
1.0) ? 1.0 : light[type_light][0];
light[type_light][0] = (light[type_light][0] <
0.0) ? 0.0 : light[type_light][0];
printf("%f \n",light[type_light][0]);
display();
break;
case 'r':
light[type_light][0] -= 0.1;
light[type_light][0] = (light[type_light][0] >
1.0) ? 1.0 : light[type_light][0];
light[type_light][0] = (light[type_light][0] <
0.0) ? 0.0 : light[type_light][0];
printf("%f \n",light[type_light][0]);
display();
break;
case 'G':
light[type_light][1] += 0.1;
light[type_light][1] = (light[type_light][1] >
1.0) ? 1.0 : light[type_light][1];
18
light[type_light][1] = (light[type_light][1] <
0.0) ? 0.0 : light[type_light][1];
printf("%f \n",light[type_light][1]);
display();
break;
case 'g':
light[type_light][1] -= 0.1;
light[type_light][1] = (light[type_light][1] >
1.0) ? 1.0 : light[type_light][1];
light[type_light][1] = (light[type_light][1] <
0.0) ? 0.0 : light[type_light][1];
printf("%f \n",light[type_light][1]);
display();
break;
case 'B':
light[type_light][2] += 0.1;
light[type_light][2] = (light[type_light][2] >
1.0) ? 1.0 : light[type_light][2];
light[type_light][2] = (light[type_light][2] <
0.0) ? 0.0 : light[type_light][2];
printf("%f \n",light[type_light][2]);
display();
break;
case 'b':
light[type_light][2] -= 0.1;
light[type_light][2] = (light[type_light][2] >
1.0) ? 1.0 : light[type_light][2];
light[type_light][2] = (light[type_light][2] <
0.0) ? 0.0 : light[type_light][2];
printf("%f \n",light[type_light][2]);
display();
break;
case 's':
material_shininess[0] -= 1;
printf("%f \n",material_shininess[0]);
display();
break;
case 'S':
material_shininess[0] += 1;
printf("%f \n",material_shininess[0]);
display();
break;
case 'c':
spot_cutoff -= 1;
printf("%f \n",spot_cutoff);
display();
break;
case 'C':
spot_cutoff += 1;
printf("%f \n",spot_cutoff);
display();
break;
case 'e':
spot_exponent -= 0.1;
printf("%f \n",spot_exponent);
display();
break;
case 'E':
spot_exponent += 0.1;
printf("%f \n",spot_exponent);
display();
break;
case 'a':
c_attenuation -= 0.1;
printf("%f \n",c_attenuation);
display();
break;
19
case 'A':
c_attenuation += 0.1;
printf("%f \n",c_attenuation);
display();
break;
case 'l':
l_attenuation -= 0.1;
printf("%f \n",l_attenuation);
display();
break;
case 'L':
l_attenuation += 0.1;
printf("%f \n",l_attenuation);
display();
break;
case 'q':
q_attenuation -= 0.1;
printf("%f \n",q_attenuation);
display();
break;
case 'Q':
q_attenuation += 0.1;
printf("%f \n",q_attenuation);
display();
break;

}
}

void main(int argc, char **argv)


{
xmin = ymin = -4;
xmax = ymax = 4;
ptx = pty = 10;
glutInit(&argc,argv);
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();
}

2.4.2 Mdulo ilumina_funcao.cpp

#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();
}

void normalv(float *v,float x,float y,float dx, float dy)


{
float v1[3],v2[3],norma;

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);

v[0] = v1[1] * v2[2] - v1[2] * v2[1];


v[1] = v1[0] * v2[2] - v1[2] * v2[0];
v[2] = v1[0] * v2[1] - v1[1] * v2[0];

norma = sqrt(v[0] * v[0] + v[1] *v[1] + v[2] * v[2]);


v[0] = v[0] / norma;
v[1] = v[1] / norma;
v[2] = v[2] / norma;
}

float dfx(float x,float y)


{
return(-2*x);
}

float dfy(float x,float y)


{
return(2*y);
}

void draw_normal(float x,float y)


{
float z,z1,z2;

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();
}

2.4.3- Mdulo ilumina_set.cpp

#include <gl\glut.h>
#include <stdio.h>

GLfloat light[8][4] = {{ 0.3, 0.3, 0.3, 1.0 }, /* Luz Ambiente


*/
{ 1.0, 1.0, 1.0, 1.0 }, /* Luz difusa
*/
{ 1.0, 1.0, 1.0, 0.0 }, /* Posicao da luz
*/
{ 1.0, 1.0, 1.0, 1.0 }, /* Luz Especular
*/
{ 0.4, 0.4, 0.4, 1.0 }, /* Material Ambiente
*/
{ 0.8, 0.8, 0.8, 1.0 }, /* Material Difusa
*/
{ 1.0, 1.0, 1.0, 1.0 }, /* Material Especular
22
*/
{ 0.0, 0.0, 0.0, 1.0 }}; /* Iluminacao do
Ambiente */

GLfloat spot_direction[3] = {0.0,0.0,-10.0};


GLfloat spot_cutoff = 180.0;
GLfloat spot_exponent = 0.0;
GLfloat c_attenuation = 1.0;
GLfloat l_attenuation = 0.0;
GLfloat q_attenuation = 0.0;
GLfloat material_shininess[1] = { 60.0 } ;

/*---------------------------------------------------------------*/
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);

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, light[4]);


glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, light[5]);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, light[6]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_shininess );
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
}

2.4.4 Mdulo ilumina_funcao.h


void draw_eixos();
void draw_funcao();

2.4.5 Mdulo ilumina_set.h


void desabilita_lighting();
void habilita_lighting();
void le_tecla(unsigned char key, int x, int y);

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:

(u , v) = ( x(u, v), y (u , v), z (u , v))

Uma superfcie parametrizada uma aplicao : D R 2 R 3 onde D algum domnio em R 2 . A


superfcie S correspondente a funo a imagem S = ( D ) . A superfcie parametrizada depende de dois
parmetros (u, v).

3.1 Visualizao de superfcies na forma paramtrica


.
Para visualizar superfcies dadas na forma paramtrica, utilizaremos o programa abaixo. O programa
composto de dois mdulos: sup_main.cpp e sup_param.cpp. O mdulo sup_main.cpp
responsvel pelas tarefas de iluminao e definio do ambiente OpenGL. O segundo mdulo
sup_param.cpp define a parametrizao e atravs da funo draw_superficie(), visualiza a superfcie
desejada.

/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Superficies Parametrizadas */
/* */
/* Modulo: Sup_main.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */

#include <gl\glut.h>
#include <stdio.h>
#include "Sup_param.h"

extern float ptx,pty;


extern float umin,umax,vmin,vmax;

int type_light = 0;
24
int xb,yb,xm,ym;
float gamma=90.0,phi=45.0,theta=135.0;
float scale = 1.0;

GLfloat light[8][4] = {{ 0.1, 0.0, 0.0, 1.0 },


{ 0.3, 0.3, 0.0, 1.0 },
{ 1.0, 1.0, 1.0, 0.0 },
{ 0.0, 0.0, 1.0, 1.0 },
{ 0.2, 0.4, 0.0, 1.0 },
{ 1.0, 1.0, 0.0, 1.0 },
{ 0.3, 0.8, 1.0, 1.0 },
{ 0.5, 0.0, 0.1, 1.0 }};

GLfloat light1[8][4] = {{ 0.3, 0.3, 0.3, 1.0 },


{ 1.0, 1.0, 1.0, 1.0 },
{ 0.0, 0.0, -1.0, 0.0 },
{ 1.0, 1.0, 1.0, 1.0 },
{ 0.0, 0.0, 1.0, 1.0 },
{ -1.0, -1.0, -1.0, 1.0 },
{ 0.0, 0.1, 1.0, 1.0 },
{ 0.5, 0.5, 0.5, 1.0 }};
GLfloat material_shininess[1] = { 60.0 } ;
GLfloat lmodel_ambient[4] = {0.5,0.5,0.5,1.0};
GLfloat spot_cutoff = 90.0;
GLfloat spot_exponent = 0.0;
GLfloat c_attenuation = 1.0;
GLfloat l_attenuation = 0.0;
GLfloat q_attenuation = 0.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);

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);
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);
25
glLightfv(GL_LIGHT1, GL_AMBIENT, light1[0]);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1[1]);
glLightfv(GL_LIGHT1, GL_POSITION, light1[2]);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1[3]);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1[4]);
glLightf (GL_LIGHT1, GL_SPOT_CUTOFF , spot_cutoff);
glLightf (GL_LIGHT1, GL_SPOT_EXPONENT , spot_exponent);
glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION , c_attenuation);
glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION , l_attenuation);
glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION , q_attenuation);
glEnable(GL_LIGHT1);

glLightfv(GL_LIGHT2, GL_AMBIENT, light[0]);


glLightfv(GL_LIGHT2, GL_DIFFUSE, light[1]);
glLightfv(GL_LIGHT2, GL_POSITION, light1[5]);
glLightfv(GL_LIGHT2, GL_SPECULAR, light[3]);
glLightf (GL_LIGHT2, GL_SPOT_CUTOFF , spot_cutoff);
glLightf (GL_LIGHT2, GL_SPOT_EXPONENT , spot_exponent);
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, light1[6]);
glLightf (GL_LIGHT2, GL_CONSTANT_ATTENUATION , c_attenuation);
glLightf (GL_LIGHT2, GL_LINEAR_ATTENUATION , l_attenuation);
glLightf (GL_LIGHT2, GL_QUADRATIC_ATTENUATION , q_attenuation);
glEnable(GL_LIGHT2);

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);

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, light[4]);


glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, light[5]);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, light[6]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_shininess );
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);

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);
}

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)


{
glutInit(&argc,argv);
27
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();
}

/* * * * * * * * * * * * * * * * * * * * * * * */
/* */
/* Superficies Parametrizadas */
/* */
/* Modulo: Sup_param.cpp */
/* */
/* * * * * * * * * * * * * * * * * * * * * * * */

#include <gl/glut.h>
#include <math.h>
#include "Sup_param.h"

float umin = 0.0 ;


float umax = 6.283;
float vmin = 1.5 ;
float vmax = 4.28;
float ptx = 20 ;
float pty = 20 ;

void parametrizacao(float u,float v,float *x,float *y,float *z)


{
*x = -sin(u)*(2+cos(v));
*y = cos(u)*(2+cos(v));
*z = 2+sin(v);
}

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 normalv(float *n,float u,float v,float dx, float dy)


28
{
float v1[3],v2[3],norma;
float x1,y1,z1;
float x2,y2,z2;
float x3,y3,z3;

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;

n[0] = v1[1] * v2[2] - v1[2] * v2[1];


n[1] = v1[0] * v2[2] - v1[2] * v2[0];
n[2] = v1[0] * v2[1] - v1[1] * v2[0];

norma = 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;
}

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

2) Visualize os vetores normais sobre a superfcie. Observe o exemplo da letra f).

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

Entre as vrias solues possveis, apresentaremos o mtodo de Shepard.

4 .1 Interpolao Utilizando o Mtodo de Shepard


O mtodo de Shepard define a funo por:

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

Uma forma numericamente mais estvel para se calcular os vi dada por:

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 )

4 .2 Propriedades do Mtodo de Shepard


Destacamos duas propriedades importantes do mtodo de Shepard:

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;

GLfloat visgl_lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 } ;


GLfloat material_shininess[1]= { 60.0 } ;
GLfloat light[8][4] = {{ 0.3, 0.3, 0.3, 1.0 },
{ 1.0, 1.0, 1.0, 1.0 },
{ 0.0, 0.0, 1.0, 0.0 },
{ 1.0, 1.0, 1.0, 1.0 },
{ 0.4, 0.4, 0.4, 1.0 },
{ 0.9, 0.9, 0.9, 1.0 },
{ 1.0, 1.0, 1.0, 1.0 },
{ 0.0, 0.0,-1.0, 0.0 }};

/*---------------------------------------------------------------*/
void desabilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
}

/*---------------------------------------------------------------*/
void habilita_lighting()
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
{

// glShadeModel(GL_FLAT);

glLightfv(GL_LIGHT0, GL_AMBIENT, light[0]);


32
glLightfv(GL_LIGHT0, GL_DIFFUSE, light[1]);
glLightfv(GL_LIGHT0, GL_POSITION, light[2]);
glLightfv(GL_LIGHT0, GL_SPECULAR, light[3]);
glEnable(GL_LIGHT0);

glLightfv(GL_LIGHT1, GL_AMBIENT, light[0]);


glLightfv(GL_LIGHT1, GL_DIFFUSE, light[1]);
glLightfv(GL_LIGHT1, GL_POSITION, light[7]);
glLightfv(GL_LIGHT1, GL_SPECULAR, light[3]);
glEnable(GL_LIGHT1);

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);

glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, light[4]);


glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, light[5]);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, light[6]);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, material_shininess );
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);

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);
}

void botao_mouse(int b,int state,int x, int y)


{

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;
}
}

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)


{
int i;

printf("\n Numero de pontos = ");


scanf("%d",&N);
xp = (float *) malloc(N*sizeof(float));
yp = (float *) malloc(N*sizeof(float));
zp = (float *) malloc(N*sizeof(float));

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 xb,yb,xm,ym;

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();
}

float interp(float xx,float yy)


{
int i,j;
35
float s = 0.0;
float sv = 0.0;
float *p;

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);
}

void normalv(float *v,float x,float y,float dx, float dy)


{
float v1[3],v2[3];

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);

v[0] = v1[1] * v2[2] - v1[2] * v2[1];


v[1] = v1[0] * v2[2] - v1[2] * v2[0];
v[2] = v1[0] * v2[1] - v1[1] * v2[0];
}

void draw_normal(float x,float y,float dx,float dy)


{
float z,v[3];

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.

1. ESTRUTURA BSICA DE UM PROGRAMA EM C++

Em C++ os programas so escritos utilizando-se classes. Inicialmente vamos aprender os


comandos bsicos do C++ e na seo 3 discutiremos o funcionamento das classes e a
orientao a objeto.

1.1 - Primeiro Programa

Como primeiro exemplo, consideremos o programa modelo do software Eclipse:

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;
}

As primeiras linhas declaram as variveis e os tipos:

int n;
Tipo da varivel Nome da varivel

Em seguda atribuimos o valor 1 para a varivel:

n = 1;

O C++ tem diferentes tipos de variveis. Os tipos bsicos so:

boolean 1-bit (TRUE ou FALSE)


char 8-bit inteiro(signed) (-128 a 127)
short 16-bit inteiro(signed) (32.768 a 32.767)
int 64-bit inteiro(signed)(-2.147.483.648 a 2.147.483 .647)
float 32-bit floating-point (10e-38 a 10e38)
double 64-bit floating point (10e-308 a 10e308)
unsigned Retira o sinal e portanto troca a variao de valores,
por exemplo: unsigned char varia de 0 a 255

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

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;

freqentemente representado por:

i++;

Da mesma forma i = i-1; pode ser escrito como 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

possvel introduzir comentrios dentro de um programa em C++. H dois nos formatos


bsicos:

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

Observe o exemplo abaixo:

#include <iostream>
#include <cmath>

int main() {

/* Solues reais da equao a*x*x + b*x + c = 0 */

double x1, x2;

const double a = 1; // Valores arbitrarios para a, b e c


const double b = -5;
const double 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;
}

6
1.5 - Fluxo de Controle

O comando principal de deciso o if() { }. Os trs formatos mais utilizados de laos


so:

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;

/** Testa se um numero e par ou impar */


int main() {

int i, n;

cout << "ntre com um numero inteiro: ";


cin >> n; // Entre com 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( ; ; ) {}

O for um comando apropriado quando queremos executar um conjunto de operaes um


nmero fixo de vezes, como no exemplo da seqncia de fibonacci:

Fibonacci.cpp

#include <iostream>
#include <cmath>
using namespace std;

/** Gera a sequencia de Fibonacci */

const int MAX = 10;


int main() {
int n;
int lo = 1;
int hi = 1;
cout << "1: 1 \n";
for (n = 2; n <= MAX; n++) {
cout << n << ": " << hi << endl;
hi = lo + hi;
lo = hi - lo;
}

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.

Exemplo: Mtodos numricos de integrao (ponto a esquerda)

Como aplicao do comando for o exemplo abaixo ilustra a implementao do mtodo do


ponto a esquerda. Podemos utilizar os mtodos de integrao para obter uma aproximao
para a expanso decimal de . Se calcularmos:

obteremos aproximaes para .

PontoEsquerda.cpp
#include <iostream>
#include <cmath>
using namespace std;

/* Integracao Numerica: Ponto a Esquerda */

int main() {

int i;
int n;
double x, dx;
double a, b;
double soma;

cout.precision(20);

a = -1; // Extremo inferior do intervalo


b = 1; // Extremo superior do intervalo
n = 1000; // Numero de particoes

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);
}

Exemplo: Mtodos numricos de integrao (Monte Carlo)

Neste mtodo utilizamos um sorteio de pontos em uma certa regio. O quociente do


nmero de pontos que so sorteados no interior pelo nmero total de pontos uma
estimativa para a integral.

MonteCarlo.cpp
#include <iostream>
#include <cstdlib>
using namespace std;

/* Integracao Numerica: Monte Carlo */

int main() {

double x, y, f;
int cont = 0;
const int points = 500000;

srand(1);
cout.precision(20);

for (int i = 0; i < points; i++) {


x = (double)rand()/ RAND_MAX;
y = (double)rand()/ RAND_MAX;
if ((x * x + y * y - 1) < 0)
cont++;
}
f = 4.0 * cont / points;
cout << "Pi = " << f << endl;
}

Exemplo: Mtodos numricos de integrao (Mtodo de Simpson)

O mtodo de Simpson refina o mtodo do trapzio [Malta,Pesco,Lopes, Clculo a uma


varivel Vol II].
#include<iostream>
#include<cmath>
using namespace std;

#define PI 3.14159265358979323846264338327950288419716939937510

10
int main() {
int n;
double x, dx;
double a, b;
double soma;
cout.precision(20);

a = -1; // Extremo inferior do intervalo


b = 1; // Extremo superior do intervalo
n = 100000; // Numero de particoes
soma = 0.0;
dx = (b - a) / n;
x = a;
soma = 2 * sqrt(1 - a * a);
for (int i = 1; i < n; i++) {
x = x + dx;
if (i % 2 == 0)
soma = soma + 2 * 2*sqrt(1 - x * x);
else
soma = soma + 4 * 2*sqrt(1 - x * x);
}
soma = 2 * sqrt(1 - b * b);
soma = soma * dx / 3;
cout << "\n Integral = " << soma;
cout << "\n Pi = " << PI;
cout << "\n Erro = " << (soma - PI);
}

1.5.3 - Comando while() {} e do { } while();

Este segundo tipo de lao adequado para situaes onde no sabemos ao certo quantas
vezes o lao deve ser repetido.

Existem dois formatos:

while (condio) {
...
comandos
...
}

Inicia testando se a condio verdadeira, e em caso afirmativo, os comando dentro while


so executados e ao final, a condio novamente testada. Enquanto a condio
permanecer verdadeira, os comandos no interior do while so repetidos. Observe que se a
condio for falsa a primeira vez, em nenhum momento os comandos dentro do lao sero
executados.

do {
...
comandos
...

11
} while (condio);

Inicia executando os comandos e ao final, testa a condio. Se verdadeira, ento os


comandos so novamente executados. Enquanto a condio permanecer verdadeira, os
comandos so repetidos. Observe que os comandos so executados no mnimo uma vez,
mesmo que a condio seja falsa na primeira vez, sendo esta a diferena para o formato
anterior while() {}.

Os exemplos a seguir ilustram aplicaes de ambos os casos:

Exemplo: Mtodo de Newton

O programa abaixo determina as solues da equao

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);

cout << "Solucao obtida = " << xn << endl;


cout << "Raiz 2 = " << M_SQRT2 << endl;
}

12
Exemplo: Mtodo da Bisseo

O programa abaixo determina as solues da equao:

Para isso utilizaremos o mtodo da bisseo. No mtodo da bisseo procuramos uma


soluo contida em certo intervalo [a,b] dado. A soluo 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).

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 * fb) > 0) {


cout << "Intervalo inicial nao garante existencia de
solucao ! \n";
return 0;
}

while(fabs(a-b) > erro) {


c = (a+b)/2.0;
fc = c*c - 2.0;

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:

- O comando break; interrompe o lao (Qualquer dos formatos apresentados) e o


programa continua no primeiro comando aps o lao. Exemplo:

Exemplobreak.cpp

#include <iostream>
using namespace std;

int main() {

int n = 0;

while (n < 10) {


cout << "n = " << n << endl;
if (n > 3)
break;
n++;
}
cout << "Fim do programa \n";
}

O resultado deste programa ser:

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.

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 * fb) > 0) {


cout << "Intervalo inicial nao garante existencia de
solucao ! \n";
return 0;
}
while(fabs(a-b) > erro) {
c = (a+b)/2.0;
fc = f(c);

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>

void troca(float x, float y)


{
float auxiliar;

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 resultado deste programa seria:


x = 1.2 e y = 56.89
Como visto anteriormente, utilizando referncias podemos obter o efeito desejado:
Permuta.cpp
/* Este programa consegue permutar os valores */

#include <iostream>

void troca(float& x, float& y)


{
float auxiliar;

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];

for (i = 0; i < 5; i++) {


cout << " Aluno [" << (i+1) << "]:" ;
cin >> notas[i];
}

soma = 0;
for (i = 0; i < 5; i++)
soma = soma + notas[i];

media = soma / 5;
cout << " A media final : " << media;
}

2.1.1 - Declarao

Um vetor uma coleo de variveis de certo tipo, alocadas seqencialmente na memria.


Para 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:

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:

int n[5] = {23, 3, -7, 288, 14};

2.1.2 Exemplo: Mtodo de Ordenao

Como exemplo vamos apresentar um programa que ordena uma seqncia de 10 nmeros
reais.
Ordenao.cpp

/* Metodo da Bolha (ordenacao de um vetor) */

#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];
}

/* Ordena a sequencia de numeros */


flag = 1;
while (flag == 1) {
flag = 0;
for (i = 0; i < (n - 1); i++) {
if (x[i] > x[i + 1]) {
swap = x[i];

20
x[i] = x[i + 1];
x[i + 1] = swap;
flag = 1;
}
}
}

/* Imprime a sequencia de numeros ordenada */


cout << "\n Sequencia ordenada : " << endl;
for (i = 0; i < n; i++)
cout << x[i] << endl;
}

2.2 - Matrizes
Para representar uma matriz 3x4 (3 linha e 4 colunas) de nmeros reais utilizamos a
seguinte declarao:

float A[3][4];

Assim fica reservado um espao de memria conforme a figura abaixo:

A[0][0] A[0][1] A[0][2] A[0][3]


A[1][0] A[1][1] A[1][2] A[1][3]
A[2][0] A[2][1] A[2][2] A[2][3]

Exemplo: Produto de uma matriz por um vetor

Vamos montar um programa que multiplica um vetor por uma matriz.


/* * * * * * * * * * * * * * * * * * * * * * */
/* Multiplicacao de um vetor por uma matriz */
#include <iostream>
using namespace std;

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];

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++) {
cout << "\n[";
for (j = 0; j < 3; j++)
cout << A[i][j] << " ";
cout << " ] [ " << v[i] << "]";
}
for (i = 0; i < 3; i++)

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;

cout << "Endereco de i = " << &i << endl;


}

O endereo da varivel obtido utilizando-se o operador unrio & na frente da varivel.


Assim &i fornece o endereo da varivel i.

3.2 Principais Aplicaes de Ponteiros

Algumas situaes em que os ponteiros so teis:


1. Para passar vetores e matrizes de forma mais conveniente como argumentos de funes.
2. Para manipular vetores e matrizes de forma mais eficiente.
3. Para manipular estruturas de dados mais complexas, tais como listas e rvores.
4. Na utilizao de alocao de memria dinmica.

3.3 Armazenando o Endereo das Variveis

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

3.4 Acessando o contedo de um endereo

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:

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 */

cout << "Endereco de i = " << pi << endl;


cout << "j = " << j << endl;
}

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

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:
/* Metodo da Bolha (ordenacao de um vetor) */

#include <iostream>
using namespace std;

void troca(float& x, float& y)


{
float auxiliar;

auxiliar = x;
x = y;
y = auxiliar;
}

void ordena(float *v,int elementos)


{
// Ordena a sequencia de numeros
int flag = 1;

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);

// Imprime a sequencia de numeros ordenada


cout << "\n Sequencia ordenada : " << endl;

24
for (int i = 0; i < n; i++)
cout << x[i] << endl;
}

Observe que quando chamamos a funo ordena(x,n), utilizamos como argumento a


varivel x, sem referncia a nenhum ndice em particular do vetor. A funo ordena
declarada como:

void ordena(float *v, int elementos)

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.

3.6 Alocao de Vetores Dinamicamente


Uma das restries do nosso programa de ordenao que o usurio no pode definir a
princpio quantos elementos ele pretende ordenar. Isto ocorre porque precisamos informar
na declarao do vetor qual ser a sua dimenso. Vamos retirar essa restrio. Para isso
utilizaremos um novo comando: new[]. Vamos utilizar um exemplo:

#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];

cout << "Entre com o vetor = " << endl;


for(i=0;i<n;i++)
cin >> v[i];
for(i=0;i<n;i++)
cout << "v[" << i << "]= " << v[i] << endl;;

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.

3.7 Alocao de Matrizes Dinamicamente

Para alocar matrizes observe o exemplo:


#include <iostream>
using namespace std;

void main()
{
int i,j,n,m;
float **A;

cout << "Entre com a dimenso da matriz desejada: \n n = ";


cin >> n;
cout << " m = ";
cin >> m;

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

A programao orientada a objeto uma estratgia de programao onde definimos novos


tipos de dados (os objetos) e as operaes que faremos sobre esses dados. A definio de
um objeto feita pela noo de classe, que ser descrita nesta seo.

4.1 Membros da Classe

Uma classe tem dois tipos principais de componentes:

1. Vrivel Membro: correspondem aos dados, representados pelos campos da classe.


2. Funo Membro: so funes que operam sobre os campos da classe.

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;

cout << "Area do Circulo = " << A.area();


}

4.2 Construtores

A declarao feita no programa main:

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).

Observe que no nosso exemplo a classe se chama Circulo e portanto o construtor se


chama Circulo(...) tambm.

#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;
};

O construtor Circulo(double r,double cx, double cy) permite que se inicialize os


campos do objeto conforme os parmetros de entrada.
Circulo.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include "Circulo.hpp"

Circulo::Circulo() {
raio = 1.0;
centrox = 0.0;
centroy = 0.0;
}

Circulo::Circulo(double r,double cx, double cy) {


raio = r;
centrox = cx;
centroy = cy;
}

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);

cout << "Area do Circulo A = " << A.area();


cout << "Area do Circulo B = " << B.area();
}

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.

4.3 Controle de Acesso aos Campos e Funes

4.3.1 - Seo Pblica


Observe que a primeira parte da classe Circulo inicia com uma seo pblica, denotada por
public:. A lista de itens que segue aps essa declarao (funes ou variveis)
ficam disponveis para acesso. Este elemento define o controle de acesso aos elementos,
definindo assim se um dado campo da classe pode ou no ser alterado por outra classe.

4.3.2 - Seo Privada


Os elementos definidos na seo private somente so acessveis pela prpria classe.
Utilizamos private quando queremos que os campos no sejam alterados exceto pelas
funes da classe.

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

double raio; // Campos


double centrox,centroy;
};

main.cpp
#include <iostream>
#include "Circulo.hpp"
using namespace std;

int main() {
Circulo A;

A.raio = 2;
A.centrox = 0.2;

cout << "Area do Circulo A = " << A.area() << endl;


}

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;

A.raio = 2; // ERRO NA COMPILAO !


A.centrox = 0.2; // ERRO NA COMPILAO !

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 Funes Membros

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.

4.3.2 Acesso as variveis da classe

Podemos definir funes que alteram ou exibem as variveis da classe.


Circulo.hpp
class Circulo {
public:
Circulo(); // Construtor
void translacao(double x,double y);
double get_centrox();
double get_centroy();
double area(); // Funcao membro
private:
double raio; // Campos
double centrox,centroy;
};

31
Circulo.cpp
#define _USE_MATH_DEFINES
#include <math.h>
#include "Circulo.hpp"

Circulo::Circulo() {
raio = 1.0;
centrox = 0.0;
centroy = 0.0;
}

void Circulo::translacao(double x,double y)


{
centrox += x;
centroy += y;
}

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

O exemplo abaixo ilustra a implementao de uma classe que represente um nmero


racional por seu numerador e denominador inteiro.
Racional.hpp
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 soma(const Racional& p);


Racional subtrai(const Racional& q);
Racional multiplica(const Racional &n);
void show();
};

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;
}

Racional Racional::soma(const Racional& z) {


Racional s;

s.p = z.p * q + z.q * p;


s.q = z.q * q;
s.simplifica();
return(s);
}

Racional Racional::subtrai(const Racional& z)


{
Racional dif;

33
dif.p = z.q * p - z.p * q;
dif.q = z.q * q;
dif.simplifica();
return(dif);
}

Racional Racional::multiplica(const Racional& z) {


Racional s;
s.p = z.p * p;
s.q = z.q * q;
s.simplifica();
return(s);
}

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

O exemplo abaixo ilustra a implementao de uma classe vetor de double.


Vetor.hpp
class Vetor
{
double *v ; // Os primeiros campos sao private
int dim;
public:
Vetor(int n); // Construtor
Vetor(Vetor& W); // Construtor
~Vetor(); // Destruidor

void set(int i,double x); // Funcoes de acesso e modificadores


double get(int i);
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.get(j);
}

Vetor::~Vetor() {
delete [] v;
}

void Vetor::set(int i,double x) {


if ((i >= 0) && (i<dim))
v[i] = x;
}

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;

cout << "Entre com a dimenso do vetor: = ";


cin >> n;

Vetor A(n);

cout << "Entre com os elementos do vetor" << endl;


for(i=0;i<n;i++) {
double x;
cout << "V[" << i << "]=";
cin >> x;
A.set(i,x);
}

for(i=0;i<n;i++)
cout << " A["<<i<<"]= " << A.get(i) << endl;
}

Soma de vetores

Existem diferentes formas de se implementar a soma de dois objetos. No caso de vetores,


vamos considerar como um primeiro exemplo somar dois vetores u e v resultando em um
novo vetor soma. A operao de soma sera implementada como uma funo da classe
Vetor.

Vetor.h
class Vetor
{
double *v ; // Os primeiros campos sao private
int dim;
public:
Vetor(int n); // Construtor
Vetor(Vetor& W); // Construtor
~Vetor(); // Destruidor

void set(int i,double x); // Funcoes de acesso e modificadores


double get(int i);
int get_dim();

Vetor soma(Vetor b);


};

36
Vetor.cpp
#include "Vetor.h"

.
.
.

Vetor Vetor::soma(Vetor b)
{
if (dim != b.dim)
return 0;
Vetor soma(dim);

for(int i = 0; i < dim; i++)


soma.v[i] = v[i] + b.v[i];

return soma;
}

main.cpp
#include <iostream>
using namespace std;
#include "Vetor.h"

int main()
{
int i,n;

cout << "Entre com a dimenso do vetor: = ";


cin >> n;

Vetor A(n);
Vetor B(n);

cout << "Entre com os elementos do vetor" << endl;


for(i=0;i<n;i++) {
double x;
cout << "v[" << i << "]=";
cin >> x;
A.set(i,x);
cout << "w[" << i << "]=";
cin >> x;
B.set(i,x);
}

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;

cout << "Entre com a dimenso do vetor: = ";


cin >> n;

Vetor A(n);

cout << "Entre com os elementos do vetor" << endl;


for(i=0;i<n;i++) {
double x;
cout << "V[" << i << "]=";
cin >> x;
A[i] = x;
}

for(i=0;i<n;i++)
cout << " A["<<i<<"]= " << A[i] << endl;
}

A classe racional poderia ser reimplementada da seguinte forma:


Racional.h
#include <iostream>
using namespace std;

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 operator+(const Racional& n);


Racional operator*(const Racional& n);
Racional operator-(const Racional& n);
friend ostream& operator<<(ostream& out, const Racional& r);
friend bool operator==(const Racional& r,const Racional& s);
};

Racional.cpp
#include "Racional.h"

Racional Racional::operator-(const Racional& z)


{
Racional dif;

dif.p = z.q * p - z.p * q;

39
dif.q = z.q * q;
dif.simplifica();

return(dif);
}

ostream& operator<<(ostream& out, const Racional& r)


{
if (r.q == 1)
out << r.p;
else
if ( r.q == -1)
out << -r.p;
else
out << r.p << "/" << r.q;
return(out);
}

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;
}

Racional Racional::operator+(const Racional& z)


{
Racional s;

s.p = z.p * q + z.q * p;


s.q = z.q * q;
s.simplifica();

return(s);

Racional Racional::operator*(const Racional& z)


{
Racional 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.

0,0 1,0 2,0


0,1 1,1 2,1

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:

8 bits 256 cores

(High Color) 16 bits 65.536 cores

(True Color) 24 bits 16.777.216 cores

(True Color) 32 bits 4.294.967.296 cores

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.

1.4 Funes Bsicas


O cdigo abaixo cria uma janela grfica.
#include <gl\glut.h>

void display()
{
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutMainLoop();
}

Vamos comentar funo a funo:

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.

Podemos alterar as configuraes iniciais da janela grfica:


#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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(400,400);
glutInitWindowPosition(1,1);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutMainLoop();
}

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:

GLUT_DOUBLE: Buffer duplo


GLUT_RGBA...: Modelo de representao das cores.
GLUT_DEPTH.: Buffer de profundidade (utilizado em remoo de superfcies escondidas).

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 );

2) Acrescente um contador para verificar quantas vezes a funo display chamada.

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

e identicamente para a coordenada y: .

O programa abaixo ilustra o efeito do gluOrttho2D.


#include <iostream>
using namespace std;
#include <gl\glut.h>

const int DIMX = 400;


const int DIMY = 600;

float xmin = -1;


float xmax = 1;
float ymin = -1;
float ymax = 1;

void converte(float L,float R,float T,float B,float& x,float& y) {


/* Faz a funcao do glOrtho */
x = ((x - L)/(R-L) * DIMX);
y = ((y - B)/(T-B) * DIMY);
}

6
void display()
{

float x = 0.5; /* Ponto que gostariamos de converter */


float y = 0.5;

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();
}

int main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(DIMX,DIMY);
glutInitWindowPosition(50,50);
glutCreateWindow("Ortho");
gluOrtho2D(0,DIMX-1,DIMY-1,0);/* Matriz de pontos DIMx x DIMy */
glutDisplayFunc(display);
glutMainLoop();
}

1.6 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 :

1.6.1 Algoritmo ingnuo

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();
}

void main(int argc, char **argv)


{

cout << "x0 = ";


cin >> x0;
cout << "y0 = ";
cin >> y0;
cout << "x1 = ";
cin >> x1;
cout << "y1 = ";
cin >> y1;

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();
}

Algumas desvantagens do programa proposto:

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.

1.6.2 Retas no Opengl

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();
}

1.7 Exemplo: Plotar o grfico de uma funo


Vamos comear com uma verso bem simplificada, para plotar o grfico de uma funo y=f(x).

#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();
}

void main(int argc, char **argv)


{

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:

funcao(int p = 300,float xm = -1,float xM = 1);

float f(float x) { return(sin(x)); }

void dominio();
void plota_funcao();
};

funcao.cpp
#include <gl\glut.h>
#include "funcao.h"
#include <iostream>
using namespace std;

funcao::funcao(int p ,float xm ,float xM) {


pontos = p;
xmin = xm;
xmax = xM;
}

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
gluOrtho2D(L,R,B,T);
glutMainLoop();
}

1.8 Fontes
Utilizando o glut possvel incluir textos na visualizao do grficos. Para isso precisamos de duas
funes:

glRasterPos2f(float x, float y);


Define a posio inicial do texto,

glutBitmapCharacter(void *font, int character);


Define a fonte e o caracter a ser exibido.

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");

glColor3f (0, 1, 0);


glBegin (GL_LINES);
glVertex2f (w.getL(),0);
glVertex2f (w.getR(),0);
glEnd();

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:

void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))

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.

2.2.1 Exemplo: Utilizao do teclado no programa funes


Como exemplo vamos acrescentar no programa funes a possibilidade de alterarmos o domnio da
funo durante a execuo do programa. Assim podemos estabelecer que quando o usurio pressionar a
tecla D ou d, o programa interrompe e solicita as novas informaes sobre o domnio da funo.

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();
}

void teclado(unsigned char key, int x, int y)

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;
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
glutKeyboardFunc(teclado);
gluOrtho2D(L,R,B,T);
glutMainLoop();
}

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.

2.3.1 Interrupes a partir do mouse

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);
}

void teclado(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
f.dominio();
glutPostRedisplay();
break;
case 'W':
case 'w':
window_dimension();
glutPostRedisplay();
break;
}
}

void botao_mouse(int b,int state,int x, int y)


{
switch(b) {
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) {
window_dimension();
glutPostRedisplay();
}
break;
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
cout << "Boto esquerdo pressionado: x = " << x << " y = " << y << endl;
else
if (state == GLUT_UP)
cout << "Boto esquerdo solto: x = " << x << " y = " << y << endl;
break;

15
}
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
glutKeyboardFunc(teclado);
glutMouseFunc(botao_mouse);
gluOrtho2D(L,R,B,T);
glutMainLoop();
}

b) 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 botao_movimento_mouse(int x, int y) imprime a posio do
mouse enquanto mantemos um de seus botes pressionados.

.
.
.

void botao_movimento_mouse(int x, int y)


{
cout << "Botao+movimento x = " << x << " y = " << y << endl;
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
glutKeyboardFunc(teclado);
glutMouseFunc(botao_mouse);
glutMotionFunc(botao_movimento_mouse);
gluOrtho2D(L,R,B,T);
glutMainLoop();
}

c) 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 movimento_mouse(int x, int y) imprime a posio do mouse
quando movimentamos o mouse dentro da janela OpenGL.

16
.
.
.

void movimento_mouse(int x, int y)


{
cout << "Movimento x = " << x << " y = " << y << endl;
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
glutKeyboardFunc(teclado);
glutMouseFunc(botao_mouse);
glutMotionFunc(botao_movimento_mouse);
glutPassiveMotionFunc(movimento_mouse);
gluOrtho2D(L,R,B,T);
glutMainLoop();
}

2.3.2 Aplicaes: Realizando o 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 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

e identicamente para a coordenada y.

funcao.h

#include <cmath>

class funcao {

int pontos;
float xmin,xmax;

public:

funcao(int p = 300,float xm = -1,float xM = 1);

17
float get_xmin() { return xmin; }
float get_xmax() { return xmax; }

void set_dominio(float x,float y);

float f(float x) { return(sin(x)); }

void dominio();
void plota_funcao();
};

funcao.cpp
#include <gl\glut.h>
#include "funcao.h"
#include <iostream>
using namespace std;

funcao::funcao(int p ,float xm ,float xM) {


pontos = p;
xmin = xm;
xmax = xM;
}

void funcao::dominio()
{
cout << "xmin = ";
cin >> xmin;
cout << "xmax = ";
cin >> xmax;
}

void funcao::set_dominio(float xi,float xf)


{
xmin = xi;
xmax = xf;
}

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"

window::window(float Left,float Right,float Bottom,float Top)


{
L = Left;
R = Right;
B = Bottom;
T = Top;
}

static float converte(int p, float min, float max, int dim) {


float x;

x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}

void window::set_window (int xv_1,int yv_1,int xv_2,int yv_2,


int DIMX,int DIMY)
{
float xmin1,xmax1;
float ymin1,ymax1;

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;

const int DIMX = 400;


const int DIMY = 400;

window w(-5,5,-5,5);
funcao f(400,w.getL(),w.getR());

int mov = 0; /* Detecta o movimento do mouse */


int xv1,xv2,yv1,yv2; /* Domnio da nova janela */

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;
}
}

void botao_mouse(int b,int state,int x, int y)


{
switch(b) {
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) {
xv1 = x;
yv1 = y;
mov = 1;
}
else
if (state == GLUT_UP) {
xv2 = x;
yv2 = y;
mov = 0;
w.set_window(xv1,yv1,xv2,yv2,DIMX,DIMY);
f.set_dominio(w.getL(),w.getR());
glutPostRedisplay();
}
break;
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN)
cout << "Botao esquerdo pressionado em: x = " << x << " y
= " << y << endl;
else
if (state == GLUT_UP)
cout << "Botao esquerdo solto em: x = " << x << " y = "
<< y << endl;
break;
}
}

void botao_movimento_mouse(int x, int y)


{
xv2 = x;
yv2 = y;
glutPostRedisplay();

void window_size(int dimx,int dimy)


{
DIMX = dimx;
DIMY = dimy;
}

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();
}

2.3.3 Aplicaes: Pilha

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);

float getL() { return(L); }


float getR() { return(R); }
float getB() { return(B); }
float getT() { return(T); }

void set_window ();


void set_window (int xv_1,int yv_1,int xv_2,int yv_2,int
DIMX,int DIMY) ;
void set_window (window& a);
void plota_retangulo(int xv0,int yv0,int xv1,int yv1,int
DIMX,int DIMY);

23
};

#endif

window.cpp
#include <gl\glut.h>
#include <iostream>
using namespace std;
#include "window.h"

window::window(float Left,float Right,float Bottom,float Top)


{
L = Left;
R = Right;
B = Bottom;
T = Top;
}
window::window(window& a)
{
L = a.L;
R = a.R;
B = a.B;
T = a.T;
}

static float converte(int p, float min, float max, int dim) {


float x;

x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}

void window::set_window (int xv_1,int yv_1,int xv_2,int yv_2,


int DIMX,int DIMY)
{
float xmin1,xmax1;
float ymin1,ymax1;

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_window (window& a)


{
L = a.L;
R = a.R;
B = a.B;
T = a.T;
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);
}

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();
}

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;

int DIMX = 400;


int DIMY = 400;

window w(-5,5,-5,5);
funcao f(400,w.getL(),w.getR());

Stack P;

int mov = 0; /* Detecta o movimento do mouse */


int xv1,xv2,yv1,yv2; /* Domnio da nova janela */

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();
}

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_window();
glutPostRedisplay();
break;
}
}

void botao_mouse(int b,int state,int x, int y)


{
switch(b) {
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) {
xv1 = x;
yv1 = y;
mov = 1;
}
else
if (state == GLUT_UP) {
xv2 = x;
yv2 = y;
mov = 0;
if ((xv1 != xv2) && (yv1 != yv2)) {
P.push(w);
w.set_window(xv1,yv1,xv2,yv2,DIMX,DIMY);
f.set_dominio(w.getL(),w.getR());
glutPostRedisplay();
}
}
break;
case GLUT_LEFT_BUTTON:
if (state == GLUT_DOWN) {
cout << "Botao esquerdo pressionado em: x = " << x << " y
= " << y << endl;
if (!P.Empty()) {

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;
}
}

void botao_movimento_mouse(int x, int y)


{
xv2 = x;
yv2 = y;
glutPostRedisplay();
}

void window_size(int dimx,int dimy)


{
DIMX = dimx;
DIMY = dimy;
}

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();
}

Exerccio: Ajuste a funo void window::set_window (int xv_1,int yv_1,int


xv_2,int yv_2,int DIMX,int DIMY) de forma que o zoom seja aplicado corretamente
independente do ponto inicial ou final.

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();

GL_POINTS Pontos individuais.


GL_LINES Reta entre dois pontos.
GL_POLYGON Polgono convexo .
GL_TRIANGLES Tripla de vrtices interpretado como um tringulo.
GL_QUADS Conjunto de quatro vrtices interpretado como
quadriltero.
GL_LINE_STRIP Sequncia de retas.
GL_LINE_LOOP Idntico ao anterior, porm com uma reta unindo o
primeiro e ltimo vrtice.
GL_TRIANGLE_STRIP Lista de tringulos.
GL_TRAINGLE_FAN Lista de tringulos com o primeiro vrtice em
comum.
GL_QUAD_STRIP Lista de quadrilteros.

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;

int DIMX = 400;


int DIMY = 400;

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();
}

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_window();
glutPostRedisplay();
break;
case '+':
h.inc_particao();
glutPostRedisplay();
break;
case '-':
h.dec_particao();
glutPostRedisplay();
break;
}
}
.
.
.

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)

Estas so as equaes paramtricas da curva C e t denominado parmetro. Como exemplo de curvas


temos:

a) Circunferncia de centro na origem e raio 1:

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)

4.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.
curva.h
#include <cmath>

class curva {
int pontos;
float tmin,tmax;

public:
curva(int p = 300,float tm = 0,float tM = 1);

float get_tmin() { return tmin; }


float get_tmax() { return tmax; }

void set_dominio(float tm,float tM);

void c(float t,float *v);

void dominio();
void plota_curva();
};

curva.cpp
#include <gl\glut.h>
#include <cmath>
#include "curva.h"
#include <iostream>
using namespace std;

curva::curva(int p ,float tm ,float tM) {


pontos = p;
tmin = tm;
tmax = tM;
}

32
void curva::dominio()
{
cout << "tmin = ";
cin >> tmin;
cout << "tmax = ";
cin >> tmax;
}

void curva::set_dominio(float ti,float tf)


{
tmin = ti;
tmax = tf;
}

void::curva::c(float t,float *v)


{
v[0] = cos(t);
v[1] = sin(t);
// v[0] = sin(3*t);
// v[1] = sin(4*t);
// v[0] = (t+sin(t));
// v[1] = (t+cos(t));
// v[0] = t+2*sin(2*t);
// v[1] = t+2*cos(5*t);
// v[0] = cos(t)-cos(80*t)*sin(t);
// v[1] = 2*sin(t)-sin(80*t);
// v[0] = 31 * cos(t) - 7 * cos(31.0/7 * t);
// v[1] = 31 * sin(t) - 7 * sin(31.0/7 * t);
// v[0] = cos(t) + 0.5 * cos(7*t) + 1/3.0 * sin(17*t);
// v[1] = sin(t) + 0.5 * sin(7*t) + 1/3.0 * cos(17*t);

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;

int DIMX = 400;


int DIMY = 400;

33
window w(-5,5,-5,5);
curva c(400,0,6.29);

Stack P;

int mov = 0; /* Detecta o movimento do mouse */


int xv1,xv2,yv1,yv2; /* Domnio da nova janela */

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();
}

void teclado(unsigned char key, int x, int y)


{
switch(key)
{
case 'D':
case 'd':
c.dominio();
glutPostRedisplay();
break;
case 'W':
case 'w':
w.set_window();
glutPostRedisplay();
break;
}
}

void botao_mouse(int b,int state,int x, int y)


{
switch(b) {
case GLUT_RIGHT_BUTTON:
if (state == GLUT_DOWN) {
xv1 = x;
yv1 = y;
mov = 1;
}
else
if (state == GLUT_UP) {
xv2 = x;

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;
}
}

void botao_movimento_mouse(int x, int y)


{
xv2 = x;
yv2 = y;
glutPostRedisplay();
}

void window_size(int dimx,int dimy)


{
DIMX = dimx;
DIMY = dimy;
}

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();
}

Exerccio

Como exerccio implemente:

1) x(t) = 3*t*t, y(t)=4*t*t*t (t assume qualquer valor real).

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.

4.3 Curvas na forma Polar


Para formar as coordenadas polares considere um ponto fixo O, denominado origem (ou polo) e um eixo
partindo de O, denominado eixo polar. A cada ponto P do plano podemos associar uma par de
coordenadas polares (r,theta) onde:

r: distncia orientada da origem ao ponto P.


theta: ngulo entre o eixo polar e o segmento OP.
.

As coordenadas polares podem ser relacionadas com as coordenadas retangulares (ou cartesianas) atravs
das expresses abaixo:

Como exemplo de curvas na forma polar temos:

a) Circunferncia de centro na origem e raio 1:

r = 1

b) Reta passando na origem com coeficiente angular m:

c) Circunferncia com centro em P(0, 0.5) e raio 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:

Em coordenadas cartesianas temos:

Substituindo r nas duas equaes obtemos:

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);
}

void::curva::c(float t,float *v)


{
v[0] = r(t) * cos(t);
v[1] = r(t) * sin(t);
}
.
.
.

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:

Na forma paramtrica a mesma curva representada 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.

5.2 Visualizao de Curvas Implcitas


Vamos implementar um programa que visualize curvas implcitas. Partindo por exemplo da equao:

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:

Assim a curva inicial desejada, ser a curva de nvel .


A estratgia para obter esta curva ser a seguinte:
- Vamos estabelecer um domnio 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 ,


por exemplo.

- A cada trs pontos, definimos um tringulo como na figura abaixo.

- Para cada ponto calculamos .

- 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.

- Se V1 * V3 < 0, ento a funo se anula em um ponto entre V1 e V3.

39
- Se V2 * V3 < 0, ento a funo se anula em um ponto entre V2 e V3.

- Se V1 = 0, ento a funo se anula exatamente sobre o vrtice V1.

- Se V2 = 0, ento a funo se anula exatamente sobre o vrtice V2.

- Se V3 = 0, ento a funo se anula exatamente sobre o vrtice V3.

- Considerando que exatamente duas das condies acima se verificaram simultaneamente,


aproximamos a curva nesse tringulo por um segmento de reta unindo os dois pontos obtidos.

5.3 Programa Curva Implcita


O programa mantm a mesma estrutura do programa curva paramtrica, alterando a classe curva,
conforme abaixo.

curva_implicita.h
#include <cmath>

class curva_implicita {

int pontos;
float xmin,xmax,ymin,ymax;

public:

curva_implicita(int p = 10,float xm = 0,float xM = 1,float ym =


0,float yM = 1);

void set_dominio(float xm,float xM,float ym,float yM);

void calcula_curva(float* xf,float* yf);


float f(float x,float y);

void dominio();
void plota_curva();
};

curva_implicita.cpp
#include <gl\glut.h>
#include <cmath>
#include "curva_implicita.h"
#include <iostream>
using namespace std;

curva_implicita::curva_implicita(int p ,float xm ,float xM,


float ym,float yM) {
pontos = p;
xmin = xm; xmax = xM;
ymin = ym; ymax = yM;
}

void curva_implicita::dominio()
{
cout << "xmin = ";
cin >> xmin;
cout << "xmax = ";
cin >> xmax;

40
cout << "ymin = ";
cin >> ymin;
cout << "ymax = ";
cin >> ymax;
}

void curva_implicita::set_dominio(float xi,float xf,float yi,float yf)


{
xmin = xi; xmax = xf;
ymin = yi; ymax = yf;
}

float curva_implicita::f(float x,float y)


{
return x*x-y*y-1.3;
// return x*x+y*y-1;
}

void curva_implicita::calcula_curva(float* xf,float* yf)


{
int j;
int i = 0;
float t;
float x[3],y[3],s[3];

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]);

if ((s[0] * s[1]) < 0) {


t = -s[0]/(s[1]-s[0]);
x[i] = xf[0] + t * (xf[1]-xf[0]);
y[i] = yf[0];
i++;
}
if ((s[0] * s[2]) < 0) {
t = -s[0]/(s[2]-s[0]);
x[i] = xf[0] ;
y[i] = yf[0] + t * (yf[2]-yf[0]);
i++;
}
if ((s[1] * s[2]) < 0) {
t = -s[1]/(s[2]-s[1]);
x[i] = xf[1] + t * (xf[2]-xf[1]);
y[i] = yf[1] + t * (yf[2]-yf[1]);
i++;
}

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:

As coordenadas dos vrtices deste cubo so:

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);

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]:

1. Monte o trip e aponte a camera para a cena desejada (viewing transformation)


2. Prepare a cena a ser fotografada na posio desejada (modeling transformation).
3. Escolhas a lente certa para a cmera e ajuste o zoom. (projection transformation).
4. Defina os limites da cena que estaro na foto final (viewport transformation).

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).

De forma esquemtica podemos estabelecer:

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.

1.3 - Comandos de Auxlio


Antes de iniciar a descrio do mecanismo das transformaes acima, apresentaremos um conjunto de
comandos de carter geral. Os comandos a seguir sero teis durante todas as etapas do processo de
modelagem, visualizao e Projeo.

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.

GlLoadMatrix(const TYPE *M);

Quando voc deseja especificar uma matriz M particular para ser a matriz corrente, utilize o
glLoadMatrix(M).

GlMultMatrix(const TYPE *M);

Este comando multiplica a matriz definida por

pela matriz corrente.

1.4- Exemplo: cubo unitrio


Antes de detalhar as transformaes principais, vamos apresentar um programa exemplo que visualiza o
mesmo cubo do exemplo anterior, porem utilizando as transformaes do OpenGL.

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;

float theta = 45.0;


float phi = 135.0;
float gama = 0.0;

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cube");
glutDisplayFunc(redesenha);
inicia_config();
glutMainLoop();
}

1.5 - Transformaes de Modelagem e Visualizao


Existem trs tipos de comandos para transformaes de modelagem: glTranslate(), glRotate() e
glScale(). Vamos descrever abaixo cada uma dessas funes.

1.5.1- Translao

void glTranslatef(float x, float y, float z);

Este comando multiplica a matriz corrente por uma matriz que translada o objeto conforme o vetor .

1.5.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,

na direo do eixo dado pelo vetor .

8
1.5.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.

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();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
9
glutCreateWindow("Triangulo");
glutDisplayFunc(display);
glutMainLoop();
}

1.6- 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 :

glOrtho(double left, double right, double bottom, double top,


double near, double far);

1.7- ngulos de Euler


Um sistema de referncia que ir nos auxiliar na montagem do ambiente 3D so ao ngulos de Euler. Os
ngulos de Euler so definidos como trs sucessivos ngulos de rotao atravs do qual definiremos um novo
sistema de coordenadas partindo das coordenadas cartesianas.
No Opengl o sistema de coordenadas est posicionado conforme o desenho abaixo, onde o eixo x est na
posio horizontal, o eixo y na posio vertical e o eixo z est apontando para fora da tela do computador.

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.

Estes trs ngulos definem os ngulos de Euler.

1.8 - Criando um Ambiente de Visualizao 3D


Vamos montar um ambiente para visualizao tri-dimensional, atravs do qual poderemos visualizar nossos
objetos 3D.

1.8.1- Mdulo Bsico de Visualizao

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);
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Cubo 3D");
glutDisplayFunc(display);
inicia_config();
glutMainLoop();
}

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);
}

void botao_mouse(int b,int state,int x, int y)


{

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;
}
}

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 main(int argc, char **argv)


{
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);
glutMainLoop();
}

1.9 Comando glLookAt


O comando glLookAt uma alternativa para controlar definir a visualizao por trs parmetros:

1) A posio do observador (ox,oy,oz).


2) ,A direo em que o observador est olhando (dx,dy,dz).
3) A posio da camera (px,py,pz).

Assim a sintaxe do comando glLookAt(ox,oy,oz, dx,dy,dz, px,py,pz). Podemos criar


interessantes efeitos, movimentando o observador sobre uma curva paramtrica, por exemplo, ou
movimentando a fonte de iluminao ao mesmo tempo, etc.

14
1.10 Visualizao de grfico de funes

A seguir apresentamos um programa exemplo para visualizao de grficos de funes .O


programa est dividido em dois mdulos: main.cpp e funcao.cpp.

Main.cpp
#include <gl\glut.h>
#include "funcao.h"

float theta = 135;


float phi = 45;
float gamma = 90;
float scale = 1.0;
int xb,xm,yb,ym;
funcao f;

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;
}
}

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();
xb = xm;
yb = ym;
redesenha();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("3D");
glutDisplayFunc(redesenha);
glutKeyboardFunc(keyboard);
glutMouseFunc(botao_mouse);
16
glutMotionFunc(mov_mouse);
inicia_config();
glutMainLoop();
}

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 ;
}

float f(float x,float y) {


return(x*x-y*y);
}

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;

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;
}
}

17
2- ILUMINAO
2.1 Introduo
Para adicionar iluminao so necessrias quatro etapas bsicas:

1) Definir o vetor normal a cada vrtice de seu modelo;


2) Definir as fontes de luz (posio, cor, direo, etc.);
3) Definir um modelo de iluminao (nvel da iluminao global e posio do observador)
4) Definir as propriedades do material de cada objeto.

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"

float theta = 135;


float phi = 45;
float gamma = 90;
float scale = 1.0;
int xb,xm,yb,ym;
iluminacao I;

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();
}

void keyboard(unsigned char key, int x, int y)


{
20
switch(key)
{
case 'S':
scale += 0.2;
inicia_config();
redesenha();
break;
case 's':
scale -= 0.2;
inicia_config();
redesenha();
break;
}
}

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();
xb = xm;
yb = ym;
redesenha();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("3D");
glutDisplayFunc(redesenha);
glutKeyboardFunc(keyboard);
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
inicia_config();
glutMainLoop();
}

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 :

void glLightfv(GLenum luz, GLenum iluminao, GLenum param);

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).

Os parmetros da iluminao so:

Parmetro Valor default Significado


GL_AMBIENT (0.0, 0.0, 0.0, 1.0) Intensidade da luz
ambiente
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) Intensidade da luz difusa
GL_SPECULAR (1.0, 1.0, 1.0, 1.0) Intensidade da luz
especular
GL_POSITION (0.0, 0.0, 1.0, 0.0) posio da luz
GL_SPOT_DIRECTION (0.0, 0.0, -1.0) direo da luz
GL_SPOT_EXPONENT 0.0 Parmetro que controla a
distribuio da luz.
GL_SPOT_CUTOFF 180.0 ngulo de abertura da luz
GL_CONSTANT_ATTENUATION 1.0
GL_LINEAR_ATTENUATION 0.0
GL_QUADRATIC_ATTENUATION 0.0

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:

GLfloat luz_ambiente[4] = { 0.5, 0.2, 0.3, 1.0 };

glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambiente);

Nesse caso temos R = 0.5, G = 0.2, B = 0.3 e A = 1.0.

22
2.2.2 Posio

A posio da luz pode ser de dois tipos bsicos:

- 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:

GLfloat luz_posicao[4] = { 1.0, 1.0, 1.0, 0.0 };


glLightfv(GL_LIGHT0, GL_POSITION, luz_posicao);

- Posicional : Se o ltimo valor do vetor luz_posicao[] for diferente de zero, a luz posicional e
sua localizao definida pelo vetor:

GLfloat luz_posicao[4]={x , y, z, 1.0};

2.3 Selecionando o Modelo de Iluminao

2.3.1- Luz Ambiente Global

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:

GLfloat luz_ambiente_modelo[4] = { 0.2, 0.2, 0.2, 1.0 };

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.

2.3.2 Posio do observador local ou no infinito

A localizao do observador pode ou no influenciar na iluminao. O default o observador no infinito. Para


mudar a configurao, considerando-se a iluminao conforme o observador utilize:

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

2.3.3 Iluminao nos dois lados da face

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);

2.3.4 Habilitando a iluminao

No OpenGL voc precisa explicitamente habilitar a iluminao. Para isso utilize o comando:

glEnable(GL_LIGHTING);

Para desabilitar basta utilizar o comando:

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:

void glMaterialfv(GLenum face, GLenum iluminacao, TYPE param);

O parmetro face pode ser: GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK. Os parmetros da


iluminao so:

Parmetro Valor default Significado


GL_AMBIENT (0.2, 0.2, 0.2, 1.0) Cor da luz ambiente do
material
GL_DIFFUSE (0.8, 0.8, 0.8, 1.0) Cor da luz difusa do
material
GL_SPECULAR (0.0, 0.0, 0.0, 1.0) Especular cor do material
GL_SHININESS 0.0 ndice especular
GL_EMISSION (0.0, 0.0, 0.0, 1.0) Cor de emisso do
material

Como exemplo, inserimos o modulo de iluminacao no programa funcao3D.

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;

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_LINES);
normal(v,x,y);
glVertex3f(x ,y ,f(x ,y) );
glVertex3f(x+v[0]/n,y+v[1]/n,f(x ,y)+v[2]/n);

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:

Uma superfcie parametrizada uma aplicao onde D algum domnio em . A


superfcie S correspondente funo a imagem . A superfcie parametrizada depende de dois
parmetros (u, v).
A visualizao de superfcies paramtricas pode ser feita com pequenas alteraes no cdigo anterior que
visualiza o grfico de uma funo. O cdigo abaixo ilustra um exemplo, modificando o cdigo anterior. A
classe funcao foi substituda pela classe superfcie.
superfcie.h
#include <cmath>
class superficie {
float umin,umax,vmin,vmax;
int points;
public:
superficie(float um = 0,float uM = 6.28,float vm = -8,float vM =
8,int p = 30) {
umin = um;
vmin = vm;
umax = uM;
vmax = vM;
points = p ;
}

void s(float *r,float u,float v) {


r[0] = cos(u) * (0.5+sin(v)/5);
r[1] = sin(u) * (0.5+sin(v)/5);
r[2] = v/5;
}
void normal(float *v,float x,float y);
void plota_superficie_01();
void plota_superficie_02();
void plota_normal();
};
28
superfcie.cpp
#include <gl/glut.h>
#include "superficie.h"

void superficie::plota_superficie_01() {
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
float r[3],n[3];

glColor3f (1.0f, 1.0f, 1.0f);


u = umin;
for(int i=0;i<points;i++) {
v = vmin;
for(int j=0;j<points;j++){
glBegin(GL_LINE_LOOP);
s(r,u,v);
glVertex3f(r[0],r[1],r[2]);

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];

glColor3f (1.0f, 1.0f, 1.0f);


u = umin;
for(int i=0;i<points;i++) {
v = vmin;
for(int j=0;j<points;j++){
glBegin(GL_QUADS);
normal(n,u,v);
s(r,u,v);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(r[0],r[1],r[2]);
normal(n,u+du,v);
s(r,u+du,v);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(r[0],r[1],r[2]);
normal(n,u+du,v+dv);
s(r,u+du,v+dv);
glNormal3f(n[0],n[1],n[2]);
glVertex3f(r[0],r[1],r[2]);
normal(n,u,v+dv);
s(r,u,v+dv);
29
glNormal3f(n[0],n[1],n[2]);
glVertex3f(r[0],r[1],r[2]);
glEnd();
v += dv;
}
u += du;
}
}
void superficie::normal(float *n,float u,float v) {
float v1[3];
float v2[3];
float norma;

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];

n[0] = v1[1] * v2[2] - v1[2] * v2[1];


n[1] = -v1[0] * v2[2] + v1[2] * v2[0];
n[2] = v1[0] * v2[1] - v1[1] * v2[0];
norma = 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;
}

void superficie::plota_normal() {
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;

float r[3],n[3];

glColor3f (1.0f, 1.0f, 1.0f);


u = umin;
for(int i=0;i<points;i++) {
v = vmin;
for(int j=0;j<points;j++){
glBegin(GL_LINES);
normal(n,u,v);
s(r,u,v);
glVertex3f(r[0] ,r[1] ,r[2] );
glVertex3f(r[0]+n[0],r[1]+n[1],r[2]+n[2]);
normal(n,u+du,v);
30
s(r,u+du,v);
glVertex3f(r[0] ,r[1] ,r[2] );
glVertex3f(r[0]+n[0],r[1]+n[1],r[2]+n[2]);
normal(n,u+du,v+dv);
s(r,u+du,v+dv);
glVertex3f(r[0] ,r[1] ,r[2] );
glVertex3f(r[0]+n[0],r[1]+n[1],r[2]+n[2]);
normal(n,u,v+dv);
s(r,u,v+dv);
glVertex3f(r[0] ,r[1] ,r[2] );
glVertex3f(r[0]+n[0],r[1]+n[1],r[2]+n[2]);
glEnd();
v += dv;
}
u += du;
}
}

Exerccios
1) Utilizando o programa anterior, visualize as seguintes superfcies e identifique-as:

a) b) c) d)

e) f) g)

2) Visualize os vetores normais sobre a superfcie. Observe o exemplo da letra f).

31
4- SUPERFCIES IMPLCITAS
4.1 Introduo
Na seo de curva implcita, vimos que na forma implcita uma curva representada pela equao:

Para superfcies estamos buscando o conjunto de pontos que satisfaz a 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.

4.2 Visualizao de Superfcies Implcitas


Para implementar a visualizao de superfcies implcitas estabelecemos os seguintes passos:
- Vamos estabelecer um domnio no espao como partida (a priori no
sabemos se existem ou no pontos da superfcie nesse domnio).

- Em seguida discretizamos este domnio, determinando um grid 3D de 10x10x10 pontos


, por exemplo.

- 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 ponto calculamos .

- Para cada cubo, analisamos cada um dos seus 6 tetraedros.

- 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.

- Se S1 * S4 < 0, ento a funo se anula em um ponto entre V1 e V4.

- Se S2 * S3 < 0, ento a funo se anula em um ponto entre V2 e V3.

- Se S2 * S4 < 0, ento a funo se anula em um ponto entre V2 e V4.

- Se S3 * S4 < 0, ento a funo se anula em um ponto entre V3 e V4.

- Se S1 = 0, ento a funo se anula exatamente sobre o vrtice V1.

- Se S2 = 0, ento a funo se anula exatamente sobre o vrtice V2.

- Se S3 = 0, ento a funo se anula exatamente sobre o vrtice V3.

- Se S4 = 0, ento a funo se anula exatamente sobre o vrtice V4.

- 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"

float theta = 135;


float phi = 45;
float gamma = 90;
float scale = 1.0;
int xb,xm,yb,ym;
implicito S(-2,2,-2,2,-2,2,5);

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();
}

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;
}
}

void botao_mouse(int b,int state,int x, int y)


35
{
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();
xb = xm;
yb = ym;
redesenha();
}

void main(int argc, char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("3D");
glutDisplayFunc(redesenha);
glutKeyboardFunc(keyboard);
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
inicia_config();
glutMainLoop();
}

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;
}

float f(float x,float y,float z);


void normal(float* v, float x,float y,float z);
void tetraedro(float* x,float* y,float* z,float* w);
void plota_superficie();

};

implcito.cpp
#include <gl/glut.h>
#include <cmath>
#include "implicito.h"

float implicito::f(float x,float y,float z) {


return(x*x+cos(x)*y*y-z*y-1);
}

void implicito::normal(float* v, float x,float y,float z) {


v[0] = 2*x-sin(x)*y*y;
v[1] = 2*y*cos(x)-z;
v[2] = -y;
}

void implicito::tetraedro(float *v0,float *v1,float *v2,float *v3)


{
#define TETRA 1
glColor3f(1,0,0);
int i;
int n = 0;
float t,p[4][3];
float w0,w1,w2,w3;

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 ;

v[4][0] = x ; v[5][0] = x+dx; v[6][0] = x ;


v[7][0] = x+dx;
v[4][1] = y ; v[5][1] = y ; v[6][1] = y+dy;
v[7][1] = y+dy;
v[4][2] = z+dz; v[5][2] = z+dz; v[6][2] = z+dz;
v[7][2] = z+dz;

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.

Em seguida vamos apresentar os comandos essenciais para utilizar uma textura.

5.2 Parmetros Bsicos


Etapa 1: Definir a textura 2D. O comando glTexImage2D o comando principal.

void glTexImage2D(GLenum target,


GLint level,
GLint internalFormat,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid *pixels);

O comando glGenTextures serve apenas para retornar um inteiro ainda no usado para nomear uma
textura. O inteiro retornado na varivel textureNames.

void glGenTextures(GLsizei n, GLuint *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:

1) void glTexParameteri(GLenum target, GLenum pname, GLint param);


Parmetros:

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);

2) void glTexEnv{if}(GLenum target, GLenum pname, TYPEparam);

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.

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);


Substitui a cor pela cor da textura.

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);


Faz uma mdia ponderada entra a cor atual pela cor da textura.

Etapa 3: Para habilitar a textura, temos os comandos abaixo:

Habilita o uso de textura:


glEnable(GL_TEXTURE_2D);

Define qual textura deve ser aplicada:


glBindTexture(GL_TEXTURE_2D, texName);

Etapa 4: Define as coordenadas da textura sobre cada face.

A textura representada pelas coordenadas de textura:


glTexCoord2f(0.0, 0.0);
glTexCoord2f(0.0, 1.0);
glTexCoord2f(1.0, 1.0);
glTexCoord2f(1.0, 0.0);

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:

glTexCoord2f( i/10.0, j /10.0);


glTexCoord2f( i/10.0, (j+1)/10.0);
glTexCoord2f((i+1)/10.0, (j+1)/10,0);
glTexCoord2f((i+1)/10.0, j /10.0);

5.3 Aplicao em Superfcies Paramtricas


Textura.h
#include <gl/glut.h>

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);

imagem = new unsigned char[dimx*dimy*3];

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;

parametrico p(0,4.28, 1, 3.2, 10);


Textura T("lena.pgm");

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;
}
}
}

void botao_movimento(int x,int y)


{
theta = theta + (xi - x);
phi = phi + (yi - y);
xi = x;
yi = y;
inicia();
glutPostRedisplay();
}

void teclado(unsigned char b,int x,int y)


{
if (b == 'r')
m = (m+1)%2;
}
void main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(512,512);
glutCreateWindow("Cubo");
46
glutDisplayFunc(display);
inicia();
T.init();

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 normal(float u,float v,float *n);


void p (float u,float v,float *f);

void draw_parametrico();
void draw_parametrico_textura();
void draw_parametrico_textura1();
};

parametrico.cpp

#include <gl/glut.h>
#include <cmath>
#include "parametrico.h"

void parametrico::normal(float u,float v,float *n) {


float d1[3];
float d2[3];

float p1[3];
float p2[3];
float p3[3];

float du = (umax - umin) / pontos;


float dv = (vmax - vmin) / pontos;

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::p (float u,float v,float *f) {


f[0] = u;
f[1] = v;
f[2] = u*u-v*v;

// f[0] = (2+0.5*cos(v)) * cos(u);


// f[1] = (2+0.5*cos(v)) * sin(u);
// f[2] = 0.5*sin(v);
// f[0] = cos(u) * sin(v);
// f[1] = sin(u) * sin(v);
// f[2] = cos(v);

// f[0] = cos(u) + v * cos(u/2) * cos(u);


// f[1] = sin(u) + v * cos(u/2) * sin(u);
// f[2] = v * sin(u/2);
}

void parametrico::draw_parametrico() {

float u,v;
float du,dv;
float f[3];
float n[3];

du = (umax - umin) / pontos;


dv = (vmax - vmin) / pontos;

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];

du = (umax - umin) / pontos;


dv = (vmax - vmin) / pontos;

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::insert(float x,float y) {


p[++n][0] = x;
p[n][1] = y;
}

void bezier::remove(float x,float y) {


}

float bezier::bernstein(int n,int i,float t)


{
float ti = 1;
float ti1 = 1;
float s = 1;

for (int j = 0;j < i ; j++) {


s *= (n-j)/(float)(i-j);
ti *= t;
}
for(int j = 0; j < n-i; j++) {
ti1 *= (1-t);
}
return(s * ti * ti1);
}

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();
}

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));
52
}

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 insert(float x,float y);


void remove(float x,float y);

float bernstein(int n,int i,float t);


void draw_bezier();

float casteljau(float t,int r,int i,int j);


void draw_casteljau();

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();
}

void botao(int b,int state,int x,int y)


{
if (b == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
xi = x;
yi = y;
}
}
if (b == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN) {
float xb = -5 + x/400.0 * 10;
float yb = -5 + (400-y)/400.0 * 10;
C.insert(xb,yb);
glutPostRedisplay();
}
}
}

void botao_movimento(int x,int y)


{
theta = theta + (xi - x);
phi = phi + (yi - y);
xi = x;
yi = y;
inicia();
54
glutPostRedisplay();
}

void main(int argc,char **argv)


{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutCreateWindow("Bezier");
glutDisplayFunc(display);
inicia();
glutMouseFunc(botao);
glutMotionFunc(botao_movimento);
glutMainLoop();
}

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 insert(float x,float y);


void insert(float x,float y,float z,int i,int j);

void remove(float x,float y);

float bernstein(int n,int i,float t);


void draw_bezier();
void draw_sup_bezier();

float casteljau(float t,int r,int i,int j);


void draw_casteljau();

void draw_poligono();
void draw_poliedro();

void draw_method_casteljau();
};

55
#include <gl/glut.h>
#include "bezier.h"

void bezier::insert(float x,float y) {


p[++n][0] = x;
p[n][1] = y;
}

void bezier::insert(float x,float y,float z,int i,int j) {


S[i][j][0] = x;
S[i][j][1] = y;
S[i][j][2] = z;
}

void bezier::remove(float x,float y) {


}

float bezier::bernstein(int n,int i,float t)


{
float ti = 1;
float ti1 = 1;
float s = 1;

for (int j = 0;j < i ; j++) {


s *= (n-j)/(float)(i-j);
ti *= t;
}
for(int j = 0; j < n-i; j++) {
ti1 *= (1-t);
}
return(s * ti * ti1);
}

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();
}

void botao(int b,int state,int x,int y)


{
if (b == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
xi = x;
yi = y;
}
}
if (b == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN) {
float xb = -5 + x/400.0 * 10;
float yb = -5 + (400-y)/400.0 * 10;
// C.insert(xb,yb);
glutPostRedisplay();
}
60
}
}

void botao_movimento(int x,int y)


{
theta = theta + (xi - x);
phi = phi + (yi - y);
xi = x;
yi = y;
inicia();
glutPostRedisplay();
}

void main(int argc,char **argv)


{
S.insert(1,0,1,0,0);
S.insert(2,-1,2,1,0);
S.insert(3,0,2,2,0);
S.insert(4,0,1,3,0);

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

S-ar putea să vă placă și