|
Para desenhar qualquer objeto no espaço, é necessário descrevê-lo. E, para descrever um objeto, você necessita de referências, onde medidas se encontram numa escala válida. Normalmente, fora do OpenGL, descrevemos a posicionamento de pontos através da notação de linha/coluna. Embora essa notação seja adequada para o desenho de textos, ela está muito afastada da notação matemática, e acaba se tornando pouco prática para o desenho de figuras.
No OpenGL, assim como em praticamente todas as APIs 3D, você pode definir o seu próprio sistema de coordenadas. O sistema padrão, utilizado até agora, envolvia coordenadas de -1 até 1, tanto em x, y e z. O que fazia que as imagens ficassem lateralmente esticadas, já que a tela não é um quadrado e, logo, -1 até +1 em x é uma distância maior que -1 até +1 em y.
Nesse artigo, vamos aprender sobre como o OpenGL define o sistema de coordenadas, como definir o nosso próprio sistema e as diferentes formas de mapeamento de coordenadas.
Coordenadas cartesianas 2D
Além de diversos trabalhos de filosofia (e da criação da frase “Penso, logo existo.”), René Descartes (ou, Renatus Cartesius, em latim) foi também um matemático importante, e criou duas técnicas que conhecemos hoje como sistema cartesiano e geometria analítica. Se tivermos que atribuir um pai a computação gráfica, Descartes seria realmente um ótimo candidato à vaga.
A localização de cada ponto cartesiano é formada de um par de números, um no eixo x e outro no eixo y, chamados coordenadas. A coordenada x mede uma distância na direção horizontal e a y uma distância na posição vertical. A notação comumente utilizada para descrever um ponto é colocar ambas as coordenadas entre parênteses, separadas por vírgulas. Para evitar confusão e por ser mais próxima do que programaremos, usaremos a notação de números reais americana, com um “ponto” no lugar da vírgula. Assim, exemplos de coordenadas cartesianas seriam: (14.17, 50.23) ou (3, 4).
A figura abaixo, mostra o sistema cartesiano bidimensional, tal como vemos durante todo segundo grau. Ele é formado por dois eixos perpendiculares, definidos por duas retas marcadas numa unidade qualquer. O ponto (0,0), onde os dois eixos se cruzam em um ângulo de 90 graus, é chamado de origem. Quaisquer duas retas não colineares formam um plano (na verdade, basta uma reta e um ponto não colinear para definir um plano) e o plano formado pelo eixo cartesiano é o plano de desenho 2D.
Clipping de coordenadas
O sistema de coordenadas pode ser infinito, mas nossos monitores não são. Eles têm uma medida fixa, geralmente descrita em termos de pixels. Antes de iniciar o desenho, podemos dizer ao OpenGL como mapear os pares coordenados em unidades da tela, os pixels. Fazemos isso através da função void gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top). Essa função aceita quatro parâmetros, que definem a coordenada máxima e mínima que cada eixo ocupará na área de desenho.
A figura abaixo mostra alguns exemplos dessa função na prática:
Também é possível fazer um eixo em que a menor coordenada esteja no topo e a maior na base, como é padrão em muitos aplicativos. Essa prática, entretanto, não é muito utilizada pela comunidade OpenGL.
A área onde o mapeamento é feito é chamada de clipping area, na tradução literal “área de recorte”. Isso porque mostramos ao OpenGL que parte do eixo cartesiano deve ser “recortada” para caber dentro da área de desenho.
Viewport: Definindo a área de desenho
Os jogos geralmente utilizam toda a área da tela para o desenho. Mas isso nem sempre é desejável para todos os tipos de aplicação. Usamos o comando void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) para definir exatamente o local e a área onde queremos desenhar. Por estramos tratando aqui de coordenas da janela, dentro do monitor, todas as medidas são dadas em pixels.
Você também pode usar o Viewport para aumentar ou diminuir o tamanho da imagem.
Por padrão, o viewport do OpenGL ocupa toda a janela. Entretanto, é sempre recomendável executar o comando glViewport pois algumas implementações do OpenGL mais antigas simplesmente ignoram esse padrão e, sem o comando, não desenham nada.
Coordenadas cartesianas 3D
Não é muito difícil imaginar um eixo cartesiano com mais uma dimensão. Crie um eixo perpendicular tanto a y, quanto a x e chame-o de eixo z. Definimos os pontos a partir de 3 coordenadas e, voilá. Temos um novo eixo cartesiano, tridimensional.
Embora matematicamente perfeito, ao pensar no monitor alguns alarmes devem soar na sua cabeça. Afinal, nem todos tem um monitor 3D em casa, e seu preço inicial ainda é extremamente caro. Portanto, como podemos “espremer” três dimensões em apenas duas? Através de projeções, calculadas com base em trigonometria e matrizes. O OpenGL trabalha com duas formas diferentes de projeção.
Projeção ortográfica
O primeiro tipo de projeção é o mais utilizado em CADs, programas de arquitetura, e jogos isométricos. É chamada de projeção ortográfica, ou projeção paralela. Para criar essa projeção você desenha uma forma retangular. Tudo que está fora dessa forma, não é desenhado. Por isso volume definido por essa forma, é chamado volume de visualização (viewing volume). Todos os objetos parecem ter o mesmo tamanho, independente do quão próximos ou o quão afastados se encontrem. Você especifica a projeção ortográfica através da função void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far). O desenho abaixo, ajuda a entender cada um desses valores:
A funçao gluOrtho2D, vista no tópico anterior, simplesmente fornece os valores -1 e 1 para near e far.
Projeção em perspectiva
Ao falarmos de jogos 3D, a forma de projeção mais comum é a projeção em perspectiva. Essa projeção faz com que objetos mais distantes sejam desenhados em tamanho menor do que se estivessem próximos. Nessa projeção o viewing volume não é definido por um retângulo e sim por uma forma que lembra uma pirâmide que sofreu um corte paralelo a base, chamada de frustum.
A função que permite-nos definir o tamanho do frustum é a seguinte:
Abaixo, uma figura que nos ajuda a entender cada um desses parâmetros:
Uma das grandes dificuldades em usar essa função diretamente é saber o tamanho correto para os valores, de modo a formar uma imagem convincente. Para resolver esse problema, foi incluída na biblioteca de utilidades a função gluPerspective, que define o frustum baseada em outros parâmetros. A assinatura da função é a seguinte:
void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
Onde fovy é o ângulo de visão na direção y (valores convincentes para os humanos variam de 45 até 60 graus), aspect é a razão entre a largura e a altura, ou seja, x / y e near e far definem o quão longe ou próximo essa visão irá cobrir. Abaixo, uma figura descrevendo esses mesmos parâmetros:
Combinando projeções
Tipicamente, num jogo 3D, combinamos dois tipos de projeções. Primeiro, desenhamos todo o cenário usando a projeção em perspectiva. Em seguida, utilizamos a projeção ortográfica 2D para desenhar o heads-up display, com as informações de vida, balas, pontuação, etc. Veja como exemplo a tela principal do Bola Gelada:
A título de curiosidade, veja como foram definidas as funções no bola gelada:
- Viewport: glViewport (0, 0, GAME_WINDOW.getWidth(), GAME_WINDOW.getHeight());
- Perspectiva: gluPerspective(60.0f, GAME_WINDOW.getRatio(),1 ,15000);
- HUD: gluOrtho2D(0, GAME_WINDOW.getWidth(), GAME_WINDOW.getHeight(), 0);
Usando os comandos
Todos os comandos vistos, exceto glViewport, precisam ser usados na matriz de projeção do OpenGl. Entraremos em mais detalhes sobre as matrizes nos próximos artigos, por hora, apenas decore a sintaxe. Abaixo, um exemplo com glOrtho2D, mas que vale também para glOrtho, glPerspective e glFrustum:
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); //Resetamos a projeção atual
gluOrtho2D(0, GAME_WINDOW.getWidth(),
GAME_WINDOW.getHeight(), 0);
glMatrixMode(GL_MODELVIEW);
Resumindo
- Você viu como definir a clipping area, ou seja, o tamanho do eixo cartesiano na área de desenho, através da função gluOrtho2D;
- Também aprendeu a como definir o tamanho da área de desenho através da função glViewport;
- Viu como o OpenGL projeta coordenadas tridimensionais em bidimensionais;
- Aprendeu a como definir o modo de projeção ortográfica usando a função glOrtho;
- Entendeu que a projeção em perspectiva é mais adequada ao desenho 3D, e aprendeu a defini-la com a função glFrustum;
- Viu que é possível combinar duas projeções, para desenhar o HUD de um jogo 3D.
Exercícios
- Use a função glOrtho para criar um sistema de coordenadas proporcional a sua tela, como por exemplo de -40 até 40 na largura e de -30 até 30 na altura para uma janela em 800×600. Então, altere o seu cubo para ser desenhado nesse novo sistema. Note que o cubo parecerá melhor desenhado, agora que as coordenadas são proporcionais;
- Agora use a função gluPerspective para desenhar o cubo em perspectiva (você terá que incluir o header “GL/GLU.h”). Você notará que o cubo parecerá ainda mais bem desenhado, já que o OpenGL desenhará a parte de trás ligeiramente menor que a parte da frente.
Importante: Por padrão, a câmera está localizada na origem e voltada para -z. Portanto, para você não ficar exatamente no centro do cubo ao aplicar esse comando, desloque-o usando o comando glTranslatef(x,y,z); antes de desenha-lo ou gira-lo, onde x, y e z são distâncias. Uma boa medida para os valores de x, y e z usando-se o glOrtho sugerido no primeiro exercício é (0,0, -10). Veremos detalhes sobre esse comando no próximo artigo.
-
Experimente o modo de perspectiva em outros exercícios, como o das pirâmides e o da mola.
Referências
- OpenGL Superbible;
- OpenGL Red Book;
- Programming Game AI By Example;
- Biografia de René Descartes, na Wikipedia;
-
19/07/2010 15:21:51 |SAdministrator| Vinícius Godoy de Mendonça - SDL

Sim, todas as funções do OpenGL funcionam na SDL.
Na verdade, a SDL só monta a tela e abre a superfície OpenGL, a partir dali, você está usando OpenGL diretamente.
O problema dos caracteres internacionais é que muitos são unicode. Nesse caso, você tem que trabalhar usando a função SDL_SetEnableUnicode(true);
http://sdl.beuc.net/sdl.wiki/SDL_EnableUNICODE
-
21/07/2010 06:45:52 |187.90.84.xxx| Neto - Mas...

Mesmo assim, mesmo ativando o SDL_EnableUNICODE e pegando as teclas com key.keysym.unicode ou seria key.unicode. ? Não lembro bem, a questão é que com as demais teclas funciona, exceto a do acento agudo (´) e a do til (~), pra furar esse buraco tive que fazer com scancode. Sabe me dizer o porque disso ?
-
21/07/2010 08:17:35 |SAdministrator| Vinícius Godoy de Mendonça - Unicode

Não sei o porque.
Nunca precisei fazer nada para valer usando SDL e Unicode.
Se descobrir, por favor, compartilhe aqui com a gente.
-
21/07/2010 14:45:18 |187.90.45.xxx| Neto - re: Unicode
Vinícius Godoy de Mendonça Escreveu:Não sei o porque.
Nunca precisei fazer nada para valer usando SDL e Unicode.
Se descobrir, por favor, compartilhe aqui com a gente.q pena.... pelo jeito não sou só eu que tenho esse problema. Afinal de contas como a SDL obtem os caracters internacionais ? E porque ele retorna um Uint16 ? Pelo que me consta existem caracteres que superam e muito esse tipo de dados.
-
21/07/2010 14:51:31 |Administrator| Bruno Crivelari Sanches

Essa eu (acho que) sei!
Existem varios formatos Unicode, o da SDL pelo jeito é o UTF-16, são 65536 caracteres e acho que já li em algum lugar que da conta do recado sim.
Além deste tem o UTF32 e o que acho mais pratico UTF-8.
Se não me engano a API do windows é UTF-16, dai a escolha da SDL e acredito que no Windows eles peguem isso diretamente da API dele.
-
21/07/2010 15:02:46 |187.90.45.xxx| Neto - HUm....

A tah, agora saquei. Mas só não entendo o pq fica dandos esses erros se o UNICODE era justamente para teclados internacionais. Acabei de fazer um exemplo aki e até a tecla "P" retorna 0 com UNICODE. Algum de vcs poderia fazer testes para comprovar minhas duvidas, porque pode ocorrer de ser meu SDL com defeito ou mau uso de código. t++
-
21/07/2010 15:12:26 |Administrator| Bruno Crivelari Sanches

Fiz um teste aqui e parece funcionar. Posta o código num daqueles notepad onlines para a gente ver.
T+
-
21/07/2010 15:39:03 |187.90.45.xxx| Neto - re:

O BCS respondeu, o lance que só sai unicode do acento agudo depois que aperta outra tecla. Vlw as respostas pessoal.
-
21/07/2010 16:02:21 |SAdministrator| Vinícius Godoy de Mendonça

Mesmo o padrão unicode estendido tem apenas 16 bytes por "default". O que acontece é que tem um valor no primeiro byte que daí indicará que seguem mais dois bytes após aquele.
Ou seja, pelo unicode completo, fica virtualmente impossível saber o número de caracteres de um texto só olhando o número de bytes dele.
Mas não sei se a SDL trabalhar com esse padrão, creio que não.
-
25/07/2010 14:32:34 |200.181.150.xxx| Anônimo - re:
Vinícius Godoy de Mendonça Escreveu:Mesmo o padrão unicode estendido tem apenas 16 bytes por "default". O que acontece é que tem um valor no primeiro byte que daí indicará que seguem mais dois bytes após aquele.
Ou seja, pelo unicode completo, fica virtualmente impossível saber o número de caracteres de um texto só olhando o número de bytes dele.
Mas não sei se a SDL trabalhar com esse padrão, creio que não.Obrigado por mais esse esclarecimento. Sendo assim, já que todas as minhas perguntas foram respondidas, então reservo-me o direito de dar um fim nessa discurção. T++ galera vlw .
-
26/07/2010 21:48:07 |189.110.154.xxx| Jose Carlos Pinna

Muito bom! Não vejo a hora de entrar textura, tenho algumas duvidas.
Tenho um bmp rico em detalhes com muita gradiente 1024/768 na allegro vai bem mais quando passo para opengl eu tenho que mexer no tamanho dela para que a opengl aceite e depois o filtro faz os ajustes mais percebo que acaba perdendo qualidade em alguns pontos sou muito iniciante no opengl mais espero que quando entrar em textura eu entenda o que esta acontecendo.
-
26/07/2010 21:52:53 |SAdministrator| Vinícius Godoy de Mendonça - Texturas

Bem. As texturas no OpenGL tem que ter largura e altura que sejam potências de 2. Placas mais novas renderizam outros tamanhos, mas com perda de qualidade ou performance.
Tente alterar sua textura para um tamanho como 512x512, e veja se a performance melhora. Outra coisa, é possível também configurar os filtros de textura.
Alguns filtros tem melhor qualidade que outros, e é aí que entram aquele configurações que os jogos dão de "bilinear", "trilinear", "anisotrópico", etc... veremos mais sobre essas configurações no artigo sobre texturas.
-
27/07/2010 21:48:39 |187.11.23.xxx| Pinna

Eu ja tentei usando exemplos prontos só trocando pelo meu bmp alterando o tamanho mais quando comparo com o original tem perda de qualidade mais com certeza é falta de conhecimento meu vou estudar esses filtros .
Valeu!!
-
27/07/2010 22:18:51 |187.11.23.xxx| Anônimo

Vinícius desculpe se estou sendo inconveniente mais quando estou pesquisado na net sempre vejo comentários bons seus e por isso acho que você é a pessoa mais indicada para me ajudar.
Às vezes estou estudando c++ opengl, como agora mais ai eu dou uma fuçada nessas engines profissionais e ate essas gratuitas e fico em duvida devo estudar as engines, devo estudar Java quero me dedicar em uma coisa só para aprender bem quero me tornar um bom programador e quem sabe um dia trabalhar na área; por favor, qual a sua opinião.
-
28/07/2010 09:49:47 |SAdministrator| Vinícius Godoy de Mendonça

Primeiro de tudo, você já tem alguma curso de graduação? Se não tiver, comece por aí, preferencialmente, com algum curso de ciência ou engenharia da computação.
É importante aprender a programar bem. E isso inclui:
a) Entender os conceitos básicos: saber bem OO, saber bem estruturas de dados, saber bem matemática (se você for pegar CG ou física). Enfim, entender os conceitos;
b) Ter boas noções sobre boas práticas de programação: Refatoração, desenvolvimento orientado a testes, ler livros como "Effective C++" ou "Effective Java", conhecer bem as APIs que você está usando;
c) Ter boas noções sobre processos de desenvolvimento;Note que nada disso envolve uma linguagem específica, ou uma engine. Linguagem e engine são ferramentas.
Se você quer entrar na indústria de jogos, especificamente, pode ser uma boa idéia fazer em seguida uma pós-graduação na área. Assim você conhece bem os campos que a área de jogos contempla (CG, IA, Matemática e Física, Redes, Etc).
Quanto à linguagem, se você tem pretensões de entrar de cabeça na indústria, procure olhar com mais carinho para o C++. É a linguagem mais usada na indústria de jogos.
Engines são interessantes para um desenvolvimento mais agradável e mais rápido, mas mesmo elas exigem que você tenha um certo conhecimento do básico, antes de começar. Por isso, mesmo se usa-las, será bom conhecer como a placa de vídeo funciona, ou os conceitos do OpenGL e do DirectX de iluminação, texturas, shaders, etc.
-
28/07/2010 12:57:46 |189.78.204.xxx| Anônimo

Muito obrigado pela sua opinião mais infelizmente faculdade não da para min eu achava que seria possível estudar com livros e net.
-
28/07/2010 13:51:15 |SAdministrator| Vinícius Godoy de Mendonça

Ué, por que você não pode fazer faculdade?
Bom, comece então pelo roadmap C++ que tem aqui mesmo no site.











tenho uma duvida. Com relação ao uso do OpenGL com a SDL. Todas as funções do open GL funcionam no SDL ? E vc tem alguma forma de resolver o problema de imput de teclados ineternacionais, porque algumas teclas retorna 0 como key e unicode;