Conheça a iniciativa da Biblioteca dos Desenvolvedores  
Índice da Biblioteca  
Área dos Usuários  
Fórum de Discussão  
Forúm
 
  Visualização bidimensional na prática (Viewports)

Para entender a visualização bidimensional em OPEN GL precisamos conhecer o conceito “universo”, que pode ser definido como sendo a região, plano ou espaço de uma aplicação. Como qualquer objeto pelo qual devemos representar na tela envolve coordenadas geométricas é necessário adotar um sistema de referência que irá definir uma posição a qual todos os objetos estarão desenhados.

O sistema de referência do universo (SRU) em Open GL consiste em definir as coordenadas através do plano cartesiano normal em dois eixos (x e y).
Sendo x orientado para a direita e y orientado para cima.

Conforme a figura abaixo:



Entretanto o monitor adota o sistema de referência da tela (SRT) que possui algumas diferenças ao sistema SRU.
No SRT a origem fica no canto superior esquerdo do monitor.

Conforme abaixo:



Portanto, para mostrar a correta visualização de um sistema para o outro é necessário fazer uma conversão ou mapeamento das coordenadas.

Veja a ilustração abaixo:



Resumindo iremos sempre desenhar nossos objetos com base no sistema SRU, plano cartesiano normal com eixos x e y.
Depois disso será feita o mapeamento para a tela independente do dispositivo ou resolução da tela.

Como o universo é infinito é preciso especificar qual porção queremos mapear na tela.
A essa área que delimita a área de interessa do usuário chamamos de window ou janela de seleção.

Uma window é delimitada através das coordenadas de seus cantos (esquerdo, direito, superior, inferior) no sistema SRU.

De forma análoga também é necessário definir em que parte desejamos exibir o conteúdo na window no monitor.
Essa região é chamada de viewport ou janela de exibição, uma viewport normalmente é delimitada pelo tamanho da janela GLUT correspondente ao tamanho da resolução do monitor.

Segue abaixo uma ilustração simples para entendimento:



Para mapear o objeto do sistema SRU para o sistema SRT é necessário apenas especificar a viewport e a window, utilizando as funções abaixo:

void glViewport( GLint x, GLint y, GLsizei width, GLsizei height);

Os valores especificadoes nos dois primeiros parâmetros x e y definem a posição da janela na tela enquanto os dois últimos definem a largura e a altura dessa tela.
Se você não especificar viewports no seu programa, o OpenGL assume o viewport default e cria uma para trabalhar com toda a tela. Seria o mesmo que fazer:

Exemplo:

glViewport(0, 0, fLargura/2, fAltura/2);


int glutGet(GLenum state);

Função responsável por pegar informações sobre os estados internos do GLUT. No exemplo, ela foi usada para pegar a largura e altura atual da janela do programa.
Essa função aceita muitos outros argumentos, para mais detalhe consulte o manual de referência do GLUT.

Exemplo:
glutGet(GLUT_WINDOW_WIDTH); // Pega a largura da janela
...
glutGet(GLUT_WINDOW_HEIGHT); // Pega a altura da janela


gluOrtho2D (Gldouble left, Gldouble right, Gldouble bottom, Gldouble top);

Essa função serve para definir a window quando se está trabalhando com desenhos 2D. Seus parâmetros correspondem especificamente cada borda da window. Isto é: x mínimo (borda esquerda - left) – x máximo (borda direita - right) – y mínimo (borda inferior - bottom) – y máximo (borda superior - top).

Exemplo:

gluOrtho2D (-win*aspecto, win*aspecto, -win, win);


Praticamente já trabalhamos em um viewport só que muitas vezes não declarado explicitamente e sim por default do GLUT.
Entendido o que é um viewport vamos ver como criar mais de um em um mesmo ambiente. Basicamente, o procedimento é:

- Definir viewport1
- Desenhar conteúdo na viewport1
- Definir viewport2
- Desenhar conteúdo na viewport2

Exemplo com 2 viewports




CÓDIGO...
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
#include <GL/glut.h>

void DesenhaQuadrado();
void DesenhaBorda();
void Inicializa();

static void Desenha(void);
static void TecladoNormal(unsigned char key, int x, int y);
void AlteraTamanhoJanela(GLsizei w, GLsizei h);
static void idle(void);

GLint iLargura = 0;
GLint iAltura = 0;
GLfloat win = 0.0f; 
GLfloat aspecto = 0.0f;
GLfloat ratio = 0.0f;

GLboolean HabilitaViewport = true;

int main(int argc, char *argv[])
{
   glutInit(&argc, argv);
   glutInitWindowSize(640,480);
   glutInitWindowPosition(10,10);
   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

   glutCreateWindow("Desenhos Bidimensionais - Viewports");

   glutDisplayFunc(Desenha);
   glutReshapeFunc(AlteraTamanhoJanela);
   glutKeyboardFunc(TecladoNormal);
   glutIdleFunc(idle);
   
   Inicializa();
   
   glutMainLoop();

   return 0;
}

static void Desenha(void)
{
   //Limpa a tela de visualização com a cor preta
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glLoadIdentity();

   //Canto inferior esquerdo
   glViewport(0, 0, iLargura, iAltura); 
   DesenhaQuadrado();
   
   if (HabilitaViewport)
   {
      //Canto superior direito
      glViewport(440, 280, 200, 200); 
      DesenhaQuadrado();
      DesenhaBorda();
   }

   glutSwapBuffers();
}

// Função que é chamada quando uma tecla é apertada
static void TecladoNormal(unsigned char key, int x, int y)
{
   switch (key) 
   {
      case 27 : // ESC sai do programa
         exit(0);
         break; 
      case 32 : // Barra de espaço Habilita/Desabilita Viewport
         if (HabilitaViewport) 
            HabilitaViewport = false;
         else
            HabilitaViewport = true;
         break;
   }
}

// Função que executa rotinas padrões do GLUT
static void idle(void)
{
   glutPostRedisplay();
}

void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
   // Evita a divisao por zero
   if(== 0) h = 1;

   ratio = 1.0f * w / h;
   // Atualiza as variáveis
   iLargura = w;
   iAltura = h;

   aspecto = (iLargura / iAltura);

   //Seleciona o sistema de coordenadas do tipo Projeção
   glMatrixMode(GL_PROJECTION);
   //Carrega a matriz inicial do sistema de coordenadas selecionado
   glLoadIdentity();
   
   //Define Janela(Window) de visualização 2D
   gluOrtho2D (-win*aspecto, win*aspecto, -win, win);
}

void DesenhaQuadrado()
{
   static GLfloat fAngulo = 0.0;

   glPushMatrix();
      //Rotaciona o Objeto
      glRotatef(fAngulo, 1.0f, 0.0f, 0.0f );
      glRotatef(fAngulo, 0.0f, 1.0f, 0.0f );
      glRotatef(fAngulo, 0.0f, 0.0f, 1.0f );
      glColor3f(1.0,0.0,0.0);
      //Desenha um Quadrado
      glBegin(GL_QUADS);
         glVertex2f(-0.25f, -0.25f);
         glVertex2f(-0.25f,  0.25f);
         glVertex2f( 0.25f,  0.25f);
         glVertex2f( 0.25f, -0.25f);
      glEnd();
   glPopMatrix();
   
   glColor3f(0.0,1.0,0.0);
   glBegin(GL_QUADS);
      glVertex2f(-0.95f, 0.95f);
      glVertex2f(-0.85f, 0.95f);
      glVertex2f(-0.85f, 0.85f);
      glVertex2f(-0.95f, 0.85f);
   glEnd();
   
   fAngulo += 0.05f;
}

void Inicializa()
{
   //Limpa a tela com a cor preta RGBA
   glClearColor(0.0, 0.0, 0.0, 1.0);

   //Define a espessura da linha que compõe a borda de cada viewport
   glLineWidth(3);
}

void DesenhaBorda()
{
   glColor3f(1.0, 1.0, 0.0);
   glBegin(GL_LINES);
      //Linha Topo
      glVertex2f(-1.0, 1.0);
      glVertex2f(1.0, 1.0);

      //Linha Direita
      glVertex2f(1.0, 1.0);
      glVertex2f(1.0, -1.0);

      //Linha Base
      glVertex2f(1.0, -1.0);
      glVertex2f(-1.0, -1.0);

      //Linha Esquerda
      glVertex2f(-1.0, -1.0);
      glVertex2f(-1.0, 1.0);
   glEnd();
}


FIM DE CÓDIGO...
Executando o código acima você verá duas viewports.
São elas: a default que fica de fundo e uma no canto superior direito da tela que possui os mesmos objetos só que de forma reduzida.


Exemplo com 4 viewports

CÓDIGO...
001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
#include <GL/glut.h>

void DesenhaQuadrado();
void DesenhaLosango();
void DesenhaPoligono();
void DesenhaTriangulo();
void DesenhaBorda();

void Inicializa();

static void Desenha(void);
static void TecladoNormal(unsigned char key, int x, int y);
void AlteraTamanhoJanela(GLsizei w, GLsizei h);
static void idle(void);

GLint fLargura = 0;
GLint fAltura = 0;
GLint win = 0; 
GLfloat aspecto = 0;

int main(int argc, char *argv[])
{
   glutInit(&argc, argv);
   glutInitWindowSize(640,480);
   glutInitWindowPosition(10,10);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

   glutCreateWindow("Utilizando vários Viewports");

   glutDisplayFunc(Desenha);
   glutReshapeFunc(AlteraTamanhoJanela);
   glutKeyboardFunc(TecladoNormal);
   glutIdleFunc(idle);
   
   Inicializa();
   
   glutMainLoop();

   return 0;
}

static void Desenha(void)
{
   //Limpa a tela de visualisação com a cor preta
   
   glClear(GL_COLOR_BUFFER_BIT);

   //Canto inferior esquerdo
   glViewport(0, 0, fLargura/2, fAltura/2); 
   DesenhaQuadrado();
   DesenhaBorda();

   //Canto superior esquerdo
   glViewport(0, fAltura/2, fLargura/2, fAltura/2); 
   DesenhaTriangulo();
   DesenhaBorda();

   //Canto superior direito
   glViewport(fLargura/2, fAltura/2, fLargura/2, fAltura/2); 
   DesenhaLosango();                          
   DesenhaBorda();

   //Canto inferior direito
   glViewport(fLargura/2, 0, fLargura/2, fAltura/2); 
   DesenhaPoligono();
   DesenhaBorda();   

   glFlush();
}

// Função que é chamada quando uma tecla é apertada
static void TecladoNormal(unsigned char key, int x, int y)
{
   switch (key) 
   {
      // caso aperte ESC sai do programa
      case 27 : 
         exit(0);
         break; 
   }
}

// Função que executa rotinas padrões do GLUT
static void idle(void)
{
   glutPostRedisplay();
}

void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
   // Evita a divisao por zero
   if(== 0) h = 1;

   // Atualiza as variáveis
   fLargura = w;
   fAltura = h;

   aspecto = (float) fLargura/fAltura;

   // Inicializa o sistema de coordenadas
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   
   // e Define Janela de visualização 2D
   gluOrtho2D (-win*aspecto, win*aspecto, -win, win);
}

void DesenhaQuadrado()
{
   glColor3f(1.0,0.0,0.0);
   //Desenha um Quadrado
   glBegin(GL_QUADS);
      glVertex2f(-0.25f, -0.25f);
      glVertex2f(-0.25f,  0.25f);
      glVertex2f( 0.25f,  0.25f);
      glVertex2f( 0.25f, -0.25f);
   glEnd();
}

void DesenhaTriangulo()
{
   glColor3f(0.0,1.0,0.0);
   //Desenha um Triângulo
   glBegin(GL_TRIANGLES);
      glVertex2f(-0.25f, -0.25f);
      glVertex2f( 0.0f,   0.25f);
      glVertex2f( 0.25f, -0.25f);
   glEnd();
}

void DesenhaPoligono()
{
   glColor3f(1.0,1.0,1.0);
   //Desenha um Poligono
   glBegin(GL_POLYGON);
      glVertex2f( 0.0f,  0.50f);
      glVertex2f(-0.25f, 0.25f);
      glVertex2f(-0.25f,-0.25f);
      glVertex2f( 0.0f, -0.50f);
      glVertex2f( 0.25f,-0.25f);
      glVertex2f( 0.25f, 0.25f);
   glEnd();
}

void DesenhaLosango()
{
   glColor3f(0.0,1.0,1.0);
   //Desenha um Losango
   glBegin(GL_POLYGON);
      glVertex2f(-0.25f, 0.0f);
      glVertex2f( 0.0f,  0.25f);
      glVertex2f( 0.25f, 0.0f);
      glVertex2f( 0.0f, -0.25f);
   glEnd();
}

void Inicializa()
{
   glClearColor(0.0, 0.0, 0.0, 0.0);

   //Define a espessura da linha que compõe a borda de cada viewport
   glLineWidth(3);
}

void DesenhaBorda()
{
   glColor3f(1.0, 1.0, 0.0);

   glBegin(GL_LINES);
      //Linha Topo
      glVertex2f(-0.96, 0.96);
      glVertex2f(0.96, 0.96);

      //Linha Direita
      glVertex2f(0.96, 0.96);
      glVertex2f(0.96, -0.96);

      //Linha Base
      glVertex2f(0.96, -0.96);
      glVertex2f(-0.96, -0.96);

      //Linha Esquerda
      glVertex2f(-0.96, -0.96);
      glVertex2f(-0.96, 0.96);
   glEnd();
}


FIM DE CÓDIGO...

Executando o código acima você verá a viewport principal dividida em 4.
Em cada uma tem um desenho geométrico diferente. Dessa forma fica claro a forma de trabalhar com várias janelas de exibição ao mesmo tempo.

Com essa técnica de viewports podemos incrementar em nosso jogo um espelho retrovisor, mini-mapa, radar, janela...etc. A imaginação e as aplicações são infinitas...
Se houver alguma dúvida vamos movimentar o fórum.

Abraço!

Download do exemplo 1 - Glut - Clique Aqui

Download do exemplo 2 - Glut - Clique Aqui




Contribuidor
Bruno A. Rovela
05/01/2009


 

« Anterior

 

Próximo »

 
 

01/06/2007 (C) Copyright. Todos os Direitos Reservados. Leia a política de privacidade do portal.
É proibida a cópia de conteúdo deste site de acordo com a Lei Brasileira de Direitos Autorais.