Formato PDF - Departamento de Matemática - PUC-Rio

Propaganda
1
Capítulo I – Introdução a Linguagem JAVA ____________________________3
1. Estrutura Básica de um Programa em Java ______________________________ 3
1.1 - Primeiro Programa ______________________________________________________ 3
1.2 - Variáveis _____________________________________________________________ 4
1.3 - Operadores ___________________________________________________________ 5
1.4 - Constantes ____________________________________________________________ 6
1.5 - Comentários___________________________________________________________ 7
1.6 - Fluxo de Controle_______________________________________________________ 7
Comando if () {} __________________________________________________________ 8
Comando for( ; ; ) {} _______________________________________________________ 9
O método de Simpson ____________________________________________________ 11
Comando break e continue ________________________________________________ 13
2 - VETORES E MATRIZES _____________________________________________ 14
2.1 - Vetores______________________________________________________________
2.2 - Declaração ___________________________________________________________
2.3 - Inicializando vetores____________________________________________________
2.4 – Exemplo: Método de Ordenação__________________________________________
2.5 - Matrizes _____________________________________________________________
2.6 – Exemplo: Produto de uma matriz por um vetor_______________________________
14
16
16
16
18
18
3 – OBJETOS E CLASSES _____________________________________________ 19
3.1 – Membros da Classe ___________________________________________________
3.2 – Construtores _________________________________________________________
3.3 – Métodos_____________________________________________________________
3.3.1 - Introdução ________________________________________________________
3.3.2 – Modificadores do Método____________________________________________
3.3.3 – Campos Static ____________________________________________________
3.3.4 – Exemplo de uma Classe Vetor________________________________________
19
21
23
23
24
24
27
2
Capítulo I – Introdução a Linguagem JAVA
Java é uma linguagem de programação orientada a objeto com grande popularidade entre os
usuários de internet. Uma das razões de sua popularidade na web é que o Java gera applets
para a web. Um applet é um aplicativo para ser executado nas páginas web. Porém o Java
também é amplamente utilizado em outros domínios além da internet principalmente por
sua característica multi-plataforma e no aspecto segurança.
1. Estrutura Básica de um Programa em Java
A linguagem Java tem uma estrutura muito semelhante a C++ e por esta razão os usuários
que aprendem Java como primeira linguagem de programação não tem dificuldades de
futuramente programar em C++ também.
1.1 - Primeiro Programa
Em Java os programas são escritos utilizando-se classes. Inicialmente vamos aprender os
comandos básicos do Java e na seção 4 discutiremos o funcionamento das classes e a
orientação a objeto. Como primeiro exemplo, consideremos o programa:
HelloWorld.java
class Hello {
public static void main(String[] args) {
System.out.println("Ola");
}
}
Para compilar execute:
javac HelloWorld.java
O resultado será a geração do arquivo:
Hello.class
Observe que o nome do arquivo gerado tem extensão .class e o nome corresponde ao
nome da classe (Hello.class), e não ao original nome do arquivo compilado
(HelloWorld.java)
3
E finalmente para executar:
java Hello
O resultado será a exibição da mensagem:
“Hello”.
Possíveis problemas:
1) Se na compilação ocorrer o seguinte erro:
'javac' is not recognized as an internal or external command,
operable program or batch file.
solução: verifique se o java está instalado e acrescente no path do windows o
diretório C:\jdk5.0\bin. Para alterar o path vá para: Control Panel-> System ->
Advanced -> Environment Variables. No primeiro quadro, User variables for ...
edit a variável path e acrescente o diretório do java.
2) Se na compilação ocorrer o seguinte erro:
Exception in thread "main" java.lang.NoClassDefFoundError:
HelloWorldApp
solução: vá para: Control Panel-> System -> Advanced -> Environment Variables.
No primeiro quadro, User variables for ... pressione new e acrescente:
variable name: CLASSPATH
variable value: .
(obs:apenas um ponto)
1.2 - Variáveis
O programa a seguir exibe como é feita a declaração de algumas variáveis e sua utilização.
public class Input {
public static void main(String[] args) {
int
n = 1;
float a = 2.3e10f;
double b = 34.5e200;
}
System.out.println("n = " + n + " a = " + a + " b = " + b);
}
4
As primeiras linhas declaram as variáveis e os tipos:
int
Tipo da variável
n;
Nome da variável
Em seguda atribuimos o valor 1 para a variável:
n = 1;
O Java tem diferentes tipos de variáveis:
boolean
char
byte
short
int
long
float
double
TRUE ou FALSE
16-bit Unicode 2.1 character
8-bit inteiro (signed)
16-bit inteiro (signed)
32-bit inteiro (signed)
64-bit inteiro (signed)
32-bit floating-point
64-bit floating point
1.3 - Operadores
Os operadores aritméticos sobre as variáveis são os seguintes:
+ Soma
*
/
%
Subtração
Multiplicação
Divisão
Resto da divisão
A operação de incremento de uma unidade tem também um formato reduzido, ou seja, o
comando:
i = i + 1;
E é freqüentemente representado por:
i++;
Da mesma forma i = i-1; pode ser escrito como i--;
Como exemplo dos operadores, o programa abaixo calcula as raízes reais de um polinômio
de segundo grau:
5
Raizes.java
class Raizes {
public static void main(String[] args) {
double a,b,c;
double x1,x2;
a = 1;
b = -5;
c = 6;
x1 = (-b + Math.sqrt(b*b - 4*a*c)) / (2 * a);
x2 = (-b - Math.sqrt(b*b - 4*a*c)) / (2 * a);
System.out.println("x1 = " + x1 + "
x2 = " + x2);
}
}
1.4 - Constantes
Uma constante é um valor constante que é definido no programa de forma que não será
alterado durante toda a execução. Assim por exemplo, no programa anterior não
pretendemos alterar os valores de a, b e c, e gostaríamos que estes valores ficassem
registrados por alguma referência que pudesse auxiliar futuramente seu significado. Para
declararmos uma constante utilizamos o prefixo final, como no exemplo:
Raizes.java
class Raizes {
public static void main(String[] args) {
final double a = 1;
final double b = -5;
final double c = 6;
double x1,x2;
x1 = (-b + Math.sqrt(b*b - 4*a*c)) / (2 * a);
x2 = (-b - Math.sqrt(b*b - 4*a*c)) / (2 * a);
System.out.println("x1 = " + x1 + "
x2 = " + x2);
}
}
6
1.5 - Comentários
É possível introduzir comentários dentro de um programa em Java, bastando para isso
colocá-los nos seguintes formatos:
/* Comentario pode prosseguir por varias
linhas e so termina ao encontar a marca de fim de
comentario */
/** Normalmente usado no inicio das classes */
// Comentario somente até o final da linha
Observe o exemplo abaixo:
class Raizes {
/** Soluções reais da equação ax*x + b*x + c = 0
public static void main(String[] args) {
double a,b,c;
double x1,x2;
*/
a = 1;
// Valores arbitrarios para a,b, e c
b = -5;
c = 6;
x1 = (-b + Math.sqrt(b*b - 4*a*c)) / (2 * a);
x2 = (-b - Math.sqrt(b*b - 4*a*c)) / (2 * a);
System.out.println("x1 = " + x1 + "
x2 = " + x2);
}
}
1.6 - Fluxo de Controle
O comando principal de decisão é o if() { }. Os dois dos formatos mais utilizados de
laços são:
while() {}
for( ; ;) { }
7
Comando if () {}
Através deste comando o fluxo do programa pode ser desviado para executar ou não um
conjunto de comandos. Considere o exemplo abaixo:
class ExemploIf {
/** Testa se um numero e par ou impar */
public static void main(String[] args)
{
int i,n;
n = 7;
// Entre com n
i = n % 2;
if (i == 0) {
System.out.println("\n n e um numero par\n");
}
else {
System.out.println("\n n e um numero impar\n");
}
}
}
Neste exemplo a variável i armazena o resto da divisão de n por 2. Caso seja zero, então o
programa passa a execução do comando println("\n n e um numero par\n").
Se a condição falha, o comando else indica que o programa deve executar o comando
println("\n n e um numero impar\n"). Observe que o else é um comando
opcional. Caso você não o inclua, o programa segue para o próximo comando após o if.
Os testes utilizam os seguintes operadores relacionais:
<
>
<=
>=
==
!=
&&
!
||
Menor
Maior
Menor ou igual
Maior ou igual
Igual
Diferente
e
negação
ou
8
Comando for( ; ; ) {}
O for é um comando apropriado quando queremos executar um conjunto de operações um
número fixo de vezes, como no exemplo da seqüência de fibonacci:
Fibonacci2.java
class Fibonacci2 {
public static void main(String[] args) {
int n;
int lo = 1;
int hi = 1;
final int MAX = 10;
System.out.println("1: 1");
for(n = 2;n <= MAX; n++) {
System.out.println(n + ": " + hi);
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
9
O comando for é composto de três argumentos:
for( n=0
; n<= 10
; n++
Expressão de inicialização
Expressão de teste
Incremento
)
Expressão de inicialização
Inicializa a variável do laço. A inicialização é feita uma única vez quando o laço inicia.
Expressão de teste
Esta expressão testa (a cada vez que o conjunto de comandos no interior do for finaliza), se
o laço deve ser encerrado. Enquanto a expressão for verdadeira o laço é repetido. Para
realizar teste utilizamos os operadores relacionais.
Expressão de incremento
A cada repetição do laço, o terceiro argumento (n++) incrementa a variável n.
Exemplo: Métodos numéricos de integração (ponto a esquerda)
Como aplicação do comando for o exemplo abaixo ilustra a implementação do método do
ponto a esquerda. Podemos utilizar os métodos de integração para obter uma aproximação
para a expansão decimal de . Se calcularmos:
obteremos aproximações para
.
class Integral {
/** Integracao Numerica: Ponto a Esquerda */
public static void main(String[] args) {
int
i;
int
n;
double x,dx ;
double a,b ;
double soma;
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;
for(i=0; i < n; i++) {
soma = soma + Math.sqrt(1-x*x) * dx;
x = x + dx;
}
System.out.println("\nIntegral = "+ 2*soma);
}
10
Exemplo: Métodos numéricos de integração (Monte Carlo)
Neste método utilizamos um sorteio de pontos em uma certa região. O quociente do
número de pontos que são sorteados no interior pelo número total de pontos é uma
estimativa para a integral.
import java.util.*;
public class MonteCarlo {
public static void main(String[] args) {
Random rn = new Random();
double x,y,f;
long cont = 0;
final long points = 500000;
for (long i = 0; i < points; i++)
{
x = rn.nextDouble();
y = rn.nextDouble();
if ((x*x+y*y-1) < 0)
cont++;
}
f = 4.0*cont/points;
System.out.println("Pi = "+ String.valueOf(f)
}
}
Exemplo: Métodos numéricos de integração (Método de Simpson)
O método de Simpson refina o método do trapézio [Malta,Pesco,Lopes, Cálculo a uma
variável – Vol II].
public class Simpson {
public static void main(String[] args) {
int
i;
int
n;
double x,dx ;
double a,b ;
double soma;
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 = Math.sqrt(1-x*x);
for(i=1; i < n; i++) {
x = x + dx;
if (i % 2 == 0)
soma = soma + 2 * Math.sqrt(1-x*x);
11
else
soma = soma + 4 * Math.sqrt(1-x*x);
}
x = b;
soma = soma + Math.sqrt(1-x*x);
soma = soma * dx/3;
System.out.println("\nIntegral = "+ 2*soma);
System.out.println("\nErro = " + (2*soma-Math.PI));
}
}
Comando while() {}
Este segundo tipo de laço é adequado para situações onde não sabemos ao certo quantas
vezes o laço deve ser repetido. Neste exemplo, primeiro é feito o teste:
while (n < 10)
e somente em caso verdadeiro os comando dentro do while são executados. Assim se a
condição for falsa a primeira vez, em nenhum momento os comandos dentro do laço serão
executados. O exemplo abaixo ilustra a utilização do comando:
Exemplo: Método de Newton
O programa abaixo determina as raízes da função:
utilizando o método de Newton, ou seja, dada uma condição inicial x0, e um erro máximo,
a seqüência abaixo pode convergir para uma das raízes:
class Newton {
/** Metodo de Newton */
public static void main(String[] args) {
int
i = 0
;
double xn,x0,xn_1 ;
double erro
;
x0 = 2;
// Condicao inicial
erro = 0.0000001; // Erro maximo
xn
= x0;
xn_1 = xn + 2 * erro; // Garante a entrada no while
12
while (Math.abs(xn - xn_1) > erro) {
xn_1 = xn;
xn
= xn_1 - (xn_1 * xn_1 - 2) / (2 * xn_1);
i++;
System.out.println("\nx[" + i + "] =" + xn);
}
System.out.println("\n A raiz obtida: "+ xn + "\n");
}
}
Comando break e continue
Estes dois comando sservem para auxiliar na interrupção do laço, cumprindo diferentes
tarefas:
- O comando break; interrompe o laço (Qualquer dos formatos apresentados) e o
programa continua no primeiro comando após o laço. Exemplo:
Exemplobreak.java
class Exemplobreak {
public static void main(String[] args) {
int n = 0;
while (n < 10) {
System.out.println("n = " + n);
if (n > 3)
break;
n++;
}
System.out.println("Fim do programa \n");
}
}
O resultado deste programa será:
n =
n =
n =
n =
n =
Fim
0
1
2
3
4
do programa
- O comando continue; transfere a execução do programa para o teste do laço, que
pode ou não prosseguir caso a condição seja verdadeira ou falsa.
Exemplo: Método da Bisseção
13
O programa abaixo determina as solucoes da equacao:
Para isso utilizaremos o método da bisseção. No método da bisseção procuramos uma raiz
contida em certo intervalo [a,b] dado. A raiz existe desde que a função seja contínua e o
sinal da função troque de um extremo para outro (ou seja f(a) * f(b) < 0).
Bissecao.java
class Bissecao {
public static void main(String[] args) {
double a,b,c;
double fa,fb,fc;
final double erro = 0.0000001;
a = 0; // Entre com o extremo a
b = 2; // Entre com o extremo b
fa = a*a - 2;
fb = b*b - 2;
c=0;
if ((fa * fb) > 0) {
System.out.println("\nCondicao inicial nao contem raiz
!\n");
return;
}
while(Math.abs(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;
}
System.out.println("\n Raiz parcial = " + c);
}
System.out.println("\n\n Raiz obtida = " + c);
return;
}
}
2 - VETORES E MATRIZES
2.1 - Vetores
14
Quando você deseja representar uma coleção de dados semelhantes, pode ser muito
inconveniente utilizar um nome de variável diferente para cada dado.
Para ilustrar vamos considerar o seguinte exemplo: Montar um programa que armazena as
notas de 15 alunos e calcula a média obtida pela turma. As notas serão armazenadas em
uma variável do tipo float, porém ao invés de criarmos 15 variáveis, utilizamos uma
variável do tipo vetor, definida como abaixo:
float notas[15];
o programa completo seria:
public class notas {
public static void main(String[] args) {
int
i
;
float media
;
float soma = 0 ;
float[] notas = new float[5];
for(i=0;i < 15;i++) {
System.out.println(" Aluno " + (i+1)2 + ":");
notas[i] = TextIO.getlnFloat();;
}
for(i=0;i<15;i++)
soma = soma + notas[i];
media = soma / 15;
System.out.println("\n A media final foi: " + media);
}
}
Nós podemos melhorar o programa anterior, solicitando ao usuário o número de alunos da
turma e só então alocando o vetor de notas. Veja abaixo:
public class notas1 {
public static void main(String[] args) {
int
i,n
float media
float soma = 0
float[] notas
;
;
;
;
System.out.println("Numero de alunos:");
n = TextIO.getInt();
notas = new float[n];
for(i=0; i < notas.length ;i++) {
System.out.println(" Aluno " + (i+1) + ":");
notas[i] = TextIO.getlnFloat();;
15
}
for(i=0;i< notas.length;i++)
soma = soma + notas[i];
media = soma / notas.length;
}
System.out.println("\n A media final foi: " + media);
}
2.2 - Declaração
Um vetor é uma coleção de variáveis de certo tipo, alocadas seqüencialmente na memória.
Para Java um declaração de variável vetor do tipo:
int[] n = new int[5];
reserva o espaço de 5 variáveis do tipo inteira, onde cada variável pode ser referenciada
conforme abaixo:
n[0]
n[1] n[2] n[3]
n[4]
IMPORTANTE: Observe que a declaração anterior cria cinco variáveis, porém o primeiro
elemento é n[0]. A declaração 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 referenciá-lo:
n[3] = 29;
resulta em:
29
n[0]
n[1] n[2] n[3]
n[4]
2.3 - Inicializando vetores
Assim como é possível atribuir valores a uma variável na mesma linha da declaração, o
mesmo pode ser feito para vetores. Observe o exemplo abaixo:
int [] n = {23, 3, -7, 288, 14};
2.4 – Exemplo: Método de Ordenação
16
Como exemplo vamos apresentar um programa que ordena uma seqüência de 10 números
reais.
public class Bolha {
/* * * * * * * * * * * * * * * * * * * * * */
/* Metodo da Bolha (ordenacao de um vetor) */
/* * * * * * * * * * * * * * * * * * * * * */
public static void main(String[] args) {
int
i,n
;
int
flag;
double swap;
double[] x;
/* Entrada de Dados */
System.out.println("Numero de elementos:");
n = TextIO.getInt();
x = new double[n];
System.out.println("Entre com os numeros para ordenacao");
for(i=0;i<n;i++)
{
System.out.println("x[" + i + "]: ");
x[i] = TextIO.getDouble();
}
/* 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] ;
x[i]
= x[i+1];
x[i+1] = swap ;
flag
= 1
;
}
}
}
/* Imprime a sequencia de numeros ordenada */
System.out.println("Sequencia ordenada : ");
for(i=0; i<x.length; i++)
System.out.println(" " + x[i]);
}
}
17
2.5 - Matrizes
Para representar uma matriz 3x4 (3 linha e 4 colunas) de números reais utilizamos a
seguinte declaração:
float[][] A = new float[3][4];
Assim fica reservado um espaço de memória conforme a figura abaixo:
A[0][0]
A[1][0]
A[2][0]
A[0][1]
A[1][1]
A[2][1]
A[0][2]
A[1][2]
A[2][2]
A[0][3]
A[1][3]
A[2][3]
2.6 – Exemplo: Produto de uma matriz por um vetor
Vamos montar um programa que multiplica um vetor por uma matriz.
public class produto {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int
i,j;
double[][] A = {{ 1.0, 1.5, 2.1},
{ 3.4, 2.2, 9.1},
{-1.2, -3.4, 0.9}};
double[]
v = {2.0, 1.0, 0.5};
double[]
p = new double[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++) {
System.out.print("[");
for(j=0;j<3;j++)
System.out.print(" " + A[i][j]);
System.out.print(" ] ");
System.out.println(" [" + v[i] + "]");
}
for(i=0;i<3;i++)
System.out.println(" p[" + i + "] =" + p[i]);
}
}
18
3 – OBJETOS E CLASSES
3.1 – Membros da Classe
Uma classe tem dois tipos principais de membros:
1. Campos: correspondem aos dados, representados pelas variáveis da classe.
2. Métodos: contêm o código executável e define o comportamento dos objetos.
Vamos iniciar com um exemplo, definindo um círculo:
circulo.class
public class circulo {
public double raio;
public double centrox,centroy;
}
O programa abaixo utiliza a classe circulo:
main.class
public class main {
public static void main(String[] args) {
circulo A;
A = new circulo();
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo de Raio = " + A.raio);
System.out.println("Circulo e Centro = ( " + A.cx + " , " +
A.cy + " )");
}
}
19
Inicialização da classe
A declaração feita no programa main:
circulo A;
não cria o objeto círculo, apenas estabelece que a variável “A” será uma referência para um
objeto do tipo circulo. Somente com o comando:
A = new circulo();
foi criado o objeto círculo.
Modificadores da Classe
Na definição da classe podemos definir quatro modificadores da classe:
1) public: a classe tem acesso público
2) abstract: é uma classe incompleta, que possui abstract métodos que
necessitam ser implementados por alguma subclasse.
3) final: não pode seu um asubclasse.
4) strict floating point: strictfp tem todas as operações aritméticas em ponto
flutuante definidas dentro da classe.
Controle de Acesso aos Campos
Observe que todos os campos definidos na classe círculo possuem o prefixo public. Este
elemento define o controle de acesso ao campo, definindo assim se um dado campo da
classe pode ou não ser alterado por outra classe.
Existem quatro modificadores de acesso:
1) private: campos definidos private somente são acessíveis na própria classe.
2) public: são acessíveis por qualquer classe.
3) package: acessíveis em classe do mesmo pacote (será definido posteriormente).
4) protected: são acessíveis em subclasses, classes do mesmo pacote e na
própria classe.
Modificadores de Campo
Observe que todos os campos definidos na classe círculo possuem o prefixo public. Este
elemento define o controle de acesso ao campo, definindo assim se um dado campo da
classe pode ou não ser alterado por outra classe.
Além dos quatro modificadores de acesso, temos também modificadores de acesso:
1) static: o campo static é instanciado somente uma vez para todos os objetos da
classe.
2) final: não pode ser trocado após a inicialização.
3) transient.
4) volatile.
20
3.2 – Construtores
Quando um objeto é criado pelo comando new, seus campos são iniciados com
valores default. Muitas vezes gostaríamos de definir como os campos devem ser iniciados,
e possivelmente executar alguns comandos específicos da criação do objeto. Neste caso
utilizamos os construtores. Algumas características importantes do construtor:
1) Tem sempre o mesmo nome da classe
2) Pode ou não ter argumentos
3) Não retorna nenhum campo (ou seja, não possui return).
Exemplo 1 (Construtor sem parâmetros):
public class circulo {
public double raio;
public double cx,cy;
}
circulo() {
raio = 1.0;
cx = 0;
cy = 0;
}
public class main {
public static void main(String[] args) {
circulo A,B;
A = new circulo();
B = new circulo();
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo A de Raio = " + A.raio);
System.out.println("Circulo A de Centro = ( " + A.cx + " , "
+ A.cy + " )");
System.out.println("Circulo B de Raio = " + B.raio);
System.out.println("Circulo B de Centro = ( " + B.cx + " , "
+ B.cy + " )");
}
}
21
Exemplo 2 (com parâmetros):
public class circulo {
public double raio;
public double cx,cy;
circulo() {
raio = 1.0;
cx = 0;
cy = 0;
}
}
circulo(double r,double x,double y) {
raio = r;
cx = x;
cy = y;
}
public class main {
public static void main(String[] args) {
circulo A,B,C;
A = new circulo();
B = new circulo();
C = new circulo(5, -1, 2.34);
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo A de Raio = " + A.raio);
System.out.println("Circulo A de Centro = ( " + A.cx + " , "
+ A.cy + " )");
System.out.println("Circulo B de Raio = " + B.raio);
System.out.println("Circulo B de Centro = ( " + B.cx + " , "
+ B.cy + " )");
System.out.println("Circulo C de Raio = " + C.raio);
System.out.println("Circulo C de Centro = ( " + C.cx + " , "
+ C.cy + " )");
}
}
22
3.3 – Métodos
3.3.1 - Introdução
Um método da classe é uma rotina (código) que atua sobre o objeto como, por exemplo,
alterando seus campos, respondendo propriedades sobre o objeto, etc. No nosso exemplo,
implementamos um método que responde a área do objeto círculo.
Exemplo 3 (metodo area):
public class circulo {
public double raio;
public double cx,cy;
circulo() {
raio = 1.0;
cx = 0;
cy = 0;
}
circulo(double r,double x,double y) {
raio = r;
cx = x;
cy = y;
}
public double area() {
double a;
}
a = Math.PI * raio * raio;
return(a);
}
public class main {
public static void main(String[] args) {
circulo A,B,C;
A = new circulo();
B = new circulo();
C = new circulo(5, -1, 2.34);
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo A de Raio = " + A.raio);
System.out.println("Circulo A de Centro = ( " + A.cx + " , "
+ A.cy + " )");
System.out.println("Circulo A de Area = " + A.area());
System.out.println("Circulo B de Raio = " + B.raio);
23
System.out.println("Circulo B de Centro = ( " + B.cx + " , "
+ B.cy + " )");
System.out.println("Circulo B de Area = " + B.area());
System.out.println("Circulo C de Raio = " + C.raio);
System.out.println("Circulo C de Centro = ( " + C.cx + " , "
+ C.cy + " )");
System.out.println("Circulo C de Area = " + C.area());
}
}
3.3.2 – Modificadores do Método
Observe que na definição de nosso método:
public double area() {
existem dois elementos a serem destacados:
1) public double area()
O elemento double indica que nosso método retorna um campo double, pois estamos
retornando um valor no double no comando: return(a)
2) public double area()
O elemento public é denominado modificador do método e é semelhante aos modificadores
de campo. Para o método existem os seguintes modificadores:
• private: métodos definidos private somente são acessíveis na própria classe.
• public: são acessíveis por qualquer classe.
• package: acessíveis em classe do mesmo pacote (será definido posteriormente).
• protected: são acessíveis em subclasses, classes do mesmo pacote e na própria
•
•
•
•
•
•
abstract: o corpo do método não é definido nesta classe. Uma subclasse fica
responsável pela implementação do método.
static: veja na próxima seção.
final: não permite ser sobreposto por uma subclasse.
synchronized: será discutido em outras seções.
native: será discutido em outras seções.
strictfp: strict floating point tem todas as operações de ponto flutuante avalias
estritamente.
3.3.3 – Campos Static
24
O exemplo abaixo ilustra a utilização de um campo static.
Exemplo 4: (static)
public class circulo {
public double raio;
public double cx,cy;
private static long Id = 0;
circulo() {
raio = 1.0;
cx = 0;
cy = 0;
Id++;
}
circulo(double r,double x,double y) {
raio = r;
cx = x;
cy = y;
Id++;
}
public double area() {
double a;
}
}
a = Math.PI * raio * raio;
return(a);
public long getId() {
return Id;
}
public class main {
public static void main(String[] args) {
circulo A,B,C;
A = new circulo();
B = new circulo();
C = new circulo(5, -1, 2.34);
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo
System.out.println("Circulo
+ A.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
A de Raio = " + A.raio);
A de Centro = ( " + A.cx + " , "
A de Area = " + A.area());
No = " + A.getId());
25
System.out.println("Circulo
System.out.println("Circulo
+ B.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
B de Raio = " + B.raio);
B de Centro = ( " + B.cx + " , "
System.out.println("Circulo
System.out.println("Circulo
+ C.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
}
C de Raio = " + C.raio);
C de Centro = ( " + C.cx + " , "
B de Area = " + B.area());
No = " + B.getId());
C de Area = " + C.area());
No = " + C.getId());
}
Por que todos os Id são iguais ? Porque Id é static ! Para enumerarmos as esferas será
necessário criar um campo não static na classe.
Exemplo 5: (enumerando cada esfera)
public class circulo {
public double raio;
public double cx,cy;
private static long Id = 0;
private long MyId;
circulo() {
raio = 1.0;
cx = 0;
cy = 0;
MyId = Id++;
}
circulo(double r,double x,double y) {
raio = r;
cx = x;
cy = y;
MyId = Id++;
}
public double area() {
double a;
}
}
a = Math.PI * raio * raio;
return(a);
public long getId() {
return Id;
}
public long getMyId() {
return MyId;
}
public class main {
26
public static void main(String[] args) {
circulo A,B,C;
A = new circulo();
B = new circulo();
C = new circulo(5, -1, 2.34);
A.raio = 2.5;
A.cx = 1.0;
A.cy = 1.0;
System.out.println("Circulo
System.out.println("Circulo
+ A.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
A de Raio = " + A.raio);
A de Centro = ( " + A.cx + " , "
System.out.println("Circulo
System.out.println("Circulo
+ B.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
B de Raio = " + B.raio);
B de Centro = ( " + B.cx + " , "
System.out.println("Circulo
System.out.println("Circulo
+ C.cy + " )");
System.out.println("Circulo
System.out.println("Circulo
C de Raio = " + C.raio);
C de Centro = ( " + C.cx + " , "
A de Area = " + A.area());
No = " + A.getMyId());
B de Area = " + B.area());
No = " + B.getMyId());
C de Area = " + C.area());
No = " + C.getMyId());
System.out.println("Total de círculos =
" + A.getId());
}
}
3.3.4 – Exemplo de uma Classe Vetor
O exemplo abaixo ilustra a implementação de uma classe vetor de double.
Exemplo 6: Vetores
public class Vetor {
private double[] v;
private int
dim;
Vetor(int n){
dim = n;
v
= new double[n];
}
27
Vetor(double[] C){
dim = C.length;
v = new double[dim];
for(int j=0;j<dim;j++)
v[j]=C[j];
}
// Metodos de Acesso
public void set(int i,double x){
if ((i >= 0) && (i<dim))
v[i]=x;
}
public double get(int i) {
if ((i >= 0) && (i<dim))
return (v[i]);
else return 0;
}
}
public class main {
public static void main(String[] args) {
Vetor x = new Vetor(4);
x.set(0,1.2);
x.set(1,-2);
x.set(2,-4);
x.set(3,3.2);
x.get(i));
}
for(int i=0;i<4;i++){
System.out.println("v[" + i + "]= " +
}
}
28
CAPÍTULO II – VISUALIZAÇÃO E APLICAÇÕES GRÁFICAS 2D __________ 3
1 - PONTOS E RETAS NO OPENGL ______________________________________ 3
1.1 – A Tela do Computador ___________________________________________ 3
1.2 – Cores_________________________________________________________ 3
1.3 – Introdução ao JoGL______________________________________________ 4
1.3.1 – Apresentação______________________________________________________ 4
1.3.2 – Instalação_________________________________________________________ 4
1.4 – Exemplo: Criando a janela OpenGL _________________________________ 6
1.5 – Exemplo: Plotar um ponto na tela utilizando as bibliotecas do OpenGl ______ 6
1.5 – Comando: gluOrtho2D ___________________________________________ 9
1.6 – Exemplo: Plotar uma reta unindo dois pontos ________________________ 10
1.6.1 – Algoritmo ingênuo _________________________________________________ 10
1.6.3 – Retas no Opengl __________________________________________________ 12
1.7 – Exemplo: Plotar o gráfico de uma função ____________________________ 12
2 – TECLADO E MOUSE (Callbacks) ____________________________________ 19
2.1 – Introdução ____________________________________________________ 19
2.2 – Teclado ______________________________________________________ 19
2.3 – Exemplo: Utilização do teclado no programa funções. __________________ 19
2.4 – Mouse _______________________________________________________ 21
2.4.1- Interrupções a partir do mouse ________________________________________ 21
2.4.2- Aplicações: Realizando o “zoom” do gráfico ______________________________ 26
3 – CURVAS PARAMÉTRICAS _________________________________________ 32
3.1 – Introdução ____________________________________________________ 32
3.2 – Exemplo: Visualização de Curvas Paramétricas ______________________ 32
3.2.1 – Módulo main.java__________________________________________________ 32
3.2.2 – Módulo curva _____________________________________________________ 35
3.2.4 –Exercício _________________________________________________________ 37
3.3 – Curvas na forma Polar __________________________________________ 37
3.4 – Exemplo: Visualização de Curvas Polares ___________________________ 38
3.5 – Exercícios ____________________________________________________ 39
4 – CURVAS IMPLÍCITAS _____________________________________________ 40
4.1 – Introdução ____________________________________________________ 40
4.2 – Visualização de Curvas Implícitas _________________________________ 40
4.3 – Programa Curva Implícita ________________________________________ 41
4.4 –Exercício _____________________________________________________ 42
5 – RETAS E POLÍGONOS NO OPENGL _________________________________ 43
5.1 – Retas e Polígonos______________________________________________ 43
5.2 – Exemplo: Visualização dos Métodos Numéricos de Integração ___________ 44
6 – PROCESSAMENTO DE IMAGEM ____________________________________ 46
6.1 – Introdução ____________________________________________________ 46
7 – FRACTAIS ______________________________________________________ 53
1
7.1 – Conjuntos auto-semelhantes _____________________________________ 53
7.2 – Dimensão Hausdorff e o conceito de fractal __________________________ 54
7.3 – Exemplos de fractais ____________________________________________ 54
7.3.1- Triângulo de Sierpinski ______________________________________________
7.3.2- Triângulo de Sierpinski utilizando Monte Carlo ____________________________
7.3.3- “Fern” ____________________________________________________________
7.4 – Conjunto de Julia ___________________________________________________
55
61
62
65
2
CAPÍTULO II – VISUALIZAÇÃO E APLICAÇÕES
GRÁFICAS 2D
1- PONTOS E RETAS NO OPENGL
1.1 – A Tela do Computador
A tela do computador pode ser considerada uma matriz de células discretas (Pixels), cada qual pode estar
acesa ou apagada.
0,1 1,1
2,1 …
0,0 1,0
2,0 …
A definição da tela varia conforme o monitor e a placa gráfica. As definições básicas encontradas na
maioria dos monitores são:
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 combinação de vermelho,
verde e azul (RGB). O número de cores possíveis varia conforme o hardware. Cada pixel tem uma mesma
quantidade de memória para armazenar suas cores. O buffer de cores (Color Buffer) é uma porção da
memória 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 gráfica 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 básica 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 básicas:
Cores
R
G
B
Vermelho
Verde
Azul
Amarelo
Cyan
Magenta
Branco
Preto
1.0
0.0
0.0
1.0
0.0
1.0
1.0
0.0
0.0
1.0
0.0
1.0
1.0
0.0
1.0
0.0
0.0
0.0
1.0
0.0
1.0
1.0
1.0
0.0
3
1.3 – Introdução ao JoGL
1.3.1 – Apresentação
O sistema gráfico OpenGL (GL significa Graphics Library) é uma biblioteca (de aproximadamente 350
comandos) para aplicações gráficas. O OpenGL foi desenvolvido pela Silicon Graphics (SGI) voltado
para aplicações de computação gráfica 3D, embora possa ser usado também em 2D. As rotinas permitem
gerar primitivas (pontos, linhas, polígonos, etc) e utilizar recursos de iluminação 3D.
O OpenGL é independente do sistema de janelas, ou seja, suas funções não 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.
Várias tentativas foram feitas no sentido de desenvolver uma versão do OpenGL para Java com algum
sucesso, mas somente agora com a parceria entre a Sun (criadora do Java) e a Silicon Graphics (criadora
do OpenGL) esta sendo desenvolvido uma versão oficial.
1.3.2 – Instalação
Inicialmente você deve obter duas bibliotecas na internet, no link:
https://jogl.dev.java.net/servlets/ProjectDocumentList?folderID=3631&expandFolder=3631&folderID=4
843
Os programa executados e testados nestas notas de aulas foram feitos utilizando-se:
Release Builds2005(0) - > 1.1 – June 24 (12) (veja abaixo)
jogl (0)/
•
Release Builds 2003 (6)/
•
Release Builds 2004 (0)/
•
Release Builds 2005 (0)/
o
1.1.1 - July 12 (12)/
o
1.1b08 - February 7 (11)/
o
1.1b09 - February 15 (11)/
o
1.1b10 - February 27 (11)/
o
1.1b11 - May 11 (12)/
o
1.1 b12 - May 27 (12)/
o
1.1 - June 24 (12)/
o
JSR-231 beta 01 - October 27 (11)/
•
Release Builds 2006 (0)/
•
Temporary Files (4
4
São necessários dois pacotes (em destaque na tabela abaixo):
1. jogl.jar
2. jogl-natives-win32.jar (para usuários do windows XP)
1.1 - June 24
JOGL 1.1 release build
Filter this list
Name
Status
Modified by
Size
Reservations
Description
javadoc_public.zip
Draft
kbr on Friday, June
1004.52
24, 2005 at 5:01:27
kB
PM
JOGL Javadoc
Info
jogl.jar
Draft
kbr on Friday, June
24, 2005 at 5:02:02 1.12 mB
PM
JOGL classes
Info
jogl-demos.jar
Draft
kbr on Friday, June
258.32
24, 2005 at 5:06:43
kB
PM
JOGL demo classes
Info
jogl-demos-data.jar Draft
kbr on Friday, June
24, 2005 at 5:07:13 7.49 mB
PM
JOGL demo data files
Info
jogl-demos-src.zip
Draft
kbr on Friday, June
24, 2005 at 5:07:43 7.8 mB
PM
JOGL demo source code Info
jogl-demos-util.jar
Draft
kbr on Friday, June
139.06
24, 2005 at 7:03:14
kB
PM
JOGL demo utility
classes
Info
jogl-nativeslinux.jar
Draft
kbr on Friday, June
300.06
24, 2005 at 5:03:22
kB
PM
JOGL native libraries
for Linux/x86
Info
jogl-nativesmacosx.jar
Draft
kbr on Friday, June
146.79
24, 2005 at 5:03:49
kB
PM
JOGL native libraries
for Mac OS X 10.3+
Info
jogl-nativessolsparc.jar
Draft
kbr on Friday, June
268.07
24, 2005 at 5:04:18
kB
PM
JOGL native libraries
Info
for Solaris/SPARC 2.8+
jogl-nativessolx86.jar
Draft
kbr on Friday, June
241.16
24, 2005 at 5:04:58
kB
PM
JOGL native libraries
for Solaris/x86 2.9+
Info
jogl-nativeswin32.jar
Draft
kbr on Friday, June
24, 2005 at 5:05:26 60.1 kB
PM
JOGL native libraries
for Windows/x86
Info
jogl-src.zip
Draft
kbr on Friday, June
24, 2005 at 5:05:56 1.09 mB
PM
JOGL source code
Info
5
Passos para a instalação (usando o Eclipse):
1) Dê download nos dois arquivos citados.
2) Copie o arquivo jogl.jar para o diretório:
C:\Programs Files\Java\j2re1.4.2_10\lib\ext
3) Utilizando o WinRAR (por exemplo), descomprima o arquivo jogl-natives-win32.jar (o resultado
serão dois arquivos: jogl.dll e jogl_cg.dll e o diretorio META-INF. Copie estes arquivos para o
diretório:
C:\Programs Files\Java\j2re1.4.2_10\bin
OBS: O diretorio .../j2re1.4.2_10/... pode ser diferente conforme a versão do java. Voce pode verificar
executando o Eclipse e verificando o campo JRE_System Library que aparece em qualquer dos projetos.
1.4 – Exemplo: Criando a janela OpenGL
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class canvas {
/**
* @param args
*/
public static void main(String[] args) {
Frame frame
= new Frame("Hello World");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
frame.add(canvas);
frame.setSize(300, 300);
frame.addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
frame.show();
}
}
1.5 – Exemplo: Plotar um ponto na tela utilizando as bibliotecas do OpenGl
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class ponto {
public static void main(String[] args) {
Frame frame
= new Frame("Ponto");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(300, 300);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
6
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
glu.gluOrtho2D(0,399,0,399);
}
public void display(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2f(200.0f,200.0f);
gl.glEnd();
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean
deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int height) {}
}
}
Vamos comentar alguns comandos:
Frame frame
= new Frame("Ponto");
A classe Frame somente cria uma janela. Este é um recurso do Java e é fornecido pelo pacote java.awt
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
Cria a área de rendering do OpenGL no frame anteriormente criado.
canvas.addGLEventListener( new JoglRender() );
Interrupção quando ocorre um evento no canvas do OpenGL
frame.add(canvas);
Adiciona o canvas do OpenGL no frame do java
frame.setSize(300, 300);
frame.setLocation(50,50);
Define parâmetros de inicialização do frame
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Interrupção do frame do Java. Existem outras interrupções além do windowClosing.
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
Esta a função será executada sempre que a janela for criada.
GLU glu = drawable.getGLU();
glu.gluOrtho2D(0,399,0,399);
Este comando estabelece a escala da tela. Sua sintaxe é:
gluOrtho2D(GLdouble left, Gldouble right, Gldouble bottom, Gldouble top);
}
public void display(GLDrawable drawable) {
Esta a função será executada sempre que a janela necessita ser redesenhada.
GL gl = drawable.getGL();
7
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2f(200.0f,200.0f);
gl.glEnd();
gl.glFlush();
}
Quando a função display é executada temos o seguinte resultado:
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
Indica cor para ser utilizada no fundo da tela.
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.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.0f,200f.0);
glEnd();
Plota um ponto na posição (200,200) na tela.
glFlush();
Imprime o conteúdo do buffer na tela.
public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean
deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int height) {}
Métodos que não foram implementados e correspondem respectivamente as interrupções de alteração do
display e mudança de dimensão da tela.
Exercícios:
1) Acrescente um contador para verificar quantas vezes a função display é chamada.
static class JoglRender implements GLEventListener {
static int i = 0;
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
glu.gluOrtho2D(0,399,0,399);
}
public void display(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glPointSize(5.0f);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2f(200.0f,200.0f);
gl.glEnd();
gl.glFlush();
8
}
System.out.println(i);
i++;
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
1.5 – Comando: gluOrtho2D
Na maioria de nossas aplicações desejamos nos referenciar a um ponto na tela, não por coordenadas
correspondendo as dimensões informadas no comando frame.setSize(300, 300), mas sim levando-se
em conta o domínio de visualização relacionado ao problema. Para isso, o comando gluOrtho2D()
realiza a mudança para o sistema de coordenadas desejado.
Esta tarefa é realizada fazendo a correspondência entre os intervalos em questão:
Assim:
e segue que
e identicamente para a coordenada y:
.
O programa abaixo ilustra o efeito do gluOrttho2D.
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class ortho {
public static void main(String[] args) {
Frame frame
= new Frame("Ortho");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(300, 300);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
glu.gluOrtho2D(0,300,0,300);
}
public void display(GLDrawable drawable) {
GL gl = drawable.getGL();
float x = -0.5f;
9
float
float
float
float
float
y
L
R
T
B
= 0.5f;
= -1.0f;
= 1.0f;
= 1.0f;
= -1.0f;
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glPointSize(4.0f);
float xo =
float yo =
((x - L)/(R-L)*(299));
((y - B)/(T-B)*(299));
gl.glBegin(GL.GL_POINTS);
gl.glVertex2f(xo,yo);
gl.glEnd();
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
}
1.6 – Exemplo: Plotar uma reta unindo dois pontos
Como exemplo vamos desenhar uma reta (não vertical) unindo dois pontos (x0,y0) e (x1,y1).
A equação da reta que passa por dois pontos é:
1.6.1 – Algoritmo ingênuo
A primeira idéia de como resolver este problema é proposto pelo programa abaixo. Este é um exemplo
ingênuo de como desenhar a reta que passa por dois pontos dados. Vamos discutir a seguir os principais
problemas deste programa e as possíveis soluções.
/* -------------------------------------------------------------- */
/* Exemplo ingênuo de como plotar a reta definida por dois pontos */
/* -------------------------------------------------------------- */
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class reta {
public static void main(String[] args) {
Frame frame
= new Frame("Reta");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(300, 300);
frame.setLocation(50,50);
10
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
glu.gluOrtho2D(-3,3,-3,3);
}
public void display(GLDrawable drawable) {
double y;
GL
gl = drawable.getGL();
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
for (double x = -3;x <= 3;x+=0.001) {
y = 2*x - 1;
gl.glVertex2f((float)x,(float)(y));
}
gl.glEnd();
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
}
Algumas desvantagens do programa proposto:
1) Este método requer operações em ponto flutuante (float ou double) para cada pixel. Isto acarreta em
um algoritmo lento, se comparado a um algoritmo que opera somente com números inteiros. Para o
caso da reta, existe um tal algoritmo que utiliza somente aritmética com números inteiros. Este
algoritmo foi desenvolvido por Jack E. Bresenham na década de 60 e será descrito adiante.
2) O usuário estabelece o número 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 desnecessárias). O ideal é o próprio programa se encarregar de determinar o
número de pontos necessários e suficientes para resolver o problema.
3) O caso particular da reta vertical
(onde K é constante) não pode ser plotado.
Exercício: Desenhe várias retas preeenchendo a tela e teste a velocidade, como por exemplo:
...
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
for (double b = -10; b <= 10; b+=0.01) {
for (double x = -3;x <= 3; x+=0.001) {
y = 2*x + b;
11
gl.glVertex2f((float)x,(float)(y));
}
}
gl.glEnd();
gl.glFlush();
...
1.6.2 – Retas no Opengl
O OpenGL dispõe em sua biblioteca interna de um comando que plota uma reta por dois pontos dados
P0(x0,y0) e P1(x1,y1):
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(x0, y0));
gl.glVertex2f(x1, y1);
gl.glEnd();
Compare a velocidade com o exercício anterior::
public void display(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
for (double b = -10; b<= 10;b+=0.01) {
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(-3.0f,(float)(-6f+b));
gl.glVertex2f( 3.0f,(float)( 6f+b));
gl.glEnd();
}
gl.glFlush();
}
1.7 – Exemplo: Plotar o gráfico de uma função
Vamos começar com uma versão bem simplificada, para plotar o gráfico de uma função y=f(x).
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class funcao {
public static void main(String[] args) {
12
Frame frame
= new Frame("Funcao");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
glu.gluOrtho2D(-3,3,-3,3);
}
public void display(GLDrawable drawable) {
double y;
GL
gl = drawable.getGL();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
for (double x = -3; x<= 3;x+=0.01) {
y = x*x;
// Esta é a funcao
gl.glVertex2f((float)x,(float)(y));
}
gl.glEnd();
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
}
Vamos aprimorar nosso código:
1) Acrescentando os eixos.
2) Criando uma variável pontos que permita selecionar a discretização.
3) Criar uma classe funcao que trate da definição da função e das tarefas específicas de plotar o
gráfico da função.
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static funcao f;
13
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
f = new funcao(400,-3.0f,-3.0f,3.0f,3.0f);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),f.get_ymin(),f.get_ymax());
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
}
/* * * * * * * * * * * * * * * */
/* Modulo: funcao.java
*/
/* * * * * * * * * * * * * * * */
import net.java.games.jogl.*;
public class funcao {
int
pontos;
float xmin,xmax,ymin,ymax;
funcao()
pontos
xmin =
xmax =
}
{
= 300;
ymin = -1;
ymax = 1;
funcao(int p) {
pontos = p;
14
xmin = ymin = -1;
xmax = ymax = 1;
}
funcao(int p,float xm,float ym,float xM,float yM) {
pontos = p;
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
}
public
public
public
public
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
return
return
return
return
xmin;
ymin;
xmax;
ymax;
}
}
}
}
public float f(float x) {
return (float) Math.sin((double)x);
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
}
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex2f (xmin,0);
gl.glVertex2f (xmax,0);
gl.glVertex2f (0,ymin);
gl.glVertex2f (0,ymax);
gl.glEnd();
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
int i;
float dx;
float x, y;
dx = (xmax - xmin)/pontos;
gl.glColor3f (1.0f, 0.0f, 0.0f);
}
x = xmin;
for (i = 0; i < pontos; i++) {
y = f(x);
gl.glBegin (GL.GL_POINTS);
gl.glVertex2f (x,y);
gl.glEnd();
x = x + dx;
}
}
Nossa próxima etapa é permitir que o usuário possa alterar o domínio de visualização da função
interativamente. Na próxima sessão apresentamos algumas das principais interrupções usando o mouse
que nos permitirão executar esta tarefa.
Exercício: Entre com o domínio através do teclado.
15
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static funcao f;
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
GLCanvas
canvas
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
=
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GLU glu = drawable.getGLU();
GL
gl = drawable.getGL();
f = new funcao(400);
f.dominio();
gl.glLoadIdentity();
double a,b,c,d;
a = (double)(f.get_xmin());
b = (double)(f.get_xmax());
c = (double)(f.get_ymin());
d = (double)(f.get_ymax());
glu.gluOrtho2D(a,b,c,d);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT
|
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.LoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),f.get_ymin(),f.get_ymax());
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable
modeChanged, boolean deviceChanged) {}
drawable,
boolean
public void reshape(GLDrawable drawable, int x, int y, int
width, int height) {}
}
16
}
funcao.java
import net.java.games.jogl.*;
public class funcao {
int
pontos;
float xmin,xmax,ymin,ymax;
funcao() {
pontos = 300;
xmin = ymin = -1;
xmax = ymax = 1;
}
funcao(int
pontos
xmin =
xmax =
}
p) {
= p;
ymin = -1;
ymax = 1;
funcao(int
pontos
xmin =
ymin =
xmax =
ymax =
}
p,float xm,float ym,float xM,float yM) {
= p;
xm;
ym;
xM;
yM;
public
public
public
public
//
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
return
return
return
return
xmin;
ymin;
xmax;
ymax;
}
}
}
}
public float f(float x) {
return x*x;
return (float) Math.sin((double)x);
}
public void dominio() {
System.out.print("xmin = ");
xmin = TextIO.getFloat();
System.out.print("ymin = ");
ymin = TextIO.getFloat();
System.out.print("xmax = ");
xmax = TextIO.getFloat();
System.out.print("ymax = ");
ymax = TextIO.getFloat();
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex2f (xmin,0);
gl.glVertex2f (xmax,0);
gl.glVertex2f (0,ymin);
gl.glVertex2f (0,ymax);
gl.glEnd();
}
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
int i;
float dx;
float x, y;
17
dx = (xmax - xmin)/pontos;
gl.glColor3f (1.0f, 0.0f, 0.0f);
x = xmin;
for (i = 0; i < pontos; i++) {
y = f(x);
gl.glBegin (GL.GL_POINTS);
gl.glVertex2f (x,y);
gl.glEnd();
x = x + dx;
}
}
}
18
2 – TECLADO E MOUSE (Callbacks)
2.1 – Introdução
O usuário pode interagir com o programa de duas formas principais: através do Mouse ou Teclado. Para
isso o Jogl dispõe de dois tipos de funções (que denominamos Callbacks) específicas para habilitar a
utilização do teclado e do mouse. Vamos descrevê-las a seguir.
2.2 – Teclado
Para registrar ocorrências no teclado o Jogl dispõe da função:
canvas.addKeyListener
( new JoglKey() );
Esta função determina que quando uma tecla for pressionada, o controle do programa deve passar a classe
JoglKey que reimplementa três métodos:
public void keyPressed (KeyEvent e)
public void keyReleased(KeyEvent e)
public void keyTyped (KeyEvent e)
O exemplo abaixo exemplifica uma aplicação para o programa funções.
2.3 – Exemplo: Utilização do teclado no programa funções.
Como exemplo vamos acrescentar no programa funções a possibilidade de alterarmos o domínio da
função durante a execução do programa. Assim podemos estabelecer que quando o usuário pressionar a
tecla “D” ou “d”, o programa interrompe e solicita na janela de concole do Eclipse as novas informações
sobre o domínio da função. A unica alteração ocorre no main.
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
GLCanvas
canvas
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
canvas.addKeyListener
( new JoglKey() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
=
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static funcao f;
static class JoglRender implements GLEventListener
{
public void init(GLDrawable drawable) {
f = new funcao(400);
f.dominio();
}
19
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glLoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),f.get_ymin(),f.get_ymax());
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
static class JoglKey implements
KeyListener {
public void keyPressed (KeyEvent e)
{
if (e.getKeyChar() == 'd' || e.getKeyChar() == 'D')
f.dominio();
}
public void keyReleased(KeyEvent e) {}
public void keyTyped (KeyEvent e) {
}
}
}
20
2.4 – Mouse
O Jogl é capaz de obter três tipos de ocorrências diferentes a partir do mouse. Vamos descrevê-las em
seguida e discutir uma interessante aplicação para o estudo de gráficos de funções.
2.4.1- Interrupções a partir do mouse
a) MouseListener
Este evento contém cinco métodos básicos de controle do mouse:
void mouseClicked(MouseEvent e)
Registra quando um botào for pressionado e solto.
void mouseEntered(MouseEvent e)
Registra quando o mouse entra no componente.
void mouseExited(MouseEvent e)
Registra quando o mouse sai do componente.
void mousePressed(MouseEvent e)
Registra quando um botào do mouse é pressionado.
void mouseReleased(MouseEvent e)
Registra quando o botào do mouse é solto sobre o componente.
Para testar qual botão foi pressionado:
Primeiro botão: e.getButton() == 1
Segundo botão: e.getButton() == 2
Terceiro botão: e.getButton() == 3
Como exemplo, vamos alterar o programa função anterior, e acrescentar outra forma de interrupção
para alterar o domínio. Assim se o usuário pressionar o botão direito do mouse, o programa solicita no
console o novo domínio de visualização. Se pressionar o botão esquerdo, o programa informa em qual
coordenada da tela o mouse se encontra.
Para implementar esta alteração só precisamos mudar o programa main.java. Seu novo código é
apresentado a seguir:
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static funcao f;
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
canvas.addKeyListener
( new JoglKey()
);
canvas.addMouseListener ( new JoglMouse() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
21
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
f = new funcao(400,-1,-1,1,1);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),
f.get_ymin(),f.get_ymax());
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
static class JoglKey implements
KeyListener {
public void keyPressed (KeyEvent e)
{
if (e.getKeyChar() == 'd' || e.getKeyChar() == 'D')
f.dominio();
System.out.println("Pressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("Released");
}
public void keyTyped (KeyEvent e) {
System.out.println("Typed");
}
}
static class JoglMouse implements
MouseListener {
22
public void mouseEntered(MouseEvent e) {
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==3) {
f.dominio();
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==1) {
System.out.print("x = ");
System.out.print(e.getX());
System.out.print(" y = ");
System.out.println(e.getY());
}
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
b) MouseMotionListener
Este evento detecta o movimento do mouse em dois casos:
void mouseDragged(MouseEvent e)
Quando o botão do mouse está pressionado e em movimento sobre a componente.
void mouseMoved(MouseEvent e)
Quando o mouse é movimentado sobre a componente.
c) MouseWheelListener
void mouseWheelMoved(MouseWheelEvent e)
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static funcao f;
/**
Main Class
**/
23
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new
GLCapabilities());
canvas.addGLEventListener( new JoglRender() );
canvas.addKeyListener
( new JoglKey() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addMouseWheelListener( new JoglMouseWheel() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
/**
OpenGL Eventos
**/
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
f = new funcao(400,-1,-1,1,1);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),f.get_ymin(),f.get_ymax());
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean modeChanged,
boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int width, int
height) {}
}
/**
Teclado Eventos
static class JoglKey implements
**/
KeyListener {
public void keyPressed (KeyEvent e)
{
if (e.getKeyChar() == 'd' || e.getKeyChar() == 'D')
f.dominio();
24
System.out.println("Pressed");
}
public void keyReleased(KeyEvent e) {
System.out.println("Released");
}
public void keyTyped (KeyEvent e) {
System.out.println("Typed");
}
}
/**
Mouse Eventos
**/
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==2) {
f.dominio();
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.print("x = ");
System.out.print(e.getX());
System.out.print(" y = ");
System.out.println(e.getY());
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
/**
Movimento do Mouse Eventos
static class JoglMouseMotion implements
**/
MouseMotionListener {
public void mouseDragged(MouseEvent e) {
System.out.println("Dragged: " + e.getX() + "," + e.getY());
}
public void mouseMoved(MouseEvent e) {
System.out.println("Moved: " + e.getX() + "," + e.getY());
}
}
/**
Mouse Eventos
**/
25
static class JoglMouseWheel implements
MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
System.out.println("Wheel Moved: " + e.getX() + "," + e.getY());
}
}
}
2.4.2- Aplicações: Realizando o “zoom” do gráfico
Versão Inicial
No processo de visualização das funções, ou mesmo da integração numérica, muitas vezes desejamos
alterar o domínio do nosso gráfico. Para isso selecionamos a tecla “D” e “d” como uma interrupção do
teclado para que pudéssemos informar o novo domínio. Uma forma mais ágil seria selecionar com o
mouse interativamente um retângulo que gostaríamos de visualizar. É o que faremos no próximo
programa.
Para isso utilizaremos as interrupções do mouse para selecionarmos a região desejada. Quando o botão
direito do mouse é pressionado, marcamos o ponto inicial da região. Enquanto o mouse está em
movimento (com o botão direito pressionado), desenhamos o retângulo desejado. Quando o botão do
mouse é solto, obtemos o ponto final da região e atualizamos o domínio da função.
Observe que as coordenadas obtidas pelo eventos do mouse precisam ser convertidas para o sistema de
coordendas indicado nos parâmetros do gluOrtho2D. Para isso, basta considerarmos a transformação
inversa a aplicada na seção 1.5:
e segue que
e identicamente para a coordenada y.
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static funcao f;
static int mov = 0;
/* Detecta movimento do mouse */
static int xv1, yv1, xv2, yv2;
/* Domínio da nova janela */
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
26
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
f = new funcao(400,-1,-1,1,1);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(f.get_xmin(),f.get_xmax(),f.get_ymin(),f.get_ymax());
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
if (mov == 1) {
System.out.println("mov = 1");
f.plota_retangulo (drawable, xv1,yv1,xv2,yv2);
}
f.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) { }
public void reshape(GLDrawable drawable, int x, int y, int width,
int height) {}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Entra");
xv1 = e.getX();
yv1 = e.getY();
mov = 1;
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Sai");
xv2 = e.getX();
yv2 = e.getY();
mov = 0;
f.recalcula_dominio (xv1,yv1,xv2,yv2);
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
27
}
}
static class JoglMouseMotion implements
MouseMotionListener {
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
xv2 = e.getX();
yv2 = e.getY();
System.out.println("Dragged: " + e.getX() + "," +
e.getY());
canvas.display();
}
}
public void mouseMoved(MouseEvent e) {
System.out.println("Moved: " + e.getX() + "," + e.getY());
}
//
}
}
funcao.java
import net.java.games.jogl.*;
public class funcao {
int
pontos;
float xmin,xmax,ymin,ymax;
funcao() {
pontos = 300;
xmin = ymin = -1;
xmax = ymax = 1;
}
funcao(int
pontos
xmin =
xmax =
}
p) {
= p;
ymin = -1;
ymax = 1;
funcao(int
pontos
xmin =
ymin =
xmax =
ymax =
}
p,float xm,float ym,float xM,float yM) {
= p;
xm;
ym;
xM;
yM;
public
public
public
public
//
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
return
return
return
return
xmin;
ymin;
xmax;
ymax;
}
}
}
}
public float f(float x) {
return x*x;
return (float) Math.sin((double)x);
}
public void dominio() {
System.out.print("xmin = ");
28
xmin = TextIO.getFloat();
System.out.print("ymin = ");
ymin = TextIO.getFloat();
System.out.print("xmax = ");
xmax = TextIO.getFloat();
System.out.print("ymax = ");
ymax = TextIO.getFloat();
}
public float converte(float p, float min, float max, int dim) {
float x;
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
public
xv_2,float yv_2) {
void
recalcula_dominio
(float
xv_1,float
yv_1,float
float xmin1,xmax1;
float ymin1,ymax1;
xmin1 = converte(xv_1,xmin,xmax,600);
xmax1 = converte(xv_2,xmin,xmax,600);
xmin = xmin1;
xmax = xmax1;
ymin1 = converte(yv_2,ymax,ymin,600);
ymax1 = converte(yv_1,ymax,ymin,600);
ymin = ymin1;
ymax = ymax1;
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex2f (xmin,0);
gl.glVertex2f (xmax,0);
gl.glVertex2f (0,ymin);
gl.glVertex2f (0,ymax);
gl.glEnd();
}
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
int i;
float dx;
float x, y;
dx = (xmax - xmin)/pontos;
System.out.print(xmax + " " + xmin);
gl.glColor3f (1.0f, 0.0f, 0.0f);
x = xmin;
for (i = 0; i < pontos; i++) {
y = f(x);
gl.glBegin (GL.GL_POINTS);
gl.glVertex2f (x,y);
gl.glEnd();
x = x + dx;
}
}
public void plota_retangulo (GLDrawable drawable, int x1, int y1,
int x2, int y2) {
GL gl = drawable.getGL();
29
float retxmin,retxmax,retymin,retymax;
retxmin
retxmax
retymin
retymax
=
=
=
=
converte
converte
converte
converte
(x2,xmin,xmax,600);
(x1,xmin,xmax,600);
(y1,ymax,ymin,600);
(y2,ymax,ymin,600);
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(retxmin,retymin);
gl.glVertex2f(retxmin,retymax);
gl.glVertex2f(retxmax,retymax);
gl.glVertex2f(retxmax,retymin);
gl.glEnd();
}
}
Versão Pilha
Em uma segunda versão gostariamos de voltarmos ao domínio original. Para isso, precisamos armazenar
as alterações anteriores do domínio. Uma estrutura adequada para esta situação seria montar uma pilha. O
Java já dispões desta estrutura, porém podemos montar uma versão ilustrativa da Classe Pilha. Também
vamos criar uma classe Window que armazena o domínio de visualização da janela.
Windows.java
public class Window {
float xmin;
float xmax;
float ymin;
float ymax;
Window(float xm,float ym,float xM,float yM) {
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
}
}
float get_xmin()
return xmin;
}
float get_ymin()
return ymin;
}
float get_xmax()
return xmax;
}
float get_ymax()
return ymax;
}
{
{
{
{
Pilha.java
public class Pilha {
private No topo;
30
private static class No {
private Window a
;
private No
prox;
}
public void push(Window a) {
No novo_topo
= new No();
novo_topo.a
= a;
novo_topo.prox = topo;
topo
= novo_topo;
}
public Window pop() {
if (Vazia()) throw new RuntimeException("Pilha Vazia");
Window a = topo.a;
topo
= topo.prox;
return a;
}
public boolean Vazia() {
if (topo == null)
return (true);
else
return(false);
}
}
Na classe funcao.java precisamos agora armazenar a cada mudança de janela, o novo dominio. Tambem
precisamos inserir um novo metodo que retorna o dominio anterior.
funcao.java
...
public void recalcula_dominio (float xv_1,float yv_1,
float xv_2,float yv_2) {
float xmin1,xmax1;
float ymin1,ymax1;
Window W = new Window(xmin,ymin,xmax,ymax);
xmin1 = converte(xv_1,xmin,xmax,600);
xmax1 = converte(xv_2,xmin,xmax,600);
ymin1 = converte(yv_2,ymax,ymin,600);
ymax1 = converte(yv_1,ymax,ymin,600);
w.push(W);
xmin = xmin1; xmax = xmax1;
ymin = ymin1; ymax = ymax1;
}
public void retorna_dominio () {
Window W = w.pop();
xmin = W.get_xmin();
xmax = W.get_xmax();
ymin = W.get_ymin();
ymax = W.get_ymax();
}
...
main.java
31
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Sai");
xv2 = e.getX();
yv2 = e.getY();
mov = 0;
f.recalcula_dominio (xv1,yv1,xv2,yv2);
canvas.display();
}
}
if (e.getButton()==1) {
System.out.println("Volta Zoom");
f.retorna_dominio();
canvas.display();
}
3 – CURVAS PARAMÉTRICAS
3.1 – Introdução
Considere uma curva C representando a trajetória de uma partícula P, de tal forma que a posição P(x,y)
da partícula é conhecida em cada instante de tempo t.
Assim as coordenadas x e y são conhecidas como funções da variável t de modo que:
x = x(t)
y = y(t)
Estas são as equações paramétricas da curva C e t é denominado parâmetro. Como exemplo de curvas
temos:
a) Circunferência de centro na origem e raio 1:
x = cos(t)
y = sen(t)
onde 0 <= t <= 2*Pi
b) Ciclóide (curva traçada por um ponto da circunferência quando o círculo rola sobre uma reta):
x = t - sen(t)
y = 1 - cos(t)
3.2 – Exemplo: Visualização de Curvas Paramétricas
Vamos implementar um programa que visualize curvas paramétricas. Observe que a diferença principal
para o programa funções é que tanto a variável x, quanto y devem ser calculadas em função do parâmetro
t. Vamos aproveitar uma boa parte da estrutura já implementada no programa função.
3.2.1 – Módulo main.java
Este módulo é idêntico ao módulo main.java. A única diferença é que as chamadas são feitas para as
novas funções de desenho das curvas.
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static curva c;
32
static int mov = 0;
/* Detecta movimento do
static int xv1, yv1, xv2, yv2;
/* Domínio da nova janela
mouse */
*/
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Funcao");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
c = new curva(400,-3.0f,3.0f,3.0f,3.0f,0.0f,(float)(2*Math.PI));
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(c.get_xmin(),c.get_xmax(),c.get_ymin(),c.get_ymax())
;
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
if (mov == 1) {
System.out.println("mov = 1");
c.plota_retangulo (drawable,
xv1,yv1,xv2,yv2);
}
c.plota_eixo(drawable);
c.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {
}
33
public void reshape(GLDrawable drawable, int x,
int y, int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Entra");
xv1 = e.getX();
yv1 = e.getY();
mov = 1;
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Sai");
xv2 = e.getX();
yv2 = e.getY();
mov = 0;
c.recalcula_dominio (xv1,yv1,xv2,yv2);
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
static class JoglMouseMotion implements
MouseMotionListener
{
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK)
!= 0) {
xv2 = e.getX();
yv2 = e.getY();
System.out.println("Dragged: " + e.getX() +
"," + e.getY());
canvas.display();
}
}
34
public void mouseMoved(MouseEvent e) {
System.out.println("Moved: " + e.getX() + "," +
//
e.getY());
}
}
}
3.2.2 – Módulo curva
Neste módulo implementamos a classe curva.
import net.java.games.jogl.*;
public class curva {
int
pontos;
float xmin,xmax,ymin,ymax;
float tmax,tmin;
curva() {
pontos
xmin =
xmax =
tmin =
tmax =
}
= 300;
ymin = -1;
ymax = 1;
0.0f;
1.0f;
curva(int
pontos
xmin =
xmax =
tmin =
tmax =
}
p) {
= p;
ymin = -1;
ymax = 1;
0.0f;
1.0f;
curva(int
pontos
xmin =
ymin =
xmax =
ymax =
tmin =
tmax =
}
p,float xm,float ym,float xM,float yM) {
= p;
xm;
ym;
xM;
yM;
0.0f;
1.0f;
curva(int p,float xm,float ym,float xM,float yM,float
tm,float tM) {
pontos = p;
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
tmin = tm;
tmax = tM;
}
public float get_xmin() { return xmin; }
public float get_ymin() { return ymin; }
public float get_xmax() { return xmax; }
public float get_ymax() { return ymax; }
35
public float[] c(float t) {
float [] v = new float[2];
v[0] = (float)Math.sin(t);
v[1] = (float)Math.cos(t);
return v;
}
public void dominio() {
System.out.print("xmin = ");
xmin = TextIO.getFloat();
System.out.print("ymin = ");
ymin = TextIO.getFloat();
System.out.print("xmax = ");
xmax = TextIO.getFloat();
System.out.print("ymax = ");
ymax = TextIO.getFloat();
}
public float converte(float p, float min, float max, int
dim) {
float x;
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
public void recalcula_dominio (float xv_1,float yv_1,float
xv_2,float yv_2) {
float xmin1,xmax1;
float ymin1,ymax1;
xmin1 = converte(xv_1,xmin,xmax,600);
xmax1 = converte(xv_2,xmin,xmax,600);
xmin = xmin1;
xmax = xmax1;
ymin1 = converte(yv_2,ymax,ymin,600);
ymax1 = converte(yv_1,ymax,ymin,600);
ymin = ymin1;
ymax = ymax1;
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex2f (xmin,0);
gl.glVertex2f (xmax,0);
gl.glVertex2f (0,ymin);
gl.glVertex2f (0,ymax);
gl.glEnd();
}
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
int i;
float t,dt;
float[] v;
36
dt = (tmax - tmin)/pontos;
gl.glColor3f (1.0f, 0.0f, 0.0f);
t = tmin;
for (i = 0; i < pontos; i++) {
v = c(t);
gl.glBegin (GL.GL_POINTS);
gl.glVertex2f (v[0],v[1]);
gl.glEnd();
t = t + dt;
}
}
public void plota_retangulo (GLDrawable drawable, int x1,
int y1, int x2, int y2) {
GL gl = drawable.getGL();
float retxmin,retxmax,retymin,retymax;
retxmin
retxmax
retymin
retymax
=
=
=
=
converte
converte
converte
converte
(x2,xmin,xmax,600);
(x1,xmin,xmax,600);
(y1,ymax,ymin,600);
(y2,ymax,ymin,600);
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(retxmin,retymin);
gl.glVertex2f(retxmin,retymax);
gl.glVertex2f(retxmax,retymax);
gl.glVertex2f(retxmax,retymin);
gl.glEnd();
}
}
3.2.4 –Exercício
Como exercício implemente:
1) Curva ciclóide (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 diferença 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 gráficos de funções em uma variável 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:
theta:
distância orientada da origem ao ponto P.
ângulo entre o eixo polar e o segmento OP.
.
37
As coordenadas polares podem ser relacionadas com as coordenadas retangulares (ou cartesianas) através
das expressões abaixo:
Como exemplo de curvas na forma polar temos:
a) Circunferência de centro na origem e raio 1:
r = 1
b) Reta passando na origem com coeficiente angular m:
c) Circunferência com centro em P(0, 0.5) e raio 1:
d) Cardióide
e) Espiral
f) Rosácea
3.4 – Exemplo: Visualização de Curvas Polares
Para visualizar as curvas polares, podemos utilizar o mesmo programa das curvas paramétricas. Para isso,
considere uma curva dada na forma polar:
Em coordenadas cartesianas temos:
Substituindo r nas duas equações obtemos:
Assim temos uma curva na forma paramétrica. Como exemplo vamos visualizar a curva do cardióide,
alterando apenas a rotina curva do programa anterior:
38
public float[] c(float t) {
float [] v = new float[2];
v[0] = (float) ((1 + Math.cos(t)) * Math.cos(t) );
v[1] = (float) ((1 + Math.cos(t)) * Math.sin(t) );
return v;
}
3.5 – Exercícios
1) Como exercício visualize as demais curvas dadas em coordenadas polares.
2) Visualize a curva dada em coordenadas polares por r = sec(theta).
39
4 – CURVAS IMPLÍCITAS
4.1 – Introdução
Já aprendemos na seção 3 como representar curvas na forma paramétrica. Vamos discutir agora outro tipo
de representação muito utilizada para curvas: a representação implícita.
A equação implícita de uma curva descreve uma relação entre as coordenadas x e y dos pontos que
pertencem a curva. Assim no plano xy a equação implícita de uma curva tem a forma :
Como exemplo a representação implícita de uma circunferência de raio 1 centrado na origem é dado por:
Na forma paramétrica a mesma curva é representada por:
Qual das duas representações é mais vantajosa em termos computacionais ? Na verdade ambas
representações têm vantagens e desvantagens em comparação uma com a outra. Por exemplo, é muito
simples determinar se um ponto
dado pertence ou não a uma curva dada na forma implícita.
Já na forma paramétrica é simples determinar pontos que pertençam a curva, para que se possa fazer uma
representação gráfica da curva (como foi feito na seção anterior). Vamos agora resolver este último
problema para uma curva dada na forma implícita, ou seja, vamos representar graficamente a curva
implícita.
4.2 – Visualização de Curvas Implícitas
Vamos implementar um programa que visualize curvas implícitas. Partindo por exemplo da equação:
Observe que não é simples exibir um conjunto de pontos que pertençam a esta curva. Vamos definir uma
função de duas variáveis
utilizando a equação acima, da seguinte forma:
Assim a curva inicial desejada, será a curva de nível
A estratégia para obter esta curva será a seguinte:
- Vamos estabelecer um domínio
existem ou não pontos da curva nesse domínio).
-
.
no plano como partida (a priori não sabemos se
Em seguida discretizamos este domínio, determinando uma matriz de 10x10 pontos
,
por exemplo.
-
A cada três pontos, definimos um triângulo como na figura abaixo.
-
Para cada ponto
-
Para cada triângulo, observamos os sinais
calculamos
.
= sinal(
) obtidos em cada vértice e temos as
seguintes situações:
-
Se V1 * V2 < 0, então a função se anula em um ponto entre V1 e V2. Este ponto pode ser
aproximado linearmente.
-
Se V1 * V3 < 0, então a função se anula em um ponto entre V1 e V3.
40
-
-
Se V2 * V3 < 0, então a função se anula em um ponto entre V2 e V3.
-
Se V1 = 0, então a função se anula exatamente sobre o vértice V1.
-
Se V2 = 0, então a função se anula exatamente sobre o vértice V2.
-
Se V3 = 0, então a função se anula exatamente sobre o vértice V3.
Considerando que exatamente duas das condições acima se verificaram simultaneamente,
aproximamos a curva nesse triângulo por um segmento de reta unindo os dois pontos obtidos.
4.3 – Programa Curva Implícita
O programa mantém a mesma estrutura do programa curva paramétrica, alterando a classe curva,
conforme abaixo.
implicito.java
import net.java.games.jogl.*;
public class Curva {
public float f(float x,float y) {
return x*x-y*y-1;
//
return x*x+y*y-1;
}
public void curva_implicita(GLDrawable drawable,
float[] xf,float[] yf) {
GL gl = drawable.getGL();
int
j;
int
i = 0;
float t;
float[] x = new float[3];
float[] y = new float[3];
float[] s = new float[3];
gl.glColor3f(0,0,1);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(xf[0],yf[0]);
gl.glVertex2f(xf[1],yf[1]);
gl.glVertex2f(xf[2],yf[2]);
gl.glEnd();
for(j=0;j<3;j++)
s[j] = f(xf[j],yf[j]);
if
}
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++;
((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++;
41
}
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++;
}
}
if
(i == 2) {
gl.glLineWidth(2.0f);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(x[0],y[0]);
gl.glVertex2f(x[1],y[1]);
gl.glEnd();
gl.glLineWidth(1.0f);
}
}
public void plota_curva(GLDrawable drawable) {
GL gl = drawable.getGL();
int i,j;
float[] tx
float[] ty
float x,y;
float dx =
float dy =
= new float[3];
= new float[3];
(xmax - xmin)/pontos;
(ymax - ymin)/pontos;
gl.glColor3f(1.0f,0.0f,0.0f);
x = xmin;
for(i=0;i<pontos;i++)
{
y = ymin;
for(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;
curva_implicita(drawable,tx,ty);
tx[0] = x + dx; tx[1] = x;
tx[2] = x + dx;
ty[0] = y + dy; ty[1] = y + dy; ty[2] = y;
curva_implicita(drawable,tx,ty);
y += dy;
}
x += dx;
}
}
}
4.4 –Exercício
1) Como exercício implemente as seguintes curvas implícitas:
42
a)
b)
. c)
.
.
d)
2) Implemente no programa uma rotina que imprima simultaneamente varias curvas de nivel de uma
mesma função
, ou seja
. Por exemplo,
.
5 – RETAS E POLÍGONOS NO OPENGL
5.1 – Retas e Polígonos
Além 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 .gl.glBegin(...) e finalizando com
gl.glEnd(...), por exemplo para o GL_LINES temos:
gl.glBegin(GL_LINES);
gl.glVertex2f(1.0,1.0);
gl.glVertex2f(1.0,2.0);
gl.glVertex2f(2.0,-2.0);
...
gl.glEnd();
GL.GL_POINTS
GL.GL_LINES
GL.GL_POLYGON
GL.GL_TRIANGLES
GL.GL_QUADS
GL.GL_LINE_STRIP
GL.GL_LINE_LOOP
GL.GL_TRIANGLE_STRIP
GL.GL_TRIANGLE_FAN
GL.GL_QUAD_STRIP
Pontos individuais.
Reta entre dois pontos.
Polígono convexo .
Tripla de vértices é interpretado como um triângulo.
Conjunto de quatro vértices interpretado como quadrilátero.
Sequência de retas.
Idêntico ao anterior, porém com uma reta unindo o primeiro e último vértice.
Lista de triângulos.
Lista de triângulos com o primeiro vértice em comum.
Lista de quadriláteros.
43
5.2 – Exemplo: Visualização dos Métodos Numéricos de Integração
Como exemplo de aplicação dos novos objetos vamos visualizar alguns métodos numéricos de integração
apresentados no capitulo 1.
Class Integral.java
import net.java.games.jogl.GL;
import net.java.games.jogl.GLDrawable;
public class Integral {
float
float
funcao
int
int
int
a;
b;
f;
particao;
visual;
metodo; //
//
//
//
0
1
2
3
-
ponto a esquerda
trapezio
Simpson
Monte Carlo
public Integral (float xi,float xf,int part, int met,funcao func) {
a = xi;
b = xf;
particao = part;
metodo
= met ;
f
= func;
visual
= 1;
}
public void
{
GL
int
float
float
Integral_esquerda(GLDrawable drawable)
gl = drawable.getGL();
i ;
x,y;
dx;
dx = (b-a)/particao;
x = a;
for(i=0; i < particao; i++)
{
y = f.f(x);
gl.glColor3f(1.0f,1.0f,0.0f);
if (visual == 0)
gl.glBegin(GL.GL_LINE_LOOP);
44
else
gl.glBegin(GL.GL_POLYGON);
gl.glVertex2f(x,y);
gl.glVertex2f(x+dx,y);
gl.glVertex2f(x+dx,0);
gl.glVertex2f(x,0);
gl.glEnd();
x = x+dx;
}
}
}
45
6 – PROCESSAMENTO DE IMAGEM
6.1 – Introdução
Filtro da media e Gradiente
Imagem.java
import net.java.games.jogl.*;
import java.io.*;
public class Imagem {
float xmin,xmax,ymin,ymax;
Pilha w;
int dimx,dimy,range;
int[][] image;
String file;
Imagem() {
xmin = ymin = 0;
xmax = ymax = 512;
w = new Pilha();
}
Imagem(float xm,float ym,float xM,float yM,String file_name)
{
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
w = new Pilha();
file = file_name;
}
Imagem(String s) {
xmin = 0; ymin = 511;
xmax = 511; ymax = 0;
w = new Pilha();
file = s;
try {
Reader q = new FileReader(s);
int ch;
String p;
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch )) {
ch = q.read();
if
(Character.isWhitespace((char)
ch))
break;
p += String.valueOf((char)ch);
}
dimx = Integer.parseInt(p);
while(Character.isWhitespace((char) ch))
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch)) {
ch = q.read();
46
if
(Character.isWhitespace((char)
ch))
break;
p += String.valueOf((char)ch);
}
dimy = Integer.parseInt(p);
while(Character.isWhitespace((char) ch))
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch)) {
ch = q.read();
if
(Character.isWhitespace((char)
ch))
break;
p += String.valueOf((char)ch);
}
range = Integer.parseInt(p);
image = new int[dimx][dimy];
System.out.println(" " + dimx + " " + dimy + " " +
range);
for (int i = 0; i<dimx; i++) {
for(int j = 0; j<dimy; j++) {
while(Character.isWhitespace((char) ch))
ch = q.read();
p = String.valueOf((char)ch);
while
(!Character.isWhitespace((char)
ch)) {
if
ch = q.read();
(Character.isWhitespace((char)
ch))
break;
p += String.valueOf((char)ch);
//
}
image[i][j] = Integer.parseInt(p);
System.out.print(" " + p);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void media() {
int i,j;
int[][] B = new int[dimx][dimy];
for(i=0;i<dimx;i++)
for(j=0;j<dimy;j++)
B[i][j] = image[i][j];
for(i=1;i<dimx-1;i++)
for(j=1;j<dimy-1;j++) {
image[i][j]
=
(B[i-1][j-1]+B[i-1][j]+B[i1][j+1]+B[i][j-1]+B[i][j]+B[i][j+1]+B[i+1][j1]+B[i+1][j]+B[i+1][j+1])/9;
}
}
public void filtro_gradiente()
47
{
int i,j;
int[][] B = new int[dimx][dimy];
int[][] C = new int[dimx][dimy];
int[][] D = new int[dimx][dimy];
for(i=0;i<dimx;i++)
for(j=0;j<dimy;j++)
B[i][j] = image[i][j];
for(i=1;i<dimx-1;i++)
for(j=1;j<dimy-1;j++) {
C[i][j] = (B[i-1][j-1]
-B[i-1][j+1]
+2*B[i][j-1]
-2*B[i][j+1] +B[i+1][j-1]
B[i+1][j+1])/4;
D[i][j]
=
(B[i-1][j-1]+2*B[i-1][j]+B[i-1][j+1]
-B[i+1][j-1]-2*B[i+1][j] -B[i+1][j+1])/4;
image[i][j] = (int)Math.sqrt(D[i][j] * D[i][j] +
C[i][j]*C[i][j]);
}
}
public void
{
int i,j;
int[][] B
int[][] C
int[][] D
filtro_mediana()
= new int[dimx][dimy];
= new int[dimx][dimy];
= new int[dimx][dimy];
for(i=0;i<dimx;i++)
for(j=0;j<dimy;j++)
B[i][j] = image[i][j];
for(i=1;i<dimx-1;i++)
for(j=1;j<dimy-1;j++) {
C[i][j] = (B[i-1][j-1]
-B[i-1][j+1]
+2*B[i][j-1]
-2*B[i][j+1] +B[i+1][j-1]
B[i+1][j+1])/4;
D[i][j]
=
(B[i-1][j-1]+2*B[i-1][j]+B[i-1][j+1]
-B[i+1][j-1]-2*B[i+1][j] -B[i+1][j+1])/4;
image[i][j] = (int)Math.sqrt(D[i][j] * D[i][j] +
C[i][j]*C[i][j]);
}
}
public
public
public
public
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
return
return
return
return
xmin;
ymin;
xmax;
ymax;
}
}
}
}
public float converte(float p, float min, float max, int
dim) {
float x;
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
48
}
public void recalcula_dominio (float xv_1,float yv_1,float
xv_2,float yv_2) {
float xmin1,xmax1;
float ymin1,ymax1;
Window W = new Window(xmin,ymin,xmax,ymax);
xmin1
xmax1
ymin1
ymax1
=
=
=
=
converte(xv_1,xmin,xmax,600);
converte(xv_2,xmin,xmax,600);
converte(yv_2,ymax,ymin,600);
converte(yv_1,ymax,ymin,600);
w.push(W);
xmin
xmax
ymin
ymax
=
=
=
=
xmin1;
xmax1;
ymin1;
ymax1;
}
public void retorna_dominio () {
Window W = w.pop();
xmin
xmax
ymin
ymax
=
=
=
=
W.get_xmin();
W.get_xmax();
W.get_ymin();
W.get_ymax();
}
public void draw_image(GLDrawable draw) {
GL gl = draw.getGL();
for (int i=0;i<dimx;i++)
for (int j=0;j<dimy;j++) {
gl.glColor3f(image[i][j]/(float)range,image[i][j]/(float)range,i
mage[i][j]/(float)range);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2d(j,i);
gl.glEnd();
}
}
public void plota_retangulo (GLDrawable drawable, int x1,
int y1, int x2, int y2) {
GL gl = drawable.getGL();
float retxmin,retxmax,retymin,retymax;
retxmin
retxmax
retymin
retymax
=
=
=
=
converte
converte
converte
converte
(x2,xmin,xmax,600);
(x1,xmin,xmax,600);
(y1,ymax,ymin,600);
(y2,ymax,ymin,600);
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(retxmin,retymin);
gl.glVertex2f(retxmin,retymax);
gl.glVertex2f(retxmax,retymax);
gl.glVertex2f(retxmax,retymin);
gl.glEnd();
}
}
49
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
import java.util.*;
import java.io.*;
public class main {
static Imagem g;
static int mov = 0;
/*
Detecta
movimento
static int xv1, yv1, xv2, yv2;
/*
Domínio
da
do mouse */
nova
janela */
static
GLCanvas
canvas
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
=
public static void main(String[] args) throws IOException
{
Frame frame
= new Frame("Funcao");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion()
);
canvas.addKeyListener
( new JoglKey() );
frame.add(canvas);
frame.setSize(512, 512);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
g = new Imagem("gauss.pgm");
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(g.get_xmin(),g.get_xmax(),g.get_ymin(),g.get_ymax
());
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT
|
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
g.draw_image(drawable);
50
if (mov == 1) {
System.out.println("mov = 1");
g.plota_retangulo
(drawable,
xv1,yv1,xv2,yv2);
}
gl.glFlush();
}
public
void
displayChanged(GLDrawable
boolean modeChanged, boolean deviceChanged) {
}
drawable,
public void reshape(GLDrawable drawable, int x, int
y, int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Entra");
xv1 = e.getX();
yv1 = e.getY();
mov = 1;
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Sai");
xv2 = e.getX();
yv2 = e.getY();
mov = 0;
g.recalcula_dominio (xv1,yv1,xv2,yv2);
canvas.display();
}
if (e.getButton()==1) {
System.out.println("Volta Zoom");
g.retorna_dominio();
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
51
static
MouseMotionListener {
class
JoglMouseMotion
implements
public void mouseDragged(MouseEvent e) {
if
((e.getModifiers()
InputEvent.BUTTON3_MASK) != 0) {
xv2 = e.getX();
yv2 = e.getY();
System.out.println("Dragged:
e.getX() + "," + e.getY());
canvas.display();
}
&
"
+
}
public void mouseMoved(MouseEvent e) {
System.out.println("Moved: " + e.getX() + ","
//
+ e.getY());
}
}
static class JoglKey implements
KeyListener {
public void keyPressed (KeyEvent e)
{
if (e.getKeyChar() == 'g' || e.getKeyChar() ==
'G') {
g.filtro_gradiente();
canvas.display();
System.out.println("Gradiente");
}
if (e.getKeyChar() == 'm' || e.getKeyChar() ==
'M') {
System.out.println("Media");
g.media();
canvas.display();
}
}
public void keyReleased(KeyEvent e) {
//
System.out.println("Released");
}
public void keyTyped (KeyEvent e) {
//
System.out.println("Typed");
}
}
}
52
7 – FRACTAIS
7.1 – Conjuntos auto-semelhantes
Definição: Um subconjunto fechado e limitado
expresso na forma:
onde
fator de escala
, é dito ser auto-semelhante se pode ser
são conjuntos não sobrepostos e cada um deles é congruente a
(
por mesmo
).
Exemplo 1: Um triângulo pode ser expresso como a união de quatro triângulos congruentes e não
sobrepostos. Cada um dos triângulos é congruente ao original por um fator
e o triângulo é um
conjunto auto-semelhante com k = 4.
Exemplo 2 (Triângulo de Sierpinski): Este exemplo foi apresentado pelo matemático Waclaw Sierpinski
(1882-1969). Neste exemplo, partindo de um triângulo, temos a união de três triângulos não sobrepostos
53
(portanto
), cada um dos quais é congruente ao original com um fator de escala
. Em
seguida, o processo se repete para cada um dos três triângulos, e assim sucessivamente.
7.2 – Dimensão Hausdorff e o conceito de fractal
Definição: A dimensão Hausdorff de um conjunto auto-semelhante é definida por:
onde
denota a dimensão Hausdorff.
Assim, considerando os exemplos anteriores teremos:
Exemplo 1:
Exemplo 2:
Observe que no exemplo 1, a dimensão Hausdorff, coincide com a dimensão topológica usual, uma vez
que uma região em
tem dimensão 2. Porém no exemplo 2, obtemos uma dimensão não inteira para o
triângulo de Sierpinski. Partindo desta observação, Mandelbrot sugeriu em 1977 a seguinte definição:
Definição: Um fractal é um subconjunto do espaço euclidiano cuja dimensão Hausdorff é diferente da
dimensão topológica.
7.3 – Exemplos de fractais
Alguns dos principais exemplos que apresentaremos nesta seção foram gerados utilizando composição de
transformações de rotação e escala seguido de uma possível translação. O formato geral da função é dado
por:
54
onde
7.3.1- Triângulo de Sierpinski
Para obter o triângulo de Sierpinski, utilizaremos uma aplicação que a partir de um triângulo, obtém três
novos triângulos conforme a figura abaixo:
Assim temos três funções, uma associada a cada triângulo:
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
import java.util.*;
import java.io.*;
public class main {
static Fractal g;
static int mov = 0; /* Detecta movimento do mouse */
static int xv1, yv1, xv2, yv2; /* Domínio da nova janela */
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
55
public static void main(String[] args) throws IOException {
Frame frame
= new Frame("Funcao");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addKeyListener
( new JoglKey() );
frame.add(canvas);
frame.setSize(600,600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
g = new Fractal();
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(g.get_xmin(),g.get_xmax(),g.get_ymin(),g.get_ymax())
;
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
g.plota_fractal(drawable);
if (mov == 1) {
System.out.println("mov = 1");
g.plota_retangulo (drawable,
xv1,yv1,xv2,yv2);
}
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y,
int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
56
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Entra");
xv1 = e.getX();
yv1 = e.getY();
mov = 1;
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==3) {
System.out.println("Sai");
xv2 = e.getX();
yv2 = e.getY();
mov = 0;
g.recalcula_dominio (xv1,yv1,xv2,yv2);
canvas.display();
}
if (e.getButton()==1) {
System.out.println("Volta Zoom");
g.retorna_dominio();
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
static class JoglMouseMotion implements
{
MouseMotionListener
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) {
xv2 = e.getX();
yv2 = e.getY();
System.out.println("Dragged: " + e.getX() + "," +
e.getY());
canvas.display();
}
}
public void mouseMoved(MouseEvent e) {
}
}
static class JoglKey implements
KeyListener {
public void keyPressed (KeyEvent e) {
57
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped (KeyEvent e) {
}
}
}
Fractal.java
import net.java.games.jogl.*;
import java.io.*;
public class Fractal {
float
Pilha
int
float
xmin,xmax,ymin,ymax;
w;
n;
x1,y1,x2,y2,x3,y3;
Fractal() {
xmin = ymin = 0;
xmax = ymax = 1;
w = new Pilha();
x1 = 0.0f; y1 = 0.0f;
x2 = 0.0f; y2 = 1.0f;
x3 = 1.0f; y3 = 0.0f;
n = 7;
}
Fractal(float xm,float ym,float xM,float yM,
float _x1, float _y1,
float _x2, float _y2,
float _x3, float _y3,
int iter) {
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
n = iter;
x1 = _x1; y1 = _y1;
x2 = _x2; y2 = _y2;
x3 = _x3; y3 = _y3;
}
public
public
public
public
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
return
return
return
return
xmin;
ymin;
xmax;
ymax;
}
}
}
}
58
public float converte(float p, float min, float max, int dim) {
float x;
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
public void recalcula_dominio (float xv_1,float
xv_2,float yv_2) {
float xmin1,xmax1;
float ymin1,ymax1;
Window W = new Window(xmin,ymin,xmax,ymax);
xmin1
xmax1
ymin1
ymax1
=
=
=
=
yv_1,float
converte(xv_1,xmin,xmax,600);
converte(xv_2,xmin,xmax,600);
converte(yv_2,ymax,ymin,600);
converte(yv_1,ymax,ymin,600);
w.push(W);
xmin
xmax
ymin
ymax
=
=
=
=
xmin1;
xmax1;
ymin1;
ymax1;
}
public void retorna_dominio () {
Window W = w.pop();
xmin
xmax
ymin
ymax
=
=
=
=
W.get_xmin();
W.get_xmax();
W.get_ymin();
W.get_ymax();
}
public float[] transform(float x,float y,float e,float f)
{
float[] v = new float[2];
v[0] = x/2 + e;
v[1] = y/2 + f;
return v;
}
public void plota_fractal(GLDrawable draw) {
plota_auto_semelhante(draw,x1,y1,x2,y2,x3,y3,n);
}
public void plota_auto_semelhante(GLDrawable draw,
float x0,float y0,
float x1,float y1,
float x2,float y2,
int n)
{
GL gl = draw.getGL();
int
i,j;
float[][] x = new float[3][3];
float[][] y = new float[3][3];
float[] e
= new float[3];
59
float[] f = new float[3];
float[] v;
e[1] = 0.5f;
f[2] = 0.5f;
for(i=0;i<3;i++) {
x[i][0] =
y[i][0] =
x[i][1] =
y[i][1] =
x[i][2] =
y[i][2] =
x0;
y0;
x1;
y1;
x2;
y2;
}
for(i=0;i<3;i++)
for (j=0;j<3;j++) {
System.out.println("antes
//
y[j][i]);
=
"
+
x[j][i]
+
"
"
+
v = transform(x[j][i],y[j][i],e[j],f[j]);
x[j][i] = v[0];
y[j][i] = v[1];
System.out.println("depois = " +
x[j][i] + " " +
//
y[j][i]);
}
if
(n == 0) {
for (i=0;i<3;i++) {
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_TRIANGLES);
gl.glVertex2f(x[i][0],y[i][0]);
gl.glVertex2f(x[i][1],y[i][1]);
gl.glVertex2f(x[i][2],y[i][2]);
gl.glEnd();
}
return;
}
else {
for(i=0;i<3;i++)
plota_auto_semelhante(draw,x[i][0],y[i][0],x[i][1],y[i][1],
x[i][2],y[i][2],n-1);
}
}
public void plota_retangulo (GLDrawable drawable, int x1, int
y1, int x2, int y2) {
GL gl = drawable.getGL();
float retxmin,retxmax,retymin,retymax;
retxmin
retxmax
retymin
retymax
=
=
=
=
converte
converte
converte
converte
(x2,xmin,xmax,600);
(x1,xmin,xmax,600);
(y1,ymax,ymin,600);
(y2,ymax,ymin,600);
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(retxmin,retymin);
gl.glVertex2f(retxmin,retymax);
gl.glVertex2f(retxmax,retymax);
gl.glVertex2f(retxmax,retymin);
gl.glEnd();
60
}
}
7.3.2- Triângulo de Sierpinski utilizando Monte Carlo
Este método utiliza iterações randômicas para gerar fractais utilizando o seguinte processo:
1- Defina as k transformações
(como descrito na seção 6.3) que descrevem o objeto a ser gerado.
2- Escolha um ponto arbitrário
.
3- Escolha arbitrariamente uma das k transformações e aplique no ponto escolhido:
4- Prossiga escolhendo aleatoriamente uma das k transformações e aplique no ultimo ponto obtido:
O módulo main.java, necessita apenas das alterações no display e no nome da classe.
Fractal.java
// Monte Carlo
import net.java.games.jogl.*;
import java.io.*;
import java.util.*;
public class Fractal {
float
Pilha
int
float
float
float
xmin,xmax,ymin,ymax;
w;
n;
x1,y1,x2,y2,x3,y3;
x0;
y0;
Fractal() {
xmin = ymin = 0;
xmax = ymax = 1;
w = new Pilha();
x1 = 0.0f; y1 = 0.0f;
x2 = 0.0f; y2 = 1.0f;
x3 = 1.0f; y3 = 0.0f;
n = 70000;
x0 = 0;
y0 = 0;
}
Fractal(float xm,float ym,float xM,float yM,
float _x1, float _y1,
float _x2, float _y2,
float _x3, float _y3,
int iter,
float _x0,float _y0) {
xmin = xm;
ymin = ym;
61
xmax = xM;
ymax = yM;
n = iter;
x1 = _x1; y1 = _y1;
x2 = _x2; y2 = _y2;
x3 = _x3; y3 = _y3;
x0 = _x0;
y0 = _y0;
}
public float[] transform(float x,float y,float e,float f)
{
float[] v = new float[2];
v[0] = x/2 + e;
v[1] = y/2 + f;
return v;
}
public void plota_fractal(GLDrawable draw)
{
GL gl = draw.getGL();
int
i,j;
float[][] x = new float[3][4];
float[][] y = new float[3][4];
Random rn = new Random();
float[] e = new float[3];
float[] f = new float[3];
float[] v;
e[1] = 0.5f;
f[2] = 0.5f;
for(i=0;i<n;i++) {
j = (int) (3.0 * rn.nextDouble());
j = ( j > 2) ? 2 : j;
v = transform(x0,y0,e[j],f[j]);
x0 = v[0];
y0 = v[1];
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2f(x0,y0);
gl.glEnd();
}
}
...
}
7.3.3- “Fern”
import net.java.games.jogl.*;
import java.io.*;
import java.util.*;
62
public class Fractal {
float xmin,xmax,ymin,ymax;
Pilha w;
int
n;
Fractal() {
xmin = ymin = 0;
xmax = ymax = 1;
w = new Pilha();
n = 3;
}
Fractal(float xm,float ym,float xM,float yM,
float _x1, float _y1,
float _x2, float _y2,
float _x3, float _y3,
int iter,
float _x0,float _y0) {
xmin = xm;
ymin = ym;
xmax = xM;
ymax = yM;
n = iter;
}
public float[] transform(float a11,float a12,float a21,float
a22,float e,float f,float x1,float y1)
{
float[] v = new float[2];
v[0] = a11 * x1 + a12 * y1 + e;
v[1] = a21 * x1 + a22 * y1 + f;
return v;
}
public void plota_fractal(GLDrawable draw)
{
float[] x = new float[4];
float[] y = new float[4];
x[1] = x[2] = 1.0f;
y[2] = y[3] = 1.0f;
plota_auto_semelhante(draw,x,y,n);
}
public void plota_auto_semelhante(GLDrawable draw,float[]
x,float[] y,int ni)
{
GL gl = draw.getGL();
int
i,j;
float[][] xx = new float[4][4];
float[][] yy = new float[4][4];
float[] v;
63
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
xx[i][j] = x[j];
yy[i][j] = y[j];
}
if (ni == 0) {
gl.glColor3f(0.0f,1.0f,0.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(x[0],y[0]);
gl.glVertex2f(x[1],y[1]);
gl.glVertex2f(x[2],y[2]);
gl.glVertex2f(x[3],y[3]);
gl.glEnd();
return;
}
else {
for(i=0;i<4;i++) {
v = transform( 0.20f,-0.26f, 0.23f,
0.22f,0.400f, 0.045f,xx[0][i],yy[0][i]);
xx[0][i] = v[0]; yy[0][i] = v[1];
v = transform( 0.85f, 0.04f,-0.04f,
0.85f,0.075f, 0.180f,xx[1][i],yy[1][i]);
xx[1][i] = v[0]; yy[1][i] = v[1];
v = transform( 0.00f, 0.00f, 0.00f,
0.16f,0.500f, 0.000f,xx[2][i],yy[2][i]);
xx[2][i] = v[0]; yy[2][i] = v[1];
v = transform(-0.15f, 0.28f, 0.26f,
0.24f,0.575f,-0.086f,xx[3][i],yy[3][i]);
xx[3][i] = v[0]; yy[3][i] = v[1];
}
plota_auto_semelhante(draw,xx[0],yy[0],ni-1);
plota_auto_semelhante(draw,xx[1],yy[1],ni-1);
plota_auto_semelhante(draw,xx[2],yy[2],ni-1);
plota_auto_semelhante(draw,xx[3],yy[3],ni-1);
}
}
...
}
64
7.4 – Conjunto de Julia
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class Julia {
int DIM;
float dx,dy;
float xc,yc,xcl,ycl,xc1,yc1;
float xminj,yminj,xmaxj,ymaxj;
float xminm,yminm,xmaxm,ymaxm;
int n;
int m;
int lk;
Pilha w = new Pilha();
int[][] M ;
int[][] o ;
Julia() {
M = new int[600][600];
o = new int[600][600];
DIM = 600;
n = 600;
xc1 = 1;
yc1 = 1;
m = 100;
xminm = yminm = xminj = yminj = -2;
xmaxm = ymaxm = xmaxj = ymaxj = 2;
dx=(xmaxj-xminj)/n;
dy=(ymaxj-yminj)/n;
}
public void constant(float x,float y)
{
float t2;
t2=(float)x/DIM;
xc1=xminm+t2*(xmaxm-xminm);
t2=(float)y/DIM;
yc1=(ymaxm-t2*(ymaxm-yminm));
System.out.println("\n\n----------\nConstante Atual: " + xc1 + “ , “ +
yc1);
}
public
public
public
public
float
float
float
float
get_xmin()
get_ymin()
get_xmax()
get_ymax()
{
{
{
{
if
if
if
if
(lk
(lk
(lk
(lk
==
==
==
==
0)
0)
0)
0)
return
return
return
return
xminj;
yminj;
xmaxj;
ymaxj;
else
else
else
else
return
return
return
return
xminm;}
yminm;}
xmaxm;}
ymaxm;}
public void set_m(int i) {
if (i == 0)
m += 10;
else
m -= 10;
System.out.println("iter = " + m);
}
public int getDIM() { return DIM; }
public double[] cores (float ca){
double[] result = new double[3];
double s=m/5.0;
if( ca <= s)
{
result[0]=1.0;
result[1]=ca/s;
result[2]=0.0;
}
else if( ca<=2*s )
{
result[0]=1.0-(ca-s)/s;
result[1]=1.0;
65
result[2]=0.0;
}
else if( ca<=3*s )
{
result[0]=0.0;
result[1]=1.0;
result[2]=(ca-2*s)/s;
}
else if( ca<=4*s )
{
result[0]=0.0;
result[1]=1.0-(ca-3*s)/s;
result[2]=1.0;
}
else if( ca> 4*s)
{
result[0]=(ca-4*s)/s;
result[1]=0.0;
result[2]=1.0;
}
return result;
}
public void plota_indicador_constante(GLDrawable draw)
{
GL gl = draw.getGL();
gl.glColor3f(1,1,1);
gl.glLineWidth(2);
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(xc1,yc1+((ymaxm-yminm)/20));
gl.glVertex2f(xc1,yc1+((ymaxm-yminm)/40));
gl.glVertex2f(xc1,yc1-((ymaxm-yminm)/40));
gl.glVertex2f(xc1,yc1-((ymaxm-yminm)/20));
gl.glVertex2f(xc1-((xmaxm-xminm)/20),yc1);
gl.glVertex2f(xc1-((xmaxm-xminm)/40),yc1);
gl.glVertex2f(xc1+((xmaxm-xminm)/40),yc1);
gl.glVertex2f(xc1+((xmaxm-xminm)/20),yc1);
gl.glEnd();
}
public void set_lk()
{
lk = (lk + 1) %2;
System.out.print(lk);
}
public int get_lk()
{
return lk;
}
public void init()
{
if (lk == 0) {
dx=Math.abs(xmaxj-xminj)/n;
dy=Math.abs(ymaxj-yminj)/n;
}
else {
dx=Math.abs(xmaxm-xminm)/n;
dy=Math.abs(ymaxm-yminm)/n;
}
xc=xc1;
yc=yc1;
}
public void plota_fractal(GLDrawable draw)
{
float xmin,ymin,xmax,ymax;
GL gl = draw.getGL();
int x,y,k;
float R;
float i,j,xz,yz,temp;
66
double[] cor;
for(x=0;x<n;x++)
{
for(y=0;y<n;y++)
{
M[x][y] = 0;
o[x][y] =0;
}
}
if (lk == 0)
{
xmin
xmax
ymin
ymax
}
else
{
xmin
xmax
ymin
ymax
}
=
=
=
=
xminj;
xmaxj;
yminj;
ymaxj;
=
=
=
=
xminm;
xmaxm;
yminm;
ymaxm;
i = xmin;
for(x=0;x<2*n;x++)
{
i = i+dx/2;
j = ymin;
for(y=0;y<2*n;y++)
{
j = j + dy/2;
if(lk==0)
{
xz=i;
yz=j;
k=0;
}
else
{
xz=0;
yz=0;
k=0;
xc=i;
yc=j;
}
if( ((xc*xc) + (yc*yc))>4)
{
R=(xc*xc) + (yc*yc);
}
else{
R=4.0f;
}
for(k=0;k<m;k++)
{
if((xz*xz)+(yz*yz)>R)/*Verifica se o
ponto escapou
e plota na cor de acordo com
o n˙mero de iteraà ıes
necess·rio*/
{
M[x/2][y/2] += k;
o[x/2][y/2]++;
break;
}
else
{
temp=((xz*xz) - (yz*yz) +
xc);
yz=((2*xz*yz) + yc);
xz=temp;
}
67
}
}
}
for(x=0;x<600;x++)
{
for(y=0;y<600;y++)
{
cor =
cores((float)M[x][y]/o[x][y]);
gl.glColor3d(cor[0],cor[1],cor[2]);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2i(x,y);
gl.glEnd();
}
}
}
public void recalcula_dominio (float xv_1,float yv_1,
float xv_2,float yv_2) {
float xmin1,xmax1;
float ymin1,ymax1;
if (lk == 0) {
Window W = new Window(xminj,yminj,xmaxj,ymaxj);
xmin1 = converte(xv_1,xminj,xmaxj,DIM);
xmax1 = converte(xv_2,xminj,xmaxj,DIM);
ymin1 = converte(yv_2,ymaxj,yminj,DIM);
ymax1 = converte(yv_1,ymaxj,yminj,DIM);
w.push(W);
xminj = xmin1; xmaxj = xmax1;
yminj = ymin1; ymaxj = ymax1;
}
else {
Window W = new Window(xminm,yminm,xmaxm,ymaxm);
xmin1 = converte(xv_1,xminm,xmaxm,DIM);
xmax1 = converte(xv_2,xminm,xmaxm,DIM);
ymin1 = converte(yv_2,ymaxm,yminm,DIM);
ymax1 = converte(yv_1,ymaxm,yminm,DIM);
w.push(W);
xminm = xmin1; xmaxm = xmax1;
yminm = ymin1; ymaxm = ymax1;
}
}
public float converte(float p, float min, float max, int dim) {
float x;
x = min + ( (p * (max-min))/(dim - 1) );
return (x);
}
public void retorna_dominio () {
Window W = w.pop();
if (lk == 0) {
xminj = W.get_xmin();
xmaxj = W.get_xmax();
yminj = W.get_ymin();
ymaxj = W.get_ymax();
}
else {
xminm = W.get_xmin();
xmaxm = W.get_xmax();
yminm = W.get_ymin();
ymaxm = W.get_ymax();
}
}
68
}
69
CAPÍTULO III – VISUALIZAÇÃO E APLICAÇÕES GRÁFICAS 3D ____________ 2
1- TRANSFORMAÇÕES DE VISUALIZAÇÃO ________________________________ 2
1.1
- Introdução ____________________________________________________________ 2
1.2
– Transformações _______________________________________________________ 6
1.3
- Comandos de Auxílio ___________________________________________________ 6
1.4- Exemplo: cubo unitário ____________________________________________________ 7
1.5 - Transformações de Modelagem e Visualização_________________________________ 9
1.5.1- Translação ____________________________________________________________________ 9
1.5.2- Rotação ______________________________________________________________________ 9
1.5.3- Escala _______________________________________________________________________ 9
1.5.4-Exemplo _____________________________________________________________________ 10
1.6- Projeção Ortográfica _____________________________________________________ 12
1.7- Projeção Perspectiva ______________________________________________________ 12
1.8- Ângulos de Euler _________________________________________________________ 13
1.8 - Criando um Ambiente de Visualização 3D ___________________________________ 14
1.8.1- Módulo Básico de Visualização __________________________________________________ 14
1.8.2- Alterando os ângulos de Euler ___________________________________________________ 16
1.9 – Visualização de gráfico de funções
_______________________________ 19
2- ILUMINAÇÃO _______________________________________________________ 24
2.1– Criando Fontes de Luz ____________________________________________________ 27
2.1.1– Cor ________________________________________________________________________ 27
2.1.2– Posição _____________________________________________________________________ 28
2.2– Selecionando o Modelo de Iluminação _______________________________________ 28
2.2.1- Luz Ambiente Global __________________________________________________________
2.2.2 – Posição do observador local ou no infinito _________________________________________
2.2.3 – Iluminação nos dois lados das faces ______________________________________________
2.2.4 – Habilitando a iluminação_______________________________________________________
28
28
28
28
2.3– Selecionando as Propriedades do Material ___________________________________ 29
2.4– Exemplo 1 ______________________________________________________________ 29
2.5– Comando glLookAt ______________________________________________________ 34
2.6 – Visualizando as normais __________________________________________________ 36
3- SUPERFÍCIES PARAMETRIZADAS ____________________________________ 37
3.1– Visualização de superfícies na forma paramétrica _____________________________ 37
3.2– Exercícios_______________________________________________________________ 39
4- SUPERFÍCIES IMPLÍCITAS ___________________________________________ 41
5- TEXTURA ___________________________________________________________ 48
1
CAPÍTULO III – VISUALIZAÇÃO E APLICAÇÕES
GRÁFICAS 3D
1- Transformações de Visualização
1.1 - Introdução
Nosso objetivo nesta seção é descrever a geração de uma imagem bi-dimensional partindo de um objeto tridimensional. Para isso vamos partir de um exemplo: um cubo. A idéia é construir algum tipo de visualização
deste cubo, que nos transmita a sensação de estar visualizando um objeto 3-dimensional.
Vamos considerar o cubo da figura abaixo:
As coordenadas dos vértices deste cubo são:
v0
v1
v2
v3
(0,0,0)
(1,0,0)
(1,1,0)
(0,1,0)
v4
v5
v6
v7
(0,0,1)
(1,0,1)
(1,1,1)
(0,1,1)
Para visualizar este modelo, uma primeira estratégia seria definir uma projeção de nosso modelo 3D para o bidimensional.
/* * * * * * * * * * * * * * * * * */
/* Modulo: main.java
*/
/* * * * * * * * * * * * * * * * * */
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static cubo Q;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Cubo");
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
Q = new cubo();
}
public void display(GLDrawable drawable) {
2
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glLoadIdentity();
glu.gluOrtho2D(-2,2,-2,2);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
Q.render_cubo(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {}
public void reshape(GLDrawable drawable, int x, int y, int
width, int height) {}
}
}
/* * * * * * * * * * * * * * * * */
/* Modulo: cubo.java
*/
/* * * * * * * * * * * * * * * * */
import net.java.games.jogl.*;
public class cubo {
float[][] P;
cubo() {
P = new float[8][3];
unitario();
}
public void unitario() {
P[0][0] = 0;
P[0][1] = 0;
P[0][2] = 0;
P[1][0] = 1;
P[1][1] = 0;
P[1][2] = 0;
P[2][0] = 1;
P[2][1] = 1;
P[2][2] = 0;
P[3][0] = 0;
P[3][1] = 1;
P[3][2] = 0;
}
P[4][0]
P[4][1]
P[4][2]
P[5][0]
P[5][1]
P[5][2]
P[6][0]
P[6][1]
P[6][2]
P[7][0]
P[7][1]
P[7][2]
=
=
=
=
=
=
=
=
=
=
=
=
0;
0;
1;
1;
0;
1;
1;
1;
1;
0;
1;
1;
public void render_cubo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(P[0][0],P[0][1]);
gl.glVertex2f(P[1][0],P[1][1]);
gl.glVertex2f(P[2][0],P[2][1]);
3
gl.glVertex2f(P[3][0],P[3][1]);
gl.glEnd();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(P[4][0],P[4][1]);
gl.glVertex2f(P[5][0],P[5][1]);
gl.glVertex2f(P[6][0],P[6][1]);
gl.glVertex2f(P[7][0],P[7][1]);
gl.glEnd();
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(P[0][0],P[0][1]);
gl.glVertex2f(P[4][0],P[4][1]);
gl.glVertex2f(P[1][0],P[1][1]);
gl.glVertex2f(P[5][0],P[5][1]);
gl.glVertex2f(P[2][0],P[2][1]);
gl.glVertex2f(P[6][0],P[6][1]);
gl.glVertex2f(P[3][0],P[3][1]);
gl.glVertex2f(P[7][0],P[7][1]);
gl.glEnd();
}
}
Vamos aplicar uma rotação sobre os vértices do cubo e verificar o resultado. Para isso acrescentaremos um
método que aplica uma rotação em cada um dos vértices do cubo.
import net.java.games.jogl.*;
public class cubo {
float[][] P;
cubo() {
P = new float[8][3];
unitario();
}
public void
P[0][0] =
P[0][1] =
P[0][2] =
P[1][0] =
P[1][1] =
P[1][2] =
P[2][0] =
P[2][1] =
P[2][2] =
P[3][0] =
P[3][1] =
P[3][2] =
}
unitario() {
0;
P[4][0]
0;
P[4][1]
0;
P[4][2]
1;
P[5][0]
0;
P[5][1]
0;
P[5][2]
1;
P[6][0]
1;
P[6][1]
0;
P[6][2]
0;
P[7][0]
1;
P[7][1]
0;
P[7][2]
=
=
=
=
=
=
=
=
=
=
=
=
0;
0;
1;
1;
0;
1;
1;
1;
1;
0;
1;
1;
public void rotaciona_x(double t) {
float y,z;
for(int i =0; i < 8 ;i++) {
y = P[i][1] * (float)Math.cos(t) –
P[i][2] * (float)Math.sin(t);
z = P[i][1] * (float)Math.sin(t) +
4
P[i][2] * (float)Math.cos(t);
P[i][1] = y;
P[i][2] = z;
}
}
public void rotaciona_y(double t) {
float x,z;
for(int i =0; i < 8 ;i++) {
x = P[i][0] * (float)Math.cos(t) –
P[i][2] * (float)Math.sin(t);
z = P[i][0] * (float)Math.sin(t) +
P[i][2] * (float)Math.cos(t);
P[i][0] = x;
P[i][2] = z;
}
}
public void rotaciona_z(double t) {
float x,y;
for(int i =0; i < 8 ;i++) {
x = P[i][0] * (float)Math.cos(t) –
P[i][1] * (float)Math.sin(t);
y = P[i][0] * (float)Math.sin(t) +
P[i][1] * (float)Math.cos(t);
P[i][0] = x;
P[i][1] = y;
}
}
public void render_cubo(GLDrawable drawable) {
GL gl = drawable.getGL();
unitario();
rotaciona_z(Math.PI / 4);
rotaciona_y(Math.PI / 4);
rotaciona_z(Math.PI / 6);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(P[0][0],P[0][1]);
gl.glVertex2f(P[1][0],P[1][1]);
gl.glVertex2f(P[2][0],P[2][1]);
gl.glVertex2f(P[3][0],P[3][1]);
gl.glEnd();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex2f(P[4][0],P[4][1]);
gl.glVertex2f(P[5][0],P[5][1]);
gl.glVertex2f(P[6][0],P[6][1]);
gl.glVertex2f(P[7][0],P[7][1]);
gl.glEnd();
}
gl.glBegin(GL.GL_LINES);
gl.glVertex2f(P[0][0],P[0][1]);
gl.glVertex2f(P[4][0],P[4][1]);
gl.glVertex2f(P[1][0],P[1][1]);
gl.glVertex2f(P[5][0],P[5][1]);
gl.glVertex2f(P[2][0],P[2][1]);
gl.glVertex2f(P[6][0],P[6][1]);
gl.glVertex2f(P[3][0],P[3][1]);
gl.glVertex2f(P[7][0],P[7][1]);
gl.glEnd();
5
}
1.2 – Transformações
As transformações necessárias para visualização 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 posição desejada (modeling transformation).
3. Escolhas a lente certa para a câmera e ajuste o zoom. (projection transformation).
4. Defina os limites da cena que estarão na foto final (viewport transformation).
De forma geral podemos dividir as operações necessárias em três grupos:
- Transformações (representadas por multiplicação de matrizes) incluindo operações de projeção,
visualização e modelagem. Estas operações incluem rotações, escalas, translações, reflexões, projeções
ortográficas e perspectivas.
- Operações de Clipping são responsáveis pela eliminação de objetos que estão fora da janela de
visualização.
- Transformações que estabeleçam a correspondência entre as coordenadas e a dimensão da tela (Viewport
transformation).
De forma esquemática podemos estabelecer:
Para especificar uma transformação o OpenGL constrói uma matriz 4x4 que representa a transformação
desejada. Esta matriz é então multiplicada pelas coordenadas de cada vértice na cena. As transformações de
Modelagem e Visualização são combinadas em uma única matriz denominada MODELVIEW matrix. A
transformação de projeção é armazenada na PROJECTION matrix.
1.3 - Comandos de Auxílio
Antes de iniciar a descrição do mecanismo das transformações acima, apresentaremos um conjunto de
comandos de caráter geral. Os comandos a seguir serão úteis durante todas as etapas do processo de
modelagem, visualização e Projeção.
glMatrixMode(Glenum tipo);
Este comando especifica a matriz a ser alterada. Existem três argumentos conforme o tipo da matriz:
1) GL_MODELVIEW
2) GL_PROJECTION
3) GL_TEXTURE
As transformações subsequentes afetam a matriz especificada. Observe que somente uma matriz pode ser
alterada por vez.
6
glLoadIdentity(void);
Este comando carrega a matriz identidade na matriz corrente especificada anteriormente pelo
glMatrixMode. O objetivo é limpar qualquer alteração 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 unitário
Antes de detalhar as transformações principais, vamos apresentar um programa exemplo que visualiza o
mesmo cubo do exemplo anterior, porem utilizando as transformações do OpenGL.
main.cpp
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static cubo Q;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Cubo");
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL gl = drawable.getGL();
7
Q = new cubo();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(-2.0,2.0,-2.0,2.0,-2.0,2.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glRotatef(30,0,0,1);
gl.glRotatef(45,0,1,0);
gl.glRotatef(45,0,0,1);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
Q.render_cubo(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y, int
width, int height) {
}
}
}
cubo.java
import net.java.games.jogl.*;
public class cubo {
float[][] P;
cubo() {
P = new float[8][3];
unitario();
}
public void
P[0][0] =
P[0][1] =
P[0][2] =
P[1][0] =
P[1][1] =
P[1][2] =
P[2][0] =
P[2][1] =
P[2][2] =
P[3][0] =
P[3][1] =
P[3][2] =
}
unitario() {
0;
P[4][0]
0;
P[4][1]
0;
P[4][2]
1;
P[5][0]
0;
P[5][1]
0;
P[5][2]
1;
P[6][0]
1;
P[6][1]
0;
P[6][2]
0;
P[7][0]
1;
P[7][1]
0;
P[7][2]
=
=
=
=
=
=
=
=
=
=
=
=
0;
0;
1;
1;
0;
1;
1;
1;
1;
0;
1;
1;
8
public void render_cubo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(P[0][0],P[0][1],P[0][2]);
gl.glVertex3f(P[1][0],P[1][1],P[1][2]);
gl.glVertex3f(P[2][0],P[2][1],P[2][2]);
gl.glVertex3f(P[3][0],P[3][1],P[3][2]);
gl.glEnd();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(P[4][0],P[4][1],P[4][2]);
gl.glVertex3f(P[5][0],P[5][1],P[4][2]);
gl.glVertex3f(P[6][0],P[6][1],P[4][2]);
gl.glVertex3f(P[7][0],P[7][1],P[4][2]);
gl.glEnd();
gl.glBegin(GL.GL_LINES);
gl.glVertex3f(P[0][0],P[0][1],P[0][2]);
gl.glVertex3f(P[4][0],P[4][1],P[4][2]);
gl.glVertex3f(P[1][0],P[1][1],P[1][2]);
gl.glVertex3f(P[5][0],P[5][1],P[5][2]);
gl.glVertex3f(P[2][0],P[2][1],P[2][2]);
gl.glVertex3f(P[6][0],P[6][1],P[6][2]);
gl.glVertex3f(P[3][0],P[3][1],P[3][2]);
gl.glVertex3f(P[7][0],P[7][1],P[7][2]);
gl.glEnd();
}
}
1.5 - Transformações de Modelagem e Visualização
Existem três tipos de comandos para transformações de modelagem: glTranslate(), glRotate() e
glScale(). Vamos descrever abaixo cada uma dessas funções.
1.5.1- Translação
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- Rotação
void glRotatef(float theta, float x, float y, float z);
Multiplica a matriz corrente por uma matriz que rotaciona o objeto no sentido anti-horário de theta graus,
na direção do eixo dado pelo vetor
.
1.5.3- Escala
9
void glScalef(float x, float y, float z);
Este comando realiza transformações de escala e reflexão. 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 três transformações citadas acima. Partindo de
um triângulo, desenhamos este triângulo quatro vezes sendo que:
- O triângulo vermelho é desenhado sem nenhuma transformação.
- O triângulo verde sofreu uma translação.
- O triângulo azul sofreu uma rotação.
- O triângulo amarelo sofreu uma transformação de escala.
triangulo.java
import net.java.games.jogl.*;
public class triangulo {
float[][] P;
triangulo() {
P = new float[3][3];
P[1][0] = 0.5f;
P[2][0] = 0.25f;
P[2][1] = 0.43f;
}
public void render_triangulo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glBegin(GL.GL_TRIANGLES);
gl.glVertex3f(P[0][0],P[0][1],P[0][2]);
gl.glVertex3f(P[1][0],P[1][1],P[1][2]);
gl.glVertex3f(P[2][0],P[2][1],P[2][2]);
gl.glEnd();
}
}
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static triangulo Q;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Cubo V02");
canvas.addGLEventListener( new JoglRender() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
10
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL gl = drawable.getGL();
GLU glu = drawable.getGLU();
Q = new triangulo();
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
Q.render_triangulo(drawable);
gl.glColor3f(0.0f,1.0f,0.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef( 0.5f, 0.5f,0.0f);
Q.render_triangulo(drawable);
gl.glLoadIdentity();
gl.glColor3f(0.0f,0.0f,1.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glRotatef(45,0.0f,0.0f,1.0f);
Q.render_triangulo(drawable);
gl.glLoadIdentity();
gl.glColor3f(1.0f,1.0f,0.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glScalef(0.5f, 0.5f,0.5f);
Q.render_triangulo(drawable);
gl.glLoadIdentity();
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y,
int width, int height) {
}
11
}
}
1.6- Projeção Ortográfica
Em uma projeção ortográfica, nós estabelecemos um volume de visualização (que corresponde a um
paralelepípedo retângulo). 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- Projeção Perspectiva
12
Em uma projeção perspectiva, nós estabelecemos um cone de visualização. O comando utilizado é:
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);
1.8- Ângulos de Euler
Um sistema de referência que irá nos auxiliar na montagem do ambiente 3D são ao ângulos de Euler. Os
Ângulos de Euler são definidos como três sucessivos ângulos de rotação através 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
posição horizontal, o eixo y na posição vertical e o eixo z está apontando para fora da tela do computador.
A seqüência inicia rotacionando o sistema de coordenadas xyz por um ângulo
torno do eixo z.
no sentido anti-horário em
Em seguida o sistema de coordenadas resultante é rotacionado em torno do eixo y de
graus.
13
Por fim o sistema de coordenadas sofre uma nova rotação de
em torno do eixo z.
Estes três ângulos definem os ângulos de Euler.
1.8 - Criando um Ambiente de Visualização 3D
Vamos montar um ambiente para visualização tri-dimensional, através do qual poderemos visualizar nossos
objetos 3D.
1.8.1- Módulo Básico de Visualização
Como primeiro passo vamos desenhar os três eixos de referencia, mantendo a seguinte escala de cores:
- Eixo x: vermelho
- Eixo y: verde
- Eixo z: azul
Uma posição inicial para a visualização pode ser obtida utilizando-se os ângulos theta = 135, phi = 45,
gamma=90.
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static dominio D = new dominio();
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Dominio 3D");
canvas.addGLEventListener( new JoglRender() );
14
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL
gl = drawable.getGL();
D.init(gl);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
D.plota_eixo(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable,
boolean modeChanged,
boolean deviceChanged) {
}
public void reshape(GLDrawable drawable,
int x, int y,
int width, int height) {
}
}
}
Dominio.java
import net.java.games.jogl.*;
public class dominio {
float xmin,xmax,ymin,ymax,zmin,zmax;
float gama,phi,theta;
dominio()
xmin =
xmax =
gama =
phi =
theta=
}
{
ymin = zmin = -1;
ymax = zmax = 1;
90;
45;
135;
15
dominio(float xm,float ym,float zm,float xM,float yM,float zM)
{
xmin = xm;
ymin = ym;
zmin = zm;
xmax = xM;
ymax = yM;
zmax = zM;
gama = 90;
phi = 45;
theta= 135;
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
}
gl.glColor3f (1.0f, 0.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (xmax,0,0);
gl.glVertex3f (0,0,0);
gl.glEnd();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,ymax,0);
gl.glEnd();
gl.glColor3f (0.0f, 0.0f, 1.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,0,zmax);
gl.glEnd();
public void init(GL gl) {
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(xmin,xmax,
ymin,ymax,
zmin,zmax);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glRotatef(gama ,0,0,1);
gl.glRotatef(phi ,0,1,0);
gl.glRotatef(theta,0,0,1);
}
public void set_angle(float g,float p,float t)
{
gama = g;
phi
= p;
theta = t;
}
}
1.8.2- Alterando os ângulos de Euler
Vamos agora acrescentar a possibilidade de alterar os ângulos com auxílio do mouse. Com o botão Esquerdo
do mouse pressionado, quando o mouse anda na direção horizontal, alteramos theta, quando o muse anda na
direção vertical alteramos phi.
16
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static dominio D = new dominio();
static int
xm,xb,ym,yb;
static float
gama,phi,theta;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Dominio 3D");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL
gl = drawable.getGL();
gama = 90; phi = 45; theta = 135;
D .init(gl);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
D.init(gl);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
D.plota_eixo(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable,
boolean modeChanged,
boolean deviceChanged) {
}
public void reshape(GLDrawable drawable,
int x, int y,
17
int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==1) {
System.out.println("Entra");
xb = e.getX();
yb = e.getY();
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==1) {
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
static class JoglMouseMotion implements
MouseMotionListener {
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) {
xm = e.getX();
ym = e.getY();
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
theta = theta - xm + xb;
phi
= phi
+ ym - yb;
canvas.display();
}
}
}
public void mouseMoved(MouseEvent e) {
}
}
18
1.9 – Visualização de gráfico de funções
A seguir apresentamos um programa exemplo para visualização de gráficos de funções
.
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static dominio D = new dominio();
static funcao f = new funcao();
static int
xm,xb,ym,yb;
static float
gama,phi,theta;
static float
scale;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new
LCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Funcao 3D");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addMouseWheelListener( new JoglMouseWheel() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL
gl = drawable.getGL();
gama = 90; phi = 45; theta = 135;
D .init(gl);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GLU glu = drawable.getGLU();
D.init(gl);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
19
gl.glColor3f(1.0f,0.0f,0.0f);
D.plota_eixo(drawable);
f.plota_funcao(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable,
boolean modeChanged,
boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y,
int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==1) {
System.out.println("Entra");
xb = e.getX();
yb = e.getY();
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==1) {
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
canvas.display();
}
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
static class JoglMouseMotion implements MouseMotionListener
{
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() &
20
InputEvent.BUTTON1_MASK) != 0) {
xm = e.getX();
ym = e.getY();
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
theta = theta - xm + xb;
phi
= phi
+ ym - yb;
canvas.display();
}
}
public void mouseMoved(MouseEvent e) {
}
}
static class JoglMouseWheel implements
MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
scale += e.getWheelRotation()/10.0;
D.set_scale(scale);
canvas.display();
}
}
}
funcao.java
import net.java.games.jogl.*;
public class funcao {
float xmin,xmax,ymin,ymax;
int
points;
funcao() {
xmin = ymin = -1;
xmax = ymax = 1;
points = 10;
}
public float f(float x,float y) {
return(x*x+y*y);
}
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
float x,y;
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
gl.glColor3f (1.0f, 1.0f, 1.0f);
x = xmin;
21
for(int i=0;i<points;i++) {
y = ymin;
for(int j=0;j<points;j++){
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(x
,y
,f(x
,y)
);
gl.glVertex3f(x+dx,y
,f(x+dx,y)
);
gl.glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
gl.glVertex3f(x
,y+dy,f(x
,y+dy));
gl.glEnd();
y += dy;
}
x += dx;
}
}
}
import net.java.games.jogl.*;
public class dominio {
float xmin,xmax,ymin,ymax,zmin,zmax;
float gama,phi,theta;
float scale;
dominio()
xmin =
xmax =
gama =
phi =
theta=
scale=
}
{
ymin = zmin = -2;
ymax = zmax = 2;
90;
45;
135;
1;
dominio(float xm,float ym,float zm,float xM,float yM,float zM)
{
xmin = xm;
ymin = ym;
zmin = zm;
xmax = xM;
ymax = yM;
zmax = zM;
gama = 90;
phi = 45;
theta= 135;
scale=
1;
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f (1.0f, 0.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (xmax,0,0);
gl.glVertex3f (0,0,0);
gl.glEnd();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
22
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,ymax,0);
gl.glEnd();
gl.glColor3f (0.0f, 0.0f, 1.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,0,zmax);
gl.glEnd();
}
public void init(GL gl) {
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(xmin,xmax,
ymin,ymax,
zmin,zmax);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glScalef(scale,scale,scale);
gl.glRotatef(gama ,0,0,1);
gl.glRotatef(phi ,0,1,0);
gl.glRotatef(theta,0,0,1);
}
public void set_angle(float g,float p,float t)
{
gama = g;
phi
= p;
theta = t;
}
public void set_scale(float s) {
scale = s;
}
}
23
2- ILUMINAÇÃO
Para definir o seu modelo de iluminação são necessárias três etapas básicas:
1) Definir as fontes de luz (posição, cor, direção, etc.);
2) Definir a iluminação.
3) Definir o tipo de material do objeto.
O modelo de iluminação do OPENGL considera que a iluminação pode ser dividida em três componentes
independentes: 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 direção não pode ser determinada.
- Luz Difusa: é uma luz proveniente de uma única direção que quando incide sobre o objeto não mantém
uma direção preferencial, e se divide em componentes em todas as direções.
- Luz Especular: é a luz proveniente de uma direção particular e tende a refletir em uma direção
preferencial.
A cor de uma fonte de luz é caracterizada pela intensidade de cada uma de suas componentes: vermelho,
verde e azul. O material da superfície é 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
características de uma fonte de luz, sendo necessário definir qual o seu comportamento relativo a luz
ambiente, difusa e especular.
Vamos iniciar com um simples exemplo, ilustrando as dificuldades de se estabelecer uma boa iluminação.
Nosso primeiro exemplo é um cubo, com uma face amarela e outra verde, onde se estabeleceu uma
iluminação básica, porém não satisfatória ainda. A classe Iluminacao contem alguns parâmetros básicos.
main.java
public class main {
static dominio D = new dominio();
static Iluminacao I = new Iluminacao();
static cubo
C = new cubo();
...
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
GL
gl = drawable.getGL();
gama = 90; phi = 45; theta = 135;
D.init(drawable);
I.light_on(drawable);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
D.init(drawable);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
D.plota_eixo(drawable);
I.render_light(drawable);
24
I.light_on(drawable);
C.render_cubo(drawable);
I.light_off(drawable);
gl.glFlush();
}
...
}
dominio.java
public class dominio {
...
public void init(GLDrawable drawable) {
...
gl.glRotatef(phi ,0,1,0);
gl.glRotatef(theta,0,0,1);
gl.glEnable(GL.GL_DEPTH_TEST);
}
cubo.java
public class cubo {
...
public void render_cubo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f(1,1,0);
gl.glBegin(GL.GL_QUADS);
gl.glNormal3f(0,0,1);
gl.glVertex3f(P[0][0],P[0][1],P[0][2]);
gl.glVertex3f(P[1][0],P[1][1],P[1][2]);
gl.glVertex3f(P[2][0],P[2][1],P[2][2]);
gl.glVertex3f(P[3][0],P[3][1],P[3][2]);
gl.glEnd();
gl.glColor3f(0,1,0);
gl.glBegin(GL.GL_QUADS);
gl.glNormal3f(0,0,1);
gl.glVertex3f(P[4][0],P[4][1],P[4][2]);
gl.glVertex3f(P[5][0],P[5][1],P[4][2]);
gl.glVertex3f(P[6][0],P[6][1],P[4][2]);
gl.glVertex3f(P[7][0],P[7][1],P[4][2]);
gl.glEnd();
gl.glColor3f(1,0,1);
gl.glBegin(GL.GL_LINES);
gl.glVertex3f(P[0][0],P[0][1],P[0][2]);
gl.glVertex3f(P[4][0],P[4][1],P[4][2]);
gl.glVertex3f(P[1][0],P[1][1],P[1][2]);
gl.glVertex3f(P[5][0],P[5][1],P[5][2]);
gl.glVertex3f(P[2][0],P[2][1],P[2][2]);
gl.glVertex3f(P[6][0],P[6][1],P[6][2]);
gl.glVertex3f(P[3][0],P[3][1],P[3][2]);
25
gl.glVertex3f(P[7][0],P[7][1],P[7][2]);
gl.glEnd();
}
...
}
Iluminacao.java
import net.java.games.jogl.*;
public class Iluminacao {
float[] mat_specular;
float[] mat_shininess;
float[] light_position;
Iluminacao() {
mat_specular = new float[4];
mat_specular[0] = 1.0f;
mat_specular[1] = 1.0f;
mat_specular[2] = 1.0f;
mat_specular[3] = 1.0f;
mat_shininess = new float[1];
mat_shininess[0] = 50.0f;
}
light_position = new float[4];
light_position[0] = 2.0f;
light_position[1] = 2.0f;
light_position[2] = 2.0f;
light_position[3] = 1.0f;
public void light_on(GLDrawable drawable) {
}
GL gl = drawable.getGL();
gl.glShadeModel (GL.GL_SMOOTH);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, light_position);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE);
gl.glEnable(GL.GL_NORMALIZE);
public void render_light(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f(1,0,0);
gl.glPointSize(8);
gl.glBegin(GL.GL_POINTS);
gl.glVertex3f(light_position[0],
light_position[1],
light_position[2]);
26
gl.glEnd();
}
public void light_off(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glDisable(GL.GL_LIGHTING);
gl.glDisable(GL.GL_LIGHT0);
gl.glDisable(GL.GL_DEPTH_TEST);
}
}
2.1– Criando Fontes de Luz
.
As fontes de luz têm certas propriedades que devem ser definidas (Cor, direção, posição, etc.). O comando
para especificar essas propriedades é:
void glLightfv(GLenum luz, GLenum iluminação, GLenum param);
O parâmetro luz indica apenas qual fonte de luz estamos trabalhando. Existem no máximo oito fontes que são:
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 parâmetros da iluminação são:
Parâmetro
Valor default
Significado
GL_AMBIENT
(0.0, 0.0, 0.0, 1.0)
GL_DIFFUSE
GL_SPECULAR
(1.0, 1.0, 1.0, 1.0)
(1.0, 1.0, 1.0, 1.0)
GL_POSITION
GL_SPOT_DIRECTION
GL_SPOT_EXPONENT
(0.0, 0.0, 1.0, 0.0)
(0.0, 0.0, -1.0)
0.0
GL_SPOT_CUTOFF
GL_CONSTANT_ATTENUATION
GL_LINEAR_ATTENUATION
GL_QUADRATIC_ATTENUATION
180.0
1.0
0.0
0.0
Intensidade
da
luz
ambiente
Intensidade da luz difusa
Intensidade
da
luz
especular
posição da luz
direção da luz
Parâmetro que controla a
distribuição da luz.
Ângulo de abertura da luz
2.1.1– Cor
A característica da luz é definida pelo parâmetro iluminação. O modelo de iluminação do OPENGL
considera que a iluminação 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 direção não pode ser determinada.
- Luz Difusa: é a luz proveniente de uma única direção que ao incidir sobre a superfície do material, se
reflete em todas as direções. Define a luz que naturalmente definiríamos como a cor da luz.
- Luz Especular: é a luz proveniente de uma direção particular e tende a refletir em uma direção
preferencial. Se você quer criar efeitos realísticos, mantenha a luz especular com os mesmos parâmetros
da luz difusa.
Por exemplo, para alterar a luz ambiente utiliza-se o seguinte código:
GLfloat luz_ambiente[4] = { 0.0, 0.0, 0.0, 1.0 };
27
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambiente);
2.1.2– Posição
A posição da luz pode ser de dois tipos básicos:
-
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
código:
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 localização é definida pelo vetor luz_posicao[4]={x , y, z, 1.0}.
2.2– Selecionando o Modelo de Iluminação
2.2.1- Luz Ambiente Global
Cada fonte de luz pode contribuir com uma parcela da luz ambiente. Além disso é possível adicionar uma
outra parcela de luz ambiente que não dependa das fontes de iluminação. 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á possível ver os
objetos na cena.
2.2.2 – Posição do observador local ou no infinito
A localização do observador pode ou não influenciar na iluminação. O default é o observador no infinito. Para
mudar a configuração, considerando-se a iluminação conforme o observador utilize:
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
2.2.3 – Iluminação nos dois lados das faces
O cálculo da iluminação é feito para todos os polígonos. É possível considerar diferentes iluminações nos dois
lados de um polígono. Para isso utilize:
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
2.2.4 – Habilitando a iluminação
No OpenGL você precisa explicitamente habilitar a iluminação. Para isso utilize o comando:
glEnable(GL_LIGHTING);
Para desabilitar basta utilizar o comando:
glDisable(GL_LIGHTING);
28
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 parâmetro face pode ser: GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK.
Os parâmetros da iluminação são:
Parâmetro
Valor default
Significado
GL_AMBIENT
(0.2, 0.2, 0.2, 1.0)
GL_DIFFUSE
(0.8, 0.8, 0.8, 1.0)
GL_SPECULAR
GL_SHININESS
GL_EMISSION
(0.0, 0.0, 0.0, 1.0)
0.0
(0.0, 0.0, 0.0, 1.0)
Cor da luz ambiente do
material
Cor da luz difusa do
material
Especular cor do material
Índice especular
Cor
de
emissão
do
material
2.4– Exemplo 1
Como exemplo, inserimos o modulo de iluminacao no programa funcao3D.
funcao.java
import net.java.games.jogl.*;
public class funcao {
float xmin,xmax,ymin,ymax;
int
points;
funcao() {
xmin = ymin = -2;
xmax = ymax = 2;
points = 40;
}
//
public float f(float x,float y) {
return(x*x-y*y);
return((float)Math.cos(Math.sqrt(x*x+y*y)));
}
public void plota_funcao(GLDrawable drawable) {
GL gl = drawable.getGL();
float x,y;
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
float[] v;
gl.glColor3f (1.0f, 1.0f, 1.0f);
29
x = xmin;
for(int i=0;i<points;i++) {
y = ymin;
for(int j=0;j<points;j++){
gl.glBegin(GL.GL_QUADS);
v = normal(x,y);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x
,y
,f(x
,y)
);
v = normal(x+dx,y);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x+dx,y
,f(x+dx,y)
);
v = normal(x+dx,y+dy);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
v = normal(x,y+dy);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x
,y+dy,f(x
,y+dy));
gl.glEnd();
y += dy;
}
x += dx;
}
}
public float dfx(float x,float y)
{
//
return(2*x);
return((float)(-Math.sin(Math.sqrt(x*x+y*y))*x/Math.sqrt(x*x+y*y)));
}
public float dfy(float x,float y)
{
// return(-2*y);
return((float)(-Math.sin(Math.sqrt(x*x+y*y))*y/Math.sqrt(x*x+y*y)) );
}
public float[] normal(float x,float y)
{
float[] v = new float[3];
v[0] = -dfx(x,y);
v[1] = -dfy(x,y);
v[2] = 1;
return(v);
}
}
main.java
import net.java.games.jogl.*;
public class main {
static
static
static
static
static
static
dominio D = new dominio();
funcao f = new funcao();
Iluminacao I = new Iluminacao();
int
xm,xb,ym,yb,mov=0;
float
gama,phi,theta;
float
scale;
30
static
GLCanvas
canvas
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
=
public static void main(String[] args) {
Frame frame
= new Frame("Funcao 3D");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addMouseWheelListener( new JoglMouseWheel() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
gama = 90; phi = 45; theta = 135;
D .init(drawable);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
D.init(drawable);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
gl.glColor3f(1.0f,0.0f,0.0f);
D.plota_eixo(drawable);
I.render_light(drawable);
I.light_on(drawable);
f.plota_funcao(drawable);
I.light_off(drawable);
gl.glFlush();
}
...
}
Iluminacao.java
import net.java.games.jogl.*;
public class Iluminacao {
float[]
float[]
float[]
float[]
mat_specular;
mat_shininess;
light_position;
light_diffuse;
Iluminacao() {
31
mat_specular = new float[4];
mat_specular[0] = 1.0f;
mat_specular[1] = 1.0f;
mat_specular[2] = 0.0f;
mat_specular[3] = 1.0f;
mat_shininess = new float[1];
mat_shininess[0] = 50.0f;
light_position = new float[4];
light_position[0] = 2.0f;
light_position[1] = 2.0f;
light_position[2] = 2.0f;
light_position[3] = 1.0f;
}
light_diffuse = new float[4];
light_diffuse[0] = 1.0f;
light_diffuse[1] = 0.0f;
light_diffuse[2] = 0.0f;
light_diffuse[3] = 1.0f;
public float[] get_light_position() {
return(light_position);
}
public void rotaciona_light() {
double x,y;
double t = 0.01;
Math.sin(t);
Math.cos(t);
x=
light_position[0]
*
Math.cos(t)
-
light_position[1]
*
y=
light_position[0]
*
Math.sin(t)
+
light_position[1]
*
light_position[0] = (float)x;
light_position[1] = (float)y;
}
public void light_on(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glShadeModel (GL.GL_SMOOTH);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat_specular);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SHININESS, mat_shininess);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, light_position);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE , light_diffuse);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_LIGHT0);
gl.glEnable(GL.GL_COLOR_MATERIAL);
gl.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE);
gl.glEnable(GL.GL_NORMALIZE);
}
public void render_light(GLDrawable drawable) {
GL gl = drawable.getGL();
32
gl.glColor3f(1,1,1);
gl.glPointSize(8);
gl.glBegin(GL.GL_POINTS);
);
gl.glVertex3f(light_position[0],light_position[1],light_position[2]
gl.glEnd();
}
public void light_off(GLDrawable drawable) {
GL gl = drawable.getGL();
//
}
}
gl.glDisable(GL.GL_LIGHTING);
gl.glDisable(GL.GL_LIGHT0);
gl.glDisable(GL.GL_DEPTH_TEST);
dominio.java
import net.java.games.jogl.*;
public class dominio {
float
float
float
float
xmin,xmax,ymin,ymax,zmin,zmax;
gama,phi,theta;
scale;
aa,bb;
dominio()
xmin =
xmax =
gama =
phi =
theta=
scale=
}
{
ymin = zmin = -5;
ymax = zmax = 5;
90;
45;
135;
1;
dominio(float xm,float ym,float zm,float xM,float yM,float zM)
{
xmin =
ymin =
zmin =
xmax =
ymax =
zmax =
gama =
phi =
theta=
xm;
ym;
zm;
xM;
yM;
zM;
90;
45;
135;
}
public void plota_eixo(GLDrawable drawable) {
GL gl = drawable.getGL();
gl.glColor3f (1.0f, 0.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (xmax,0,0);
gl.glVertex3f (0,0,0);
33
}
gl.glEnd();
gl.glColor3f (0.0f, 1.0f, 0.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,ymax,0);
gl.glEnd();
gl.glColor3f (0.0f, 0.0f, 1.0f);
gl.glBegin (GL.GL_LINES);
gl.glVertex3f (0,0,0);
gl.glVertex3f (0,0,zmax);
gl.glEnd();
public void init(GLDrawable drawable) {
GL gl = drawable.getGL();
GLU glu = drawable.getGLU();
//
//
//
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(xmin,xmax,
ymin,ymax,
zmin,zmax);
glu.gluPerspective(40.0,1.0,0.1,40);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0,0,-10);
gl.glScalef(scale,scale,scale);
gl.glRotatef(gama ,0,0,1);
gl.glRotatef(phi ,0,1,0);
gl.glRotatef(theta,0,0,1);
gl.glEnable(GL.GL_DEPTH_TEST);
}
public void set_angle(float g,float p,float t)
{
gama = g;
phi
= p;
theta = t;
}
public void set_scale(float s) {
scale = s;
}
}
2.5– Comando glLookAt
O comando glLookAt permite que você defina a visualização por três parâmetros:
1) A posição do observador (ox,oy,oz).
2) ,A direção em que o observador está olhando (dx,dy,dz).
3) A posição da camera (px,py,pz).
34
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 paramétrica, por exemplo, ou movimentando a fonte de
iluminação ao mesmo tempo, etc.
No exemplo abaixo, o observador se desloca sobre uma helice olhando sempre para a origem do sistema.
dominio.java
public void init(GLDrawable drawable) {
GL gl = drawable.getGL();
GLU glu = drawable.getGLU();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(40.0,1.0,0.1,40);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glScalef(scale,scale,scale);
glu.gluLookAt(2.1*Math.cos(t),
2.1*Math.sin(t),
t+0.01, 0,0,0 ,0,0,1);
t -= 0.01;
gl.glEnable(GL.GL_DEPTH_TEST);
}
curva.java
import net.java.games.jogl.*;
public class curva {
float tmin,tmax;
int
points;
curva() {
tmin = 0;
tmax = 10;
points = 80;
}
public float[] c(float t) {
float[] p = new float[3];
p[0] = 2*(float)Math.cos(t);
p[1] = 2*(float)Math.sin(t);
p[2] = (float)t;
return(p);
}
public void plota_curva(GLDrawable drawable) {
GL gl = drawable.getGL();
float t;
float dt = (tmax-tmin)/points;
float[] v;
gl.glColor3f (1.0f, 1.0f, 1.0f);
gl.glBegin(GL.GL_LINE_STRIP);
t = tmin;
for(int i=0;i<points;i++) {
35
v = c(t);
gl.glVertex3f(v[0],v[1],v[2]);
t += dt;
}
}
gl.glEnd();
}
2.6 – Visualizando as normais
Podemos acrescentar um novo metodo para visualizarmos as normais sobre a superfície.
public void plota_normal(GLDrawable drawable) {
GL gl = drawable.getGL();
float x,y;
float dx = (xmax-xmin)/points;
float dy = (ymax-ymin)/points;
float[] v;
float n = 10;
gl.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++){
gl.glBegin(GL.GL_LINES);
v = normal(x,y);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x
,y
,f(x
,y)
);
gl.glVertex3f(x+v[0]/n,y+v[1]/n,f(x ,y)+v[2]/n);
v = normal(x+dx,y);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x+dx,y
,f(x+dx,y)
);
gl.glVertex3f(x+dx+v[0]/n,y+v[1]/n,f(x+dx,y)+v[2]/n);
v = normal(x+dx,y+dy);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x+dx,y+dy,f(x+dx,y+dy));
gl.glVertex3f(x+dx+v[0]/n,y+dy+v[1]/n,f(x+dx,y+dy)+v[2]/n);
v = normal(x,y+dy);
gl.glNormal3f(v[0],v[1],v[2]);
gl.glVertex3f(x
,y+dy,f(x
,y+dy));
gl.glVertex3f(x+v[0]/n,y+dy+v[1]/n,f(x,y+dy)+v[2]/n);
gl.glEnd();
36
}
y += dy;
}
x += dx;
}
3- SUPERFÍCIES PARAMETRIZADAS
Para compreender a idéia de uma superfície parametrizada, considere D uma região do plano, cujas variáveis
são denotadas por
. A cada par
de D vamos associar um ponto
no espaço tridimensional, o qual pode ser escrito em termos de suas funções coordenadas por:
Uma superfície parametrizada é uma aplicação
superfície S correspondente a função
parâmetros (u, v).
é a imagem
onde D é algum domínio em
. A
. A superfície parametrizada depende de dois
3.1– Visualização de superfícies na forma paramétrica
.
Para visualizar superfícies dadas na forma paramétrica, utilizaremos o programa abaixo. O programa é
composto de dois módulos: sup_main.cpp e sup_param.cpp. O módulo sup_main.cpp é
responsável pelas tarefas de iluminação e definição do ambiente OpenGL. O segundo módulo
sup_param.cpp define a parametrização e através da função draw_superficie(), visualiza a superfície
desejada.
37
import net.java.games.jogl.*;
public class parametrico {
float vmin,vmax,umin,umax;
int
points;
parametrico() {
vmin = umin = 0;
vmax = (float)Math.PI;
umax = 2*(float)Math.PI;
points = 40;
}
public float[] superficie(float u,float v) {
float[] r = new float[3];
r[0] = (float)(Math.cos(u) * Math.sin(v));
r[1] = (float)(Math.sin(u) * Math.sin(v));
r[2] = (float)(Math.cos(v));
r[0] = (float)(-Math.sin(u)*(2+Math.cos(v)));
r[1] = (float)(Math.cos(u)*(2+Math.cos(v)));
r[2] = (float)(Math.sin(v));
}
return(r);
public void
GL gl
float
float
float
plota_superficie(GLDrawable drawable) {
= drawable.getGL();
u,v;
du = (umax-umin)/points;
dv = (vmax-vmin)/points;
float[] r,n;
gl.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++){
gl.glBegin(GL.GL_QUADS);
n = normal(u,v);
r = superficie(u,v);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u+du,v);
r = superficie(u+du,v);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u+du,v+dv);
r = superficie(u+du,v+dv);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u,v+dv);
r = superficie(u,v+dv);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(r[0],r[1],r[2]);
38
gl.glEnd();
v += dv;
}
}
}
u += du;
public float[] normal(float u,float v)
{
float[] v1 = new float[3];
float[] v2 = new float[3];
float[] n = new float[3];
float norma;
float[] p1 = new float[3];
float[] p2 = new float[3];
float[] p3 = new float[3];
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
p1 = superficie(u,v);
p2 = superficie(u,v+dv);
p3 = superficie(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 = (float)Math.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;
return(n);
}
}
3.2– Exercícios
1) Utilizando o programa anterior, visualize as seguintes superfícies e identifique-as:
a)
b)
c)
d)
39
e)
f)
g)
2) Visualize os vetores normais sobre a superfície. Observe o exemplo da letra f).
40
4- SUPERFÍCIES IMPLÍCITAS
main.java
import net.java.games.jogl.*;
public class main {
static dominio D = new dominio();
static superficie f = new superficie();
static Iluminacao I = new Iluminacao();
static int
xm,xb,ym,yb,mov=0;
static float
gama,phi,theta;
static float
scale;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Superficie Implicita");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addMouseWheelListener( new JoglMouseWheel() );
frame.add(canvas);
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
gama = 90; phi = 45; theta = 135;
D.init(drawable);
f.set_draw(drawable);
}
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
D.init(drawable);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
GL.GL_DEPTH_BUFFER_BIT);
D.plota_eixo(drawable);
I.render_light(drawable);
I.light_on(drawable);
f.plota_funcao();
I.light_off(drawable);
41
gl.glFlush();
}
public void displayChanged(GLDrawable drawable,
boolean modeChanged,
boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y,
int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
if (e.getButton()==1) {
xb = e.getX();
yb = e.getY();
}
if (e.getButton()==3) {
mov = (mov+1) % 2;
if (mov == 0)
System.out.println("Scala ");
else
System.out.println("Resolucao ");
}
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==1) {
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
canvas.display();
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
{
static class JoglMouseMotion implements
MouseMotionListener
42
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK)
!= 0) {
xm = e.getX();
ym = e.getY();
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
theta = theta - xm + xb;
phi
= phi
+ ym - yb;
canvas.display();
}
}
public void mouseMoved(MouseEvent e) {
}
}
static class JoglMouseWheel implements
MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
if (mov == 0){
scale += e.getWheelRotation()/10.0;
D.set_scale(scale);
canvas.display();
}
else {
int p = f.get_pontos();
p += e.getWheelRotation();
if (p <= 0)
p = 1;
f.set_pontos(p);
canvas.display();
}
}
}
}
superficie.java
import net.java.games.jogl.*;
public class superficie {
float xmin,xmax,ymin,ymax,zmin,zmax;
int
pontos;
GLDrawable drawable;
superficie() {
xmin = ymin
xmax = ymax
pontos = 5;
}
= zmin = -2;
= zmax = 2;
public int get_pontos() {
43
return pontos;
}
public void set_pontos(int p) {
pontos = p;
}
public void set_draw(GLDrawable draw) {
drawable = draw;
}
//
public float f(float x,float y,float z) {
return(x*x-y*y-z);
return(x*x+(float)Math.cos(x)*y*y-z*y-1);
}
//
//
//
public void normal(float[] v, float x,float y,float z) {
v[0] = 2*x-(float)Math.sin(x)*y*y;
v[1] = 2*y*(float)Math.cos(x)-z;
v[2] = -y;
v[0] = 2*x;
v[1] = -2*y;
v[2] = -1.0f;
}
void intersect(float[] v,float[] x,float[] y,float[] z,float[]
w,int i,int j)
{
float t;
t = w[i]/(w[i]-w[j]);
v[0] = x[i] + t * (x[j] - x[i]);
v[1] = y[i] + t * (y[j] - y[i]);
v[2] = z[i] + t * (z[j] - z[i]);
}
void tri(float[] x,float[] y,float[] z,float[] w,int i,int
j,int k,int l)
{
GL gl = drawable.getGL();
float[] v1 = new float[3];
float[] v2 = new float[3];
float[] v3 = new float[3];
float[] n = new float[3];
intersect(v1,x,y,z,w,i,j);
intersect(v2,x,y,z,w,i,k);
intersect(v3,x,y,z,w,i,l);
gl.glBegin(GL.GL_TRIANGLES);
normal(n,v1[0],v1[1],v1[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v1[0],v1[1],v1[2]);
normal(n,v2[0],v2[1],v2[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v2[0],v2[1],v2[2]);
normal(n,v3[0],v3[1],v3[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v3[0],v3[1],v3[2]);
gl.glEnd();
44
}
void quad(float[] x,float[] y,float[] z,float[] w,int i,int
j,int k,int l)
{
GL gl = drawable.getGL();
float[] v1 = new float[3];
float[] v2 = new float[3];
float[] v3 = new float[3];
float[] v4 = new float[3];
float[] n = new float[3];
}
intersect(v1,x,y,z,w,i,k);
intersect(v2,x,y,z,w,i,l);
intersect(v3,x,y,z,w,j,l);
intersect(v4,x,y,z,w,j,k);
gl.glBegin(GL.GL_TRIANGLES);
normal(n,v1[0],v1[1],v1[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v1[0],v1[1],v1[2]);
normal(n,v2[0],v2[1],v2[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v2[0],v2[1],v2[2]);
normal(n,v3[0],v3[1],v3[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v3[0],v3[1],v3[2]);
gl.glEnd();
gl.glBegin(GL.GL_TRIANGLES);
normal(n,v1[0],v1[1],v1[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v1[0],v1[1],v1[2]);
normal(n,v3[0],v3[1],v3[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v3[0],v3[1],v3[2]);
normal(n,v4[0],v4[1],v4[2]);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glVertex3f(v4[0],v4[1],v4[2]);
gl.glEnd();
void tetraedro(float[] x,float[] y,float[] z,float[] w,int
i,int j,int k,int l)
{
GL gl = drawable.getGL();
//
light_on(drawable);
gl.glColorMaterial(GL.GL_FRONT, GL.GL_DIFFUSE);
gl.glColor3f(1,1,0);
gl.glColorMaterial(GL.GL_BACK , GL.GL_DIFFUSE);
gl.glColor3f(1,0,0.2f);
if (w[i] < 0) {
if (w[j] < 0) {
if (w[k] < 0) {
if (w[l] >= 0)
tri(x,y,z,w,l,k,j,i);
}
else {
if (w[l] < 0)
tri(x,y,z,w,k,i,j,l);
else
45
quad(x,y,z,w,k,l,i,j);
}
}
else {
if (w[k] < 0) {
if (w[l] < 0)
tri(x,y,z,w,j,l,k,i);
else
quad(x,y,z,w,j,l,k,i);
}
else {
if
}
}
(w[l] < 0)
quad(x,y,z,w,j,k,i,l);
else
tri(x,y,z,w,i,l,k,j);
}
else {
if
(w[j] < 0) {
if (w[k] < 0) {
if (w[l] < 0)
tri(x,y,z,w,i,j,k,l);
else
quad(x,y,z,w,i,l,j,k);
}
else {
if
}
(w[l] < 0)
quad(x,y,z,w,i,k,l,j);
else
tri(x,y,z,w,j,l,i,k);
}
else {
if (w[k] < 0) {
if (w[l] < 0)
quad(x,y,z,w,i,j,k,l);
else
tri(x,y,z,w,k,l,j,i);
}
else {
}
if
(w[l] < 0)
tri(x,y,z,w,l,i,j,k);
}
//
}
desabilita_lighting();
gl.glColorMaterial(GL.GL_FRONT, GL.GL_DIFFUSE);
gl.glColor3f(0.0f,0.0f,1.0f);
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(x[i],y[i],z[i]);
gl.glVertex3f(x[j],y[j],z[j]);
gl.glVertex3f(x[k],y[k],z[k]);
gl.glEnd();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(x[i],y[i],z[i]);
gl.glVertex3f(x[j],y[j],z[j]);
gl.glVertex3f(x[l],y[l],z[l]);
gl.glEnd();
46
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(x[i],y[i],z[i]);
gl.glVertex3f(x[k],y[k],z[k]);
gl.glVertex3f(x[l],y[l],z[l]);
gl.glEnd();
gl.glBegin(GL.GL_LINE_LOOP);
gl.glVertex3f(x[j],y[j],z[j]);
gl.glVertex3f(x[k],y[k],z[k]);
gl.glVertex3f(x[l],y[l],z[l]);
gl.glEnd();
}
public void plota_funcao()
{
GL gl = drawable.getGL();
int
i,j,k,l;
float x,y,z;
float dx,dy,dz;
float[] xv,yv,zv,wv;
xv = new float[8];
yv = new float[8];
zv = new float[8];
wv = new float[8];
gl.glColor3f(1.0f,1.0f,0.0f);
dx = (xmax - xmin)/pontos;
dy = (ymax - ymin)/pontos;
dz = (zmax - zmin)/pontos;
for(i=0;i<pontos;i++) {
x = xmin + i * dx;
for (l = 0;l < 8;l++)
xv[l] = ((l % 2) == 0) ? x : x+dx;
for(j=0;j<pontos;j++) {
y = ymin + j * dy;
for (l = 0;l < 8;l++)
yv[l] = ((l % 4) < 2) ? y : y+dy;
for(k=0;k<pontos;k++) {
z = zmin + k * dz;
for (l = 0;l < 8;l++) {
zv[l] = (l < 4) ? z : z+dz;
wv[l] = f(xv[l],yv[l],zv[l]);
}
tetraedro(xv,yv,zv,wv,0,1,3,7);
tetraedro(xv,yv,zv,wv,0,5,1,7);
tetraedro(xv,yv,zv,wv,0,3,2,7);
tetraedro(xv,yv,zv,wv,0,2,6,7);
tetraedro(xv,yv,zv,wv,0,4,5,7);
tetraedro(xv,yv,zv,wv,0,6,4,7);
}
}
}
}
}
47
5- TEXTURA
Parametrico.java
import net.java.games.jogl.*;
public class parametrico {
float vmin,vmax,umin,umax;
int
points;
parametrico() {
vmin = umin = 0;
vmax = (float)Math.PI;
umax = 2*(float)Math.PI;
vmin = umin = -5;
umax = vmax = 5;
points = 20;
}
public float[] superficie(float u,float v) {
float[] r = new float[3];
r[0] = (float)(Math.cos(u) * Math.sin(v));
r[1] = (float)(Math.sin(u) * Math.sin(v));
r[2] = (float)(Math.cos(v));
r[0] = (float)(-Math.sin(u)*(2+Math.cos(v)));
r[1] = (float)(Math.cos(u)*(2+Math.cos(v)));
r[2] = (float)(Math.sin(v));
r[0] = u;
r[1] = v;
r[2] = (float)(Math.cos(Math.sqrt(u*u+v*v)));
r[2] = (float)(Math.cos(u)*v);
r[2] = (float)((Math.sqrt(u*u+v*v)));
r[0] = u*(float)Math.cos(v);
r[1] = u*(float)Math.sin(v);
r[2] = u;
//
//
//
//
//
//
//
//
}
return(r);
public void plota_superficie(GLDrawable drawable) {
GL gl = drawable.getGL();
float u,v;
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
float[] r,n;
gl.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++){
gl.glBegin(GL.GL_QUADS);
n = normal(u,v);
r = superficie(u,v);
gl.glNormal3f(n[0],n[1],n[2]);
48
gl.glTexCoord2f(u/10.0f+0.5f,
v/10.0f+0.5f);
gl.glTexCoord2f(0,0);
gl.glTexCoord2f(u/umax,
v/vmax);
gl.glTexCoord2f(u, v);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u+du,v);
r = superficie(u+du,v);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glTexCoord2f((u+du)/10.0f+0.5f, v/10.0f+0.5f);
gl.glTexCoord2f(0, 1);
gl.glTexCoord2f((u+du)/umax,
v/vmax);
gl.glTexCoord2f(u+du, v);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u+du,v+dv);
r = superficie(u+du,v+dv);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glTexCoord2f((u+du)/10.0f+0.5f, (v+dv)/10.0f+0.5f);
gl.glTexCoord2f(1, 1);
gl.glTexCoord2f((u+du)/umax,
(v+dv)/vmax);
gl.glTexCoord2f(u+du, v+dv);
gl.glVertex3f(r[0],r[1],r[2]);
n = normal(u,v+dv);
r = superficie(u,v+dv);
gl.glNormal3f(n[0],n[1],n[2]);
gl.glTexCoord2f(u/10.0f+0.5f,
(v+dv)/10.0f+0.5f);
gl.glTexCoord2f(1, 0);
gl.glTexCoord2f(u/umax,
(v+dv)/vmax);
gl.glTexCoord2f(u, v+dv);
gl.glVertex3f(r[0],r[1],r[2]);
gl.glEnd();
v += dv;
}
u += du;
}
}
public float[] normal(float u,float v)
{
float[] v1 = new float[3];
float[] v2 = new float[3];
float[] n = new float[3];
float norma;
float[] p1 = new float[3];
float[] p2 = new float[3];
float[] p3 = new float[3];
float du = (umax-umin)/points;
float dv = (vmax-vmin)/points;
49
p1 = superficie(u,v);
p2 = superficie(u,v+dv);
p3 = superficie(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 = (float)Math.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;
return(n);
}
}
Imagemrgb.java
import net.java.games.jogl.*;
import java.io.*;
public class Imagemrgb {
int
int
byte[][][]
String
dimx,dimy,range;
rx,ry;
imagergb;
file;
Imagemrgb(String s) {
file = s;
try {
Reader q = new FileReader(s);
int ch;
String p;
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch )) {
ch = q.read();
if (Character.isWhitespace((char) ch))
break;
p += String.valueOf((char)ch);
}
dimx = Integer.parseInt(p);
50
}
while(Character.isWhitespace((char) ch))
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch)) {
ch = q.read();
if (Character.isWhitespace((char) ch))
break;
p += String.valueOf((char)ch);
dimy = Integer.parseInt(p);
while(Character.isWhitespace((char) ch))
ch = q.read();
p = String.valueOf((char)ch);
while(!Character.isWhitespace((char) ch)) {
ch = q.read();
if (Character.isWhitespace((char) ch))
break;
p += String.valueOf((char)ch);
}
range = Integer.parseInt(p);
imagergb = new byte[dimx][dimy][3];
System.out.println(" " + dimx + " " + dimy + " " +
range);
for (int i = 0; i<dimx; i++) {
for(int j = 0; j<dimy; j++) {
for(int k = 0; k < 3; k++) {
while(Character.isWhitespace((char)
ch))
ch = q.read();
p = String.valueOf((char)ch);
while (!Character.isWhitespace((char)
ch)) {
ch = q.read();
if
(Character.isWhitespace((char) ch))
break;
p += String.valueOf((char)ch);
}
imagergb[i][j][k] =
(byte)Integer.parseInt(p);
//
//
//
+ p );
}
if (imagergb[i][j][k] < 0)
imagergb[i][j][k] += 256;
System.out.println(imagergb[i][j][k] + " "
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public byte get_image(int i,int j,int k) {
if ((i < dimx) && (j < dimy)) {
return(imagergb[i][j][k]);
51
}
else {
System.out.println(i+ " " + j + " " + dimx + " " +
dimy + " " + imagergb[i][j][k]);
return(0);
}
}
public int get_dimx() {
return dimx;
}
public int get_dimy() {
return dimy;
}
public void draw_image(GLDrawable draw) {
GL gl = draw.getGL();
for (int i=0;i<dimx;i++)
for (int j=0;j<dimy;j++) {
gl.glColor3f(imagergb[i][j][0]/(float)range,imagergb[i][j][1]/(floa
t)range,imagergb[i][j][2]/(float)range);
gl.glBegin(GL.GL_POINTS);
gl.glVertex2d(j,i);
gl.glEnd();
}
}
}
main.java
import java.awt.*;
import java.awt.event.*;
import net.java.games.jogl.*;
public class main {
static dominio D = new dominio();
static parametrico f = new parametrico();
static Iluminacao I = new Iluminacao();
static Textura T = new Textura("bricks2.pgm",1);
//
static Textura T = new Textura("sea.pgm");
static int
xm,xb,ym,yb,mov=0;
static float
gama,phi,theta;
static float
scale;
static GLCanvas canvas =
GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());
public static void main(String[] args) {
Frame frame
= new Frame("Textura");
canvas.addGLEventListener( new JoglRender() );
canvas.addMouseListener( new JoglMouse() );
canvas.addMouseMotionListener( new JoglMouseMotion() );
canvas.addMouseWheelListener( new JoglMouseWheel() );
frame.add(canvas);
52
}
frame.setSize(600, 600);
frame.setLocation(50,50);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
static class JoglRender implements GLEventListener {
public void init(GLDrawable drawable) {
}
gama = 90; phi = 45; theta = 135;
D.init(drawable);
T.set_Drawable(drawable);
T.init();
public void display(GLDrawable drawable) {
GL
gl = drawable.getGL();
GL.GL_DEPTH_BUFFER_BIT);
D.init(drawable);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT |
I.rotaciona_light();
D.plota_eixo(drawable);
I.render_light(drawable);
I.light_on(drawable);
T.texture_on();
f.plota_superficie(drawable);
T.texture_off();
I.light_off(drawable);
gl.glFlush();
}
public void displayChanged(GLDrawable drawable, boolean
modeChanged, boolean deviceChanged) {
}
public void reshape(GLDrawable drawable, int x, int y,
int width, int height) {
}
}
static class JoglMouse implements MouseListener {
public void mouseEntered(MouseEvent e) {
//
System.out.println("Mouse Entra");
}
public void mouseExited (MouseEvent e) {
//
System.out.println("Mouse Sai");
}
public void mousePressed(MouseEvent e) {
53
if (e.getButton()==1) {
System.out.println("Entra");
xb = e.getX();
yb = e.getY();
}
if (e.getButton()==2) {
System.out.println("troca");
mov = (mov+1) %3;
System.out.println("Persp = " + mov);
}
}
}
public void mouseReleased(MouseEvent e) {
if (e.getButton()==1) {
theta = theta + xm - xb;
phi
= phi
- ym + yb ;
D.set_angle(gama,phi,theta);
canvas.display();
}
public void mouseClicked(MouseEvent e) {
System.out.println("Mouse botao");
}
}
{
static class JoglMouseMotion implements
MouseMotionListener
public void mouseDragged(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_MASK)
!= 0) {
xm = e.getX();
ym = e.getY();
theta = theta + xm phi
= phi
- ym +
D.set_angle(gama,phi,theta);
theta = theta - xm
phi
= phi
+ ym
canvas.display();
}
xb;
yb ;
+ xb;
- yb;
}
}
public void mouseMoved(MouseEvent e) {
}
static class JoglMouseWheel implements
MouseWheelListener {
public void mouseWheelMoved(MouseWheelEvent e) {
scale = D.get_scale();
scale += e.getWheelRotation()/10.0;
D.set_scale(scale);
54
canvas.display();
}
}
}
Textura.java
import net.java.games.jogl.*;
public class Textura {
byte[] Image;
int dimx,dimy,depth;
int[] texName = new int[1];
int rx,ry;
GLDrawable draw;
Imagem I;
Imagemrgb R;
Textura(String s) {
int ind;
I = new Imagem(s);
dimx = I.get_dimx();
dimy = I.get_dimy();
depth = 3;
Image = new byte[dimx*dimy*3];
ind = 0;
System.out.println("W/B");
for(int i=0;i<dimx;i++) {
for(int j=0;j<dimy;j++) {
Image[ind] = I.get_image(i,j);
Image[ind+1] = Image[ind+2] = Image[ind];
ind = ind + 3;
}
}
}
Textura(String s,int type) {
int ind;
R = new Imagemrgb(s);
dimx = 512;
dimy = 512;
depth = 3;
rx = R.get_dimx();
ry = R.get_dimx();
Image = new byte[dimx*dimy*3];
ind = 0;
System.out.println("Color");
for(int i=0;i<dimx;i++) {
for(int j=0;j<dimy;j++) {
for(int k=0;k<3;k++) {
Image[ind] = R.get_image(i,j,k);
ind = ind + 1;
}
}
}
}
public void set_Drawable(GLDrawable drawable) {
draw = drawable;
55
}
public void texture_on()
{
GL gl = draw.getGL();
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE,
GL.GL_DECAL); // GL_GL_BLEND , GL_REPLACE, GL_MODULATE
gl.glBindTexture(GL.GL_TEXTURE_2D, texName[0]);
}
public void texture_off()
{
GL gl = draw.getGL();
gl.glDisable(GL.GL_TEXTURE_2D);
}
public void init()
{
GL gl = draw.getGL();
gl.glClearColor (0, 0, 0, 0);
gl.glShadeModel(GL.GL_SMOOTH);
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
gl.glGenTextures(1, texName);
gl.glBindTexture(GL.GL_TEXTURE_2D, texName[0]);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S,
GL.GL_REPEAT); //GL_CLAMP
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T,
GL.GL_REPEAT);
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); //GL.GL_NEAREST
gl.glTexParameteri(GL.GL_TEXTURE_2D,
GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, dimx,dimy, 0,
GL.GL_RGB, GL.GL_UNSIGNED_BYTE,Image);
}
}
56
Download