• Olá Visitante, se gosta do forum e pretende contribuir com um donativo para auxiliar nos encargos financeiros inerentes ao alojamento desta plataforma, pode encontrar mais informações sobre os várias formas disponíveis para o fazer no seguinte tópico: leia mais... O seu contributo é importante! Obrigado.

Biblioteca Gráfica OpenGl

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Texture1.jpg




Mapeamento de Texturas


No contexto de Computação Gráfica, o mapeamento de texturas consiste na "aplicação de uma imagem sobre as faces de um objeto 3D.

O uso de texturas requer a execução de dois passos distintos: a CARGA e a APLICAÇÃO da textura.

Em OpenGL cada textura recebe um número de identificação através da função glGenTextures. Por exemplo:

Sempre que for necessário trabalhar com um textura (para carga ou aplicação) deve-se chamar a função glBindTexture que permite definir a textura corrente. Esta definição é feita atavés do número de identificaçõa da textura.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Carga de uma textura
Para realizar a tarefa de CARGA de uma textura é necessário seguir os seguintes passos:
// Habilitar o uso de texturas
glEnable ( GL_TEXTURE_2D );

// Definir a forma de armazenamento dos pixels na textura (1= alinhamento por byte)
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );

// Definir quantas texturas serão usadas no programa
GLuint texture_id[MAX_NO_TEXTURES]; // vetor com os números das texturas
glGenTextures (1, texture_id); // 1 = uma textura;
// texture_id = vetor que guarda os números das texturas

// Definr o número da textura do cubo.
texture_id[0] = 1001;

// Define a textura corrente
glBindTexture ( GL_TEXTURE_2D, texture_id[0] );
// GL_TEXTURE_2D ==> define que será usada uma textura 2D (bitmaps)
// texture_id[CUBE_TEXTURE] ==> define o número da textura

// carrega a uma imagem TGA
image_t temp_image;
tgaLoad ( "TCG1.tga", &temp_image, TGA_FREE | TGA_LOW_QUALITY );
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Aplicação de uma Textura
Para a aplicação da textura é preciso criar uma relação entre os vértives da textura e os vértices dos polígonos sobre os quais se desenha mapear a textura escolhida.
Na figura a seguir as letras A, B, C e D definem os vértices da textura e os vértices A1, B1, C1 e D1 os vértices de polígono 3D onde deve ser mapeada esta textura.
O processo de mapeamento de texturas em OpenGL consiste em "aplicar" a imagem 2D sobre o polígono 3D de forma que os pontos A, B, C e D sejam encaixados sobre os pontos A1, B1, C1 e D1.

Mapa1a.jpg



Texture1a.jpg



Para permitir a construção desta correspondência entre a imagem 2D e o polígono 3D usa-se a função glTexCoord2f antes da definição do ponto 3D.
Por exemplo,

glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);


define que o ponto (0.0, 0.0) da textura 2D corresponde ao ponto (1.0, -1.0, 1.0) do polígono 3D.

O sistema de coordenadas da textura tem como (0,0) o ponto inferior esquerdo da imagem e como (1,1) o ponto superior direito. Ou seja, na imagem acima temos as seguintes coordenadas para os pontos A, B, C e D.

Vértice da
Textura Coordenada
A (0,1)
B (1,1)
C (1,0)
D (0,0)


Supondo que o polígono 3D é a face lateral direita de um cubo de aresta 2 com o centro no ponto (0,0,0) teremos as seguintes coordenadas:

Vértice do
Polígono 3D Coordenada
A1 1.0, 1.0, 1.0
B1 1.0, 1.0, -1.0
C1 1.0, -1.0, -1.0
D1 1.0, -1.0, 1.0


O mapeamento da textura sobre o polígono se dá através do seguinte trecho de código:


// Define a textura corrente
glBindTexture ( GL_TEXTURE_2D, texture_id[0] );
// GL_TEXTURE_2D ==> define que será usada uma textura 2D (bitmaps)
// texture_id[CUBE_TEXTURE] ==> define o número da textura

// associa cada vértice do polígono a um ponto da textura
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
É importante lembrar ainda que para definir qual a textura a ser usada em um certo polígono é preciso defini-la antes como a textura corrente através da função glBindTexture.















 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Manipulação de imagens em OpenGL

O objetivo desta aula é exibir e manipular imagens em OpenGL.
Instalação

Copie o arquivo com exemplos e descompacte em um diretório.


Se você estiver usando a versão do DEVCPP que está instalada na sala 122, do LAPRO, abra o projeto Imagens-Lapro122.dev. Isto deve permitir a compilação correta do projeto. Se tiver dúvidas de como criar um projeto no DEVCPP, consulte o material da primeira aula de OpenGL.

Caso você esteja usando uma outra versão do DEVCPP, crie um novo projeto como uma aplicação do tipo Console, em C++ e inclua as diretivas de OpenGL ( -lopengl32 -lglut32 -lglu32 -lglaux ). Note que estas diretivas não são exatamente as mesmas daquelas usadas em outras aulas. Neste caso, foi adicionada a biblioteca glaux que permite carregar iamgens BMP.

Antes de executar o programa, é necessário definir onde está a imagem a ser carregada pelo mesmo. para tanto, abra o fonte ImageTest2.cpp e procure a função void init(void). Dentro desta função há uma linha onde um método Load é chamado:

r = Image->Load("C:\\My Documents\\Doc\\Cg\\Pagina\\Aulas\\OpenGL\\Imagens\\ExemploComImagens\\EAGLE.BMP");

Altere esta linha de forma a definir o local onde você colocou sue projeto ao descompactá-lo.

Após a execução do programa, o resultado deve ser semelhante a este apresentado na figura abaixo.


Tela1.png



 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
A Classe ImageClass

Para realizar a carga de uma imagem, o programa acima usar a classe ImageClass que encapsula as funções de OpenGL para acesso a imagens, para usar esta classe você deve criar uma instâcia da classe e carregar uma imagem da seguinte forma:
// Cria um objeto imagem
Image = new ImageClass();

r = Image->Load("C:\\My Documents\\Doc\\Cg\\Pagina\\Aulas\\OpenGL\\Imagens\\ExemploComImagens\\EAGLE.BMP");
if (!r)
{
printf("Imagem não encontrada. Verifique o nome do Arquivo.\n");
printf("Pressione ENTRE para encerrar.");
getchar();
exit(1);
}
else printf ("Imagem carregada!\n");

Você pode ainda, criar uma imagem vazia da seguinte forma:

// Instacia o objeto que irá exibir uma nova imagem
// Caso precise alterar o tamanho da nova imagem, mude os parâmetros
// da construtura, na chamada abaixo. No exemplo a nova imagem é criada
// usando o tamanho da imagem recém carregada de disco
NovaImagem = new ImageClass(Image->SizeX(), Image->SizeY());

// Posiciona a imagem nova ao lado da antiga
NovaImagem->SetPos(Image->SizeX()+10, 0);

Para acessar os pontos da imagem você pode usar os métodos ReadPixel e DrawPixel.

Para obter a cor RGB de um pixel x,y na imagem use :
Image->ReadPixel(GLint x, GLint y, unsigned char &r, unsigned char &g, unsigned char &b)

Para alterar a cor RGB de um pixel x,y na imagem use :
Image->DrawPixel(GLint x, GLint y, unsigned char r, unsigned char g, unsigned char b)

Para obter o a Internsidade(Luminosidade) de um ponto use:
i = Image->GetPointIntensity(x,y);
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Exercícios

Abra o programa-fonte ImageTeste2.cpp e procure entender como funcionam as rotinas init e ConvertBlackAndWhite.

Pressionando a tecla 2 na execução do programa você consegue observar o resultado da aplicação da rotina ConvertBlackAndWhite.


1 . Crie uma rotina capaz de exibir a image de entrada em tons de cinza, conforme a imagem abaixo

cinza.jpg



2. Complete a rotina void DetectImageBorders() a fim de detectar as bordas de uma imagem, como na figura abaixo.


Bordas.gif


 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Navegação em Ambientes Virtuais
A navegação em OpenGL ou, em outras palavras, o posicionamento do observador é feito normalmente com a função gluLookAt. Nesta função define-se a posição do observador e o seu ponto de interesse, além do vetor que aponta para o "lado de cima" do cenário 3D.

Andando "para frente" com a glLookAt
Para permitir que um observador ande na direção em que ele está olhando é necessário somar à posiçõa atual do observador um vetor que tenha a mesma direção que vetor que vai do observador até o alvo. A mesma soma deve ser fetia ao ponto alvo.

É interessante que este vetor seja unitário pois assim se pode controlar a velocidade do deslocamento.
A fórmula a seguir demonstra como pode ser feito o deslocamento descrito acima.
PosicaoNova = PosicaoAtual + VetorAlvoUnitario * TamanhoDoPasso
AlvoNovo = AlvoAtual + + VetorAlvoUnitario * TamanhoDoPasso
Olhando "para os lados" com a glLookAt
Para permitir que um observador "olhe para os lados" é preciso recalcular o ponto Alvo, aplicando sobre ele uma rotação ao redor do eixo Y.

Para rotacionar um ponto ao redor deste eixo usa-se a seguinte fórmula:
AlvoNovo.X = AlvoAtual.X*cos(alfa) + AlvoAtual.Z*sen(alfa)
AlvoNovo.Y = AlvoAtual.Y
AlvoNovo.Z = -AlvoAtual.X*sen(alfa) + AlvoAtual.Z*cos(alfa)
Note, entretanto que esta fórmula rotaciona o ponto ao redor do ponto (0,0,0).

Como fazer para rotacioná-lo corretamente ?
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Instalação da Biblioteca
Para instalar OpenGL você precisa obter as bibliotecas que contém o código OpenGL assim como os aquivos de cabeçalho (.H)

Clique aqui para obter um exemplo com estes arquivos.

Descompacte o arquivo obtido e abra o arquivo BasicoDEVCPP.dev. Isto deve carregar o DevC++.
No projeto do DevC++ verifique se estão incluídas as biblitoecas necessárias, quais sejam.
libglaux.a
libglu32.a
libglut32.a
libglut.a
libopengl32.a

Para verificar isto, tecle ALT-P e clique na pasta "parâmetros".

Dependendo da versão do DEVC++, não haverá a pasta citada acima. Neste caso, a inclusão das bibliotecas deverá ser feita através da seguinte linha de configuração, também na janela de opções de projeto.

-lopengl32 -lglut32 -lglu32 -lglaux

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Utilização da Biblioteca

Para usar OpenGL em 3D são necessárias as seguintes providências.

1 .Definir a posição do observador na cena tridimensional. Isto é feito através do comandos apresentados a seguir, que devem ser colocados no início da rotina de redesenho da janela OpenGL:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// define projeção perspectiva. Deve ser colocado ANTES do gluLookAt
gluPerspective(AngVisao,1,1,1000);
// Define a posição do observador no cenário 3D
gluLookAt(ObsX,ObsY,ObsZ, 0,0,29, 0,1,0);
glMatrixMode(GL_MODELVIEW);
2. Exibir os objetos em 3D.
glBegin(GL_POLYGON); // desenha um polígono
glNormal3f(0,-1,0); // define a normal da face (essencial para usar luzes)
glVertex3f(-10.0, -10.0, -10.0); // define os vértices da face
glVertex3f(10.0, -10.0, -10.0);
glVertex3f(10.0, -10.0, 10.0);
glVertex3f(-10.0, -10.0, 10.0);
glEnd; // fim do desenho
A seguir algumas destas funções são explicadas.
Função glMatrixMode (GL_PROJECTION)
Define que as funções usadas a após a chamada desta rotina irão referir-se ao observador e não aos objetos do cenário 3D.
Função glMatrixMode (GL_MODELVIEW)
Define que as funções usadas a após a chamada desta rotina irão referir-se ao aos objetos do cenário 3D e não ao observador.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Função gluPerspective
O cabeçalho desta função é o seguinte:
gluPerperspective(AnguloDeVisao, RazaoDaJanela, LimitePerto, LimiteLonge).
Onde,
AnguloDeVisao: ângulo de visão do observador, especificado em graus;
RazaoDaJanela: relação (divisão) entre a largura e a altura da janela OpenGL;

LimitePerto: menor distância desejada para um objeto visível. Se a distância entre um objeto e o observador for menor do que este número, este objeto não será visível;

LimiteLonge: maior distância desejada para um objeto visível. Se a distância entre um objeto e o observador for maior do que este número, este objeto não será visível;
Função gluLooAt
O cabeçalho desta função é o seguinte:
void gluLookAt ( ObsX, ObsY, ObsZ
AlvoX, AlvoY, AlvoZ,
0,1,0 );
Onde,
ObsX, ObsY, ObsZ: posição do observador;
AlvoX, AlvoY, AlvoZ: posição do ponto para onde o observador está olhando;
0,1,0: Define o lado de cima do cenário 3D.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Utilização de Luzes em OpenGL


A biblioteca gráfica OpenGL é capaz de trabalhar com 3 tipos de LUZ: Ambiente, Difusa e Especular.

Exemplo em C

Luz Ambiente

Para inserir iluminação em uma cena em OPENGL, são necessárias duas providências:
geração de uma Normal para cada face:
glBegin(GL_POLYGON); // face posterior
glNormal3f(0,0,1); // normal da face
glVertex3f(10.0, 10.0, 10.0);
glVertex3f(-10.0, 10.0, 10.0);
glVertex3f(-10.0, -10.0, 10.0);
glVertex3f(10.0, -10.0, 10.0);
glEnd;

ativação da iluminação através da chamada da função
glEnable(GL_LIGHTING);

Isto irá gerar objetos em tons de cinza.
definição da cor da luz ambiente
const
// Define a cor da luz ambiente
LuzAmbient : Array[0..3] of Glfloat = (1.0,1.0,1.0, 1.0);
// r, g, b
Preferencialmente, esta cor deve ser branca(r=1,g=1,b=1)para permitir que todas as cores atribuídas ao objeto possam ser vistas. Se os valores de cor forem menores que 1, a luz diminuirá de intensidade.
Ativar o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LuzAmbient);
// o primeiro parâmetro define o modelo de iluminação e o segundo os parâmetros
// deste modelo através de um vetor
Observação
Para definir a cor de uma face deve-se utilizar a técnica de "color tracking". Com ela pode-se definir a cor de uma face chamando a função glColor(r,g,b) antes da definição da face. A ativação da "color tracking" é feita pela chamada glEnable(GL_COLOR_MATERIAL);

 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Exemplo Completo de Luz Difusa:

// As funções "DefineLuz", "DesenhaCubo" devem ser chamadas a partir da rotina do evento Paint o objeto de OpenGL.
procedure DefineLuz;
const
// Define a cor da luz ambiente.
LuzAmbient : Array[0..3] of GLfloat = (1.0, 1.0, 1.0, 1.0);
begin
// Habilita o uso de iluminação
glEnable(GL_LIGHTING);
// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LuzAmbient);
// Ativa o "Color Tracking"
glEnable(GL_COLOR_MATERIAL);

end;

procedure DesenhaCubo;
begin
glColor3f(0,0,0.5); // Define a cor Azul
glBegin(GL_POLYGON); // face 1
glNormal3f(0,0,1);
glVertex3f(10.0, 10.0, 10.0);
glVertex3f(-10.0, 10.0, 10.0);
glVertex3f(-10.0, -10.0, 10.0);
glVertex3f(10.0, -10.0, 10.0);
glEnd;
glColor3f(0.5,0.5,0); // Define a cor amarela
glBegin(GL_POLYGON); // face 2
glNormal3f(0,0,-1);
glVertex3f(10.0, 10.0, -10.0);
glVertex3f(10.0, -10.0, -10.0);
glVertex3f(-10.0, -10.0, -10.0);
glVertex3f(-10.0, 10.0, -10.0);
glEnd;
end;

Exemplo em Delphi

LuzAmbiente.jpg



 
Última edição:

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Luz Difusa

Uma luz do tipo Difusa tem como características básicas:
responsável pelo efeito de "degradé" nos objetos;
há um ponto a partir do qual a luz é emitida;
seu brilho é emitido indistintamente em todas as direções.
Por isto, em OpenGL, quando se trabalha com luzes difusas, deve-se determinar:
a componente ambinte da luz(opcional) ;
a cor da luz difusa(r,g,b);
a posição da luz(x,y,z).
Os passsos para tanto são os seguintes:
definir cor da luz Ambiente, a posição e a cor da Luz Difusa, através de constantes


const


LuzAmbiente : Array[0..3] of GLfloat = (0.5, 0.5, 0.5, 1.0);
// Cor da Luz Difusa
LuzDifusa : Array[0..3] of GLfloat = (0.8, 0.8, 0.8, 1.0);
// Posição da Luz Difusa
PosicaoLuz : Array[0..3] of GLfloat = (30.0, 30.0, 0.0, 1.0);
Ativar o uso da luz ambiente e o "Color Tracking"(conforme exemplo anterior)
// Habilita o uso de iluminação
glEnable(GL_LIGHTING);
// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LuzAmbient);
// Ativa o "Color Tracking"
glEnable(GL_COLOR_MATERIAL);
Definir e ativar uma luz Difusa


Em OpenGl podemos ter até 8 pontos de Luz. Cada um deles designado por uma constante(GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, ...). NoExemplo a seguir definimos as características da luz de número 0(zero).

// Define os parâmetros da Luz número Zero
glLightfv(GL_LIGHT0, GL_AMBIENT, @LuzAmbiente);
glLightfv(GL_LIGHT0, GL_DIFFUSE, @LuzDifusa );
glLightfv(GL_LIGHT0, GL_POSITION,@PosicaoLuz );
glEnable(GL_LIGHT0);

// Exibe uma linha da posição da luz até (0,0,0)
glBegin(GL_LINES);
glVertex4fv(@PosicaoLuz);
glVertex3f(0,0,0);
A partir deste ponto pode-se desenhar quaisquer objetos.
Exemplo em Delphi


LuzDifusa.jpg
 
Última edição:

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Luz Especular

Uma luz do tipo Especular tem como características básicas:
é a responsável pela geração de pontos de brilho no objeto;
o brilho é da cor da luz;
há um ponto a partir do qual ela é emitida;
seu brilho é emitido indistintamente em todas as direções;
cada tipo de material(objeto) tem um grau de especularidade(que em outras palavras define a capacidade de brilho do material).
Por isto, em OpenGL, quando se trabalha com luzes difusas, deve-se determinar:
a componente ambinte da luz(opcional) ;
a posição da luz(x,y,z).
a cor da luz difusa(r,g,b);
a cor da luz especular(r,g,b);
a cor especular do objeto(r,g,b);
o capacidade de brilho do objeto, ou o grau de concentração do brilho(algo como o grau de polimento do objeto);
Os passsos para tanto são os seguintes:
definir cor da luz Ambiente, a posição e a cor da Luz Difusa e da Luz especular, através de constantes


const
LuzAmbiente : Array[0..3] of GLfloat = (0.5, 0.5, 0.5, 1.0);
LuzDifusa : Array[0..3] of GLfloat = (0.4, 0.4, 0.4, 1.0);
LuzEspecular: Array[0..3] of GLfloat = (1.0, 0.0, 1.0, 1.0);
PosicaoLuz : Array[0..3] of GLfloat = (0.0, 20.0, 60.0, 1.0);
Especularidade: Array[0..3] of GLfloat = (0.0, 0.0, 0.0, 1.0);
Ativar o uso da luz ambiente e o "Color Tracking"(conforme exemplo anterior)


// Habilita o uso de iluminação
glEnable(GL_LIGHTING);
// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, @LuzAmbient);
// Ativa o "Color Tracking"
glEnable(GL_COLOR_MATERIAL);
Definir e ativar uma luz Especular


// Define os parâmetros da Luz número Zero
glLightfv(GL_LIGHT0, GL_AMBIENT, @LuzAmbiente);
glLightfv(GL_LIGHT0, GL_DIFFUSE, @LuzDifusa );
glLightfv(GL_LIGHT0, GL_SPECULAR, @LuzEspecular );
glLightfv(GL_LIGHT0, GL_POSITION, @PosicaoLuz );
glEnable(GL_LIGHT0);
Definir a cor especular do obejto


// Define a reflectancia do material
glMaterialfv(GL_FRONT,GL_SPECULAR, @Especularidade);
Definir o grau de especularidade do objeto


// Define a concentração do brilho.
// Quanto maior o valor do Segundo parametro, mais concentrado será o brilho.
// (Valores válidos: de 0 a 128)

glMateriali(GL_FRONT,GL_SHININESS,20);
A partir deste ponto pode-se desenhar quaisquer objetos.
Exemplo em Delphi


LuzEspecular.jpg
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
Imagens estendidas em Várias Telas (Tiled Displays)

Diversas aplicações de realidade virtual necessitam exibir cenários em um conjunto de telas colocadas lado a lado. Este é o caso das CAVEs e dos Workbenches. Um exemplo de uma cena exibida em várias telas é apresentada na Figura 22.

image002.jpg



Figura 22 – Cena em Múltiplas telas

Em OpenGL, para gerar este tipo de imagem usa-se a função glFrustum que define o View Frustum ou “volume de visualização” a ser usado para projetar uma cena da tela. Na Figura 23 pode-se observar o “volume de visualização” e sua relação com a posição do observador e do alvo.

image004.jpg


Figura 23 – Volume de Visualização

Na Figura 24 este mesmo “volume de visualização” é apresentado com suas respectivas dimensões.

image006.jpg


image008.jpg


Figura 24 – Volume de Visualização (com dimensões)

Na Figura 24, os valores DF e DN são, respectivamente as distâncias máximas e mínimas do volume visível pelo observador e L (de Left) e R (de Right) definem o quanto o observador vê à esquerda e à direita de seu ponto central de visão, exatamente na distância do plano NEAR. Para definir um volume de visualização é necessário ainda definir os limites verticais (inferior e superior) da visão do observador na distância do plano NEAR. Para efeito de exemplo estas medidas serão chamadas B (de Bottom) e T (de Top), respectivamente.

Os valores de NEAR e FAR são fornecidos, em geral, pela aplicação. Os valores de L e R podem ser calculados a partir do ângulo de visão pelas fórmulas:

L = -Near * tan(ViewAngleRad/2)

R = Near * tan(ViewAngleRad/2)

Se considerarmos o Plano NEAR como um quadrado, teremos B igual a L e T igual a R.

A partir destes valores é possível definir o volume de visualização, através da função glFrustum. O código da Figura 25 apresenta um exemplo deste procedimento.


 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
5.11.1. Dividindo o View Frustum em Múltiplas Telas

Para exibir uma cena em múltiplas telas, deve-se dividir o “volume de visualização” de forma que cada janela exiba uma parte dele. Na Figura 26 pode-se observar 3 volumes de visualização distintos.



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

// void SetViewFrustum()

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

void SetViewFrustum()

{

float Near, Left, Right, Bottom, Top;

float ViewAngleRad;



glMatrixMode(GL_PROJECTION);

glLoadIdentity();



ViewAngleRad = ViewAngle * 3.14f/180;



Near = 1; // definido na aplicação

Far = 100; // definido na aplicação



// Calcula os limites horizontais do View

// Frustum

Left = -Near * tan(ViewAngleRad/2);

Right = Near * tan(ViewAngleRad/2);



// Calcula os limites verticais do View

// Frustum

Bottom = -Near * tan(ViewAngleRad/2);

Top = Near * tan(ViewAngleRad/2);



// Seta o Frustum

glFrustum(Left, Right, Bottom, Top, Near, Far);



glMatrixMode(GL_MODELVIEW);

SetObs(); // posiciona o observador

}

Figura 25 – Setando o Volume de Visualização


image010.jpg




Figura 26 – Dividindo o Volume de Visualização

Em OpenGL, para recalcular o View Frustum, toma-se o ângulo de visão e divide-se pelo número de janelas nas quais se deseja exibir a imagem. Note que se deve dividir separadamente o volume na horizontal e na vertical pois o número de telas nestas duas direções pode ser diferente.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
No código apresentado na Figura 27 pode-se observar um exemplo que um “volume de visualização” é dividido horizontalmente em 3 janelas e verticalmente em duas. A Figura 28 apresenta o resultado visual deste programa.



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

// void SetViewFrustum()

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

void SetViewFrustum()

{

float Near, Left, Bottom, Top, Right, TileWidth, TileHeight;

float ViewAngleRad;



glMatrixMode(GL_PROJECTION); glLoadIdentity();



Near = 1; // definido na aplicação

Far = 100; // definido na aplicação



// Calcula os limites horizontais do View

// Frustum

Left = -Near * tan(ViewAngleRad/2);

Right = Near * tan(ViewAngleRad/2);



// Calcula os limites verticais do View Frustum

Bottom = -Near * tan(ViewAngleRad/2);

Top = Near * tan(ViewAngleRad/2);



// Calcula a largura e a altura de cada janela

TileWidth = (Right - Left)/3;

TileHeight = (Top - Bottom)/2;



// Seta o Frustum de cada janela

if (glutGetWindow()==jan1)// Inferior Esquerda

glFrustum(Left, Left+TileWidth,

Bottom, Bottom+TileHeight, Near, Far);



if (glutGetWindow()==jan2) // Inferior Central

glFrustum(Left+TileWidth, Left+TileWidth*2,

Bottom, Bottom+TileHeight, Near, Far);



if (glutGetWindow()==jan3) // Inferior Direita

glFrustum(Left+TileWidth*2,

Left+TileWidth*3,

Bottom, Bottom+TileHeight, Near, Far);



if (glutGetWindow()==jan4) // Superior Esquerda

glFrustum(Left, Left+TileWidth,

Bottom+TileHeight, Top, Near, Far);



if (glutGetWindow() == jan5) // Superior Central

glFrustum(Left+TileWidth, Left+TileWidth*2,

Bottom+TileHeight, Top, Near, Far);



if (glutGetWindow() == jan6) // Superior Direita

glFrustum(Left+TileWidth*2,

Left+TileWidth*3,

Bottom+TileHeight, Top, Near, 100);



glMatrixMode(GL_MODELVIEW);



SetObs();

}

Figura 27 – Código de Divisão do View Frustum


image012.jpg



Figura 28 – “Telão 3 x 2”

Exercícios

Copie este arquivo com um exemplo

Altere o programa a fim de exibir QUATRO janelas, numa composição de duas linhas e duas colunas.

No caso de usar o DEV CPP, lembre-se de colocar as opções -lopengl32 -lglu32 -lglut32 no projeto. Para baixar as bibliotecas a serem usdas no DEVCPP clique aqui.

Modifique o programa-exemplo apresentado acima de forma que se possa ter programas independentes controlando as janelas. Para a comunicação entre os programas, use a biblioteca SHARED MEMORY LIBRARY.
 

helldanger1

GForum VIP
Entrou
Ago 1, 2007
Mensagens
29,631
Gostos Recebidos
1
#include <windows.h>
#include <stdio.h>
#include <math.h>

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


float xrot;
float yrot;
float zrot;
float ratio;
float ViewAngle = 90;
double ConvRad;
float ObsX=0;
typedef struct
{
unsigned X, Y, TamX, TamY;
int JanId;
} TTile;


int Tiles[9];

int jan1, jan2, jan3;

// **********************************************************************
// void RemoveBorder(int janId)
//
// **********************************************************************
void RemoveBorder(int janId)
{
LONG style;
HWND janela;
char aux[50];

sprintf(aux, "TCG - Janela %d", janId);
janela = FindWindow(NULL, aux);

style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS
| WS_CLIPCHILDREN;

SetWindowLong (janela, GWL_STYLE, style );

}

// **********************************************************************
// void DefineLuz(void)
//
// **********************************************************************
void DefineLuz(void)
{
GLfloat LuzAmbiente[] = {0.24725f, 0.1995f, 0.07f } ;
GLfloat LuzDifusa[] = {0.75164f, 0.60648f, 0.22648f, 1.0f };
GLfloat LuzEspecular[] = {0.626281f, 0.555802f, 0.366065f, 1.0f };
GLfloat PosicaoLuz0[] = {3.0f, 3.0f, 0.0f, 1.0f };
GLfloat PosicaoLuz1[] = {-3.0f, -3.0f, 0.0f, 1.0f };
GLfloat Especularidade[] = {1.0f, 1.0f, 1.0f, 1.0f };

// Habilita o uso de iluminação
glEnable(GL_LIGHTING);

// Ativa o uso da luz ambiente
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbiente);
// Define os parametros da Luz número Zero
glLightfv(GL_LIGHT0, GL_AMBIENT, LuzAmbiente);
glLightfv(GL_LIGHT0, GL_DIFFUSE, LuzDifusa );
glLightfv(GL_LIGHT0, GL_SPECULAR, LuzEspecular );
glLightfv(GL_LIGHT0, GL_POSITION, PosicaoLuz1 );
glEnable(GL_LIGHT0);

// Ativa o "Color Tracking"
glEnable(GL_COLOR_MATERIAL);

// Define a reflectancia do material
glMaterialfv(GL_FRONT,GL_SPECULAR, Especularidade);

// Define a concentração do brilho.
// Quanto maior o valor do Segundo parametro, mais
// concentrado será o brilho. (Valores válidos: de 0 a 128)
glMateriali(GL_FRONT,GL_SHININESS,20);

}


// **********************************************************************
// void init(void)
// Inicializa os parâmetros globais de OpenGL
//
// **********************************************************************
void init(void)
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(1.0f, 1.0f, 1.0f, 0.0f); // Black Background
glEnable(GL_DEPTH_TEST); // habilita ZBuffer

}
// **********************************************************************
// void SetObs()
//
//
// **********************************************************************
void SetObs()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(ObsX, 0, 5,
ObsX,0,0,
0.0f,1.0f,0.0f);
}
// **********************************************************************
// void SetViewFrustum()
//
//
// **********************************************************************
void SetViewFrustum()
{
float Near, left, right, TileWidth;
float ViewAngleRad;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

ViewAngleRad = ViewAngle * 3.14f/180;

Near = 1;
left = -Near * tan(ViewAngleRad/2);
right = -left;
TileWidth = (right - left)/3;

if (glutGetWindow() == jan1)
{
glFrustum(left, left+TileWidth, left, right, Near, 100);
}
if (glutGetWindow() == jan2)
{
glFrustum(left+TileWidth, left+TileWidth*2,left,right, Near, 100);
}
if (glutGetWindow() == jan3)
{
glFrustum(left+TileWidth*2, left+TileWidth*3,left,right, Near, 100);
}
glMatrixMode(GL_MODELVIEW);

SetObs();
}

// **********************************************************************
// void reshape( int w, int h )
// trata o redimensionamento da janela OpenGL
//
// **********************************************************************
void reshape( int w, int h )
{

if(h == 0)
h = 1;

ratio = 1.0f * w / h;

// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Set the viewport to be the entire window
glViewport(0, 0, w, h);

// Set the clipping volume
SetViewFrustum();
}
// **********************************************************************
// void DrawCube()
//
//
// **********************************************************************
void DrawCube()
{

glBegin ( GL_QUADS );
// Front Face
glColor3f(1,1,0);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glColor3f(0,0,1);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glColor3f(1,0,1);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glColor3f(1,1,1);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glColor3f(0,0.4f,0);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glColor3f(1,0,0);
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();

}
// **********************************************************************
// void display( void )
//
//
// **********************************************************************
void display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

DefineLuz();
glLoadIdentity ( );

SetObs();

glPushMatrix();
glTranslatef ( -1.0, 0.0, -5.0 );
glRotatef ( xrot, 1.0, 0.0, 0.0 );
glRotatef ( yrot, 0.0, 1.0, 0.0 );
glRotatef ( zrot, 0.0, 0.0, 1.0 );
DrawCube();
glPopMatrix();
glPushMatrix();
glTranslatef ( +1.0f, 0.0, -5.0 );
glRotatef ( xrot, 1.0, 0.0, 0.0 );
glRotatef ( yrot, 0.0, 1.0, 0.0 );
glRotatef ( -zrot, 0.0, 0.0, 1.0 );
DrawCube();

glPopMatrix();
if (glutGetWindow() == jan3)
{
xrot+=1.0f;
yrot+=0.6f;
zrot+=0.4f;
}
glutSwapBuffers();
}
// **********************************************************************
// void RefreshAll()
//
//
// **********************************************************************
void RefreshAll()
{
glutSetWindow (jan1);
SetViewFrustum();
glutPostRedisplay();

glutSetWindow (jan2);
SetViewFrustum();
glutPostRedisplay();

glutSetWindow (jan3);
SetViewFrustum();
glutPostRedisplay();

}
// **********************************************************************
// void keyboard ( unsigned char key, int x, int y )
//
//
// **********************************************************************
void keyboard ( unsigned char key, int x, int y )
{
switch ( key )
{
case 27:
exit ( 0 );
break;
case 'a':
ViewAngle +=2;
if (ViewAngle > 178)
ViewAngle = 178;
break;
case 's':
ViewAngle -=2;
if (ViewAngle < 3 )
ViewAngle = 3;
break;
case 'z':
ObsX -=0.5f;
break;
case 'x':
ObsX +=0.5f;
break;
default:
break;
}
printf("Viewing angle %f\n", ViewAngle);
}

// **********************************************************************
// void arrow_keys ( int a_keys, int x, int y )
//
//
// **********************************************************************
void arrow_keys ( int a_keys, int x, int y )
{
switch ( a_keys )
{
case GLUT_KEY_UP: // When Up Arrow Is Pressed...
glutFullScreen ( ); // Go Into Full Screen Mode
break;
case GLUT_KEY_DOWN: // When Down Arrow Is Pressed...
glutInitWindowSize ( 700, 500 );
break;
default:
break;
}
}

void InitCallbacks(void)
{
glutDisplayFunc ( display );
glutReshapeFunc ( reshape );
glutKeyboardFunc ( keyboard );
glutSpecialFunc ( arrow_keys );

}
// **********************************************************************
// void main ( int argc, char** argv )
//
//
// **********************************************************************
void main ( int argc, char** argv )
{
glutInit ( &argc, argv );
glutInitDisplayMode ( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );


int Larg=250;
ConvRad = (2.0 * asin(1)) / 180.0;
glutInitWindowPosition (0,100);
glutInitWindowSize ( Larg, Larg);
jan1 = glutCreateWindow ( "TCG - Janela 1");

glutInitWindowPosition (Larg,100);
glutInitWindowSize ( Larg, Larg );
jan2 = glutCreateWindow ("TCG - Janela 2");

glutInitWindowPosition (Larg*2,100);
glutInitWindowSize ( Larg, Larg);
jan3 = glutCreateWindow ("TCG - Janela 3");

glutSetWindow(jan1);
InitCallbacks();
init ();

glutSetWindow(jan2);
InitCallbacks();
init ();

glutSetWindow(jan3);
InitCallbacks();
init ();

glutIdleFunc ( RefreshAll );

//RemoveBorder(1);
//RemoveBorder(2);
//RemoveBorder(3);
glutMainLoop ( );
}



Copie este exemplo

Altere o programa a fim de exibir QUATRO janelas, numa composição de duas linhas e duas colunas.

No caso de usar o DEV CPP, lembre-se de colocar as opções -lopengl32 -lglu32 -lglut32 no projeto. Para baixar as bibliotecas a serem usdas no DEVCPP clique aqui.

Exercícios
Modifique o programa-exemplo apresentado acima de forma que se possa ter programas independentes controlando as janelas.
 
Topo