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.


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. 



Figura 23 – Volume de Visualização

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

  

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.

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

 

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.

            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

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.