António Ramires Fernandes + Luís Paulo Santos - Computação Gráfica 08/09António Ramires Fernandes + Luís Paulo Santos - Computação Gráfica 08/09
Computação Gráfica
Geração de Geometria - Terrenos
DI-UM Computação Gráfica 06/07 2
Mapas de Alturas
Intensidade por pixel pode representar uma altura numa grelha regular
DI-UM Computação Gráfica 06/07 3
Terrenos a partir de Imagens
• Objectivo:– Dada uma imagem criar uma grelha regular em que a altura de
cada ponto da grelha corresponde à intensidade do pixel correspondente.
• Tarefas:
– Carregar a imagem– Criar a geometria do terreno
a partir da matriz de pixels extraída da imagem.
– Colocar todas as entidades domodelo na altura correcta
Carregar a Imagem - tgalib
• Em www.lighthouse3d.com é disponibilizado código para carregar TARGA (.TGA):
tgaInfo * tgaLoad(char *filename);
typedef struct {
int status;
unsigned char type, pixelDepth;
short int width, height;
unsigned char *imageData;
}tgaInfo;
DI-UM Computação Gráfica 06/07 4
DI-UM Computação Gráfica 06/07 5
Alternativa: DevIL
• http://openil.sourceforge.net/“A full featured cross-platform image library”
• Abrir um ficheiro de imagem
ilInit();
ilGenImages(1,ima); // unsigned int ima[...]
ilBindImage(ima[0]);ilLoadImage(filename); // char *filename
DI-UM Computação Gráfica 06/07 6
Alternativa: DevIL
• Aceder aos dados e informações da imagem
int width = ilGetInteger(IL_IMAGE_WIDTH);
int height = ilGetInteger(IL_IMAGE_HEIGHT);
unsigned char *imageData = ilGetData();
DI-UM Computação Gráfica 06/07 7
Alternativa: DevIL
• Converter para escala de cinzentos
ilConvertImage(IL_LUMINANCE,IL_UNSIGNED_BYTE);
outras opções: IL_RGB, IL_RGBA
DI-UM Computação Gráfica 06/07 8
Alternativa: DevIL
• Exemplo para carregar uma imagem:
unsigned int t;
ilGenImages(1,&t);
ilBindImage(t);
ilLoadImage("bla.jpg");
tw = ilGetInteger(IL_IMAGE_WIDTH);
th = ilGetInteger(IL_IMAGE_HEIGHT);
imgData = ilGetData();
Geração de geometria
• Gerar o terreno como uma strip de triângulos, sendo y dados pelo valor do h-map no ponto (xt,zt)
• Origem (0,0) no centro do mundo e canto do H-Map
• Atenção aos diferentes sistemas de eixos
DI-UM Computação Gráfica 06/07 9
(0,0)Mundo
x
z H-Map
xt
zt
(0,0)
Geração de geometria
for (z=0 ; z < MapL-1 ; z++) { glBegin(GL_TRIANGLE_STRIP);
for (x=0 ; x < MapW ; x++) {
glVertex3f (x0+x, Map[x][z+1], z0-(z+1));
glVertex3f (x0+x, Map[x][z], z0-z); }
glEnd(); }
DI-UM Computação Gráfica 06/07 10
(0,0)Mundo
x
z H-Map
xt
zt
(0,0)
Geometria: Display Lists
• Conjunto de comandos pré-compilados que podem ser reutilizados:// Create the id for the display listterrainDL = glGenLists(1);// create the display listglNewList(terrainDL,GL_COMPILE);
for (z=0 ; z < MapL-1 ; z++) {
glBegin(GL_TRIANGLE_STRIP);
for (x=0 ; x < MapW ; x++) {
glVertex3f (x0+x, Map[x][z+1], z0-(z+1));
glVertex3f (x0+x, Map[x][z], z0-z);
}
glEnd();
}
glEndList();
DI-UM Computação Gráfica 06/07 11
Geometria: Display Lists
• Na função que desenha a cena (ex., renderScene()) basta chamar a display list:
glCallList (TerrainDL);
• Permite um aumento de desempenho significativo devido à pré-compilação dos comandos de especificação da geometria
• Uma display list pode ser alterada executando de novo glNewList() .. glEndList()
• Uma display list pode ser removida com glDeleteLists()
DI-UM Computação Gráfica 06/07 12
Geometria: terrain.cpp
• O ficheiro terrain.cpp disponibiliza o esqueleto de código para:
– Carregar o h-map a partir e um ficheiro (usando tgaLoad())int terrainLoadImage (char *filename, int normals);
– Criar a display list devolvendo o seu ID int terrainCreateDL (float xOff, float yOff, float zOff);
– Dadas as coordenadas do mundo (x,z) devolver a respectiva altura de acordo com o height mapfloat terrainGetHeight (float x, float z);
DI-UM Computação Gráfica 06/07 13
DI-UM Computação Gráfica 06/07 14
Exercício
• Adapte a aplicação desenvolvida nas sessões anteriores para que:– Carregue um height map e desenhe o terreno de acordo
com estes– Posicione os vários elementos (indios, cowboys, arvores,
tesouro) à altura apropriada– A câmara móvel faça surface following, isto é, se
desloque ao longo da superfície adaptando-se à respectiva altura
Interpolação bilinear
• As coordenadas no mundo são números reais, as coordenadas no mapa de textura são inteiros (melhor, o h-map só está definido para coordenadas inteiras)
• Solução: interpolação bilinear
DI-UM Computação Gráfica 06/07 15
(x,z)
x1 x2z1
z2
xFrac
zFrac
hb
ha
x1 = int(x); xFrac = frac(x); x2 = x1+1;
z1 = int(z); zFrac = frac(z); z2 = z1+1;
ha = h(x1,z1)*(1-xFrac) + h(x2,z1)*xFrac;
hb = h(x1,z2)*(1-xFrac) + h(x2,z2)*xFrac;
h = há*(1-zFrac) + hb*zFrac;
Mapeamento
• Neste momento, a área do terreno é determinado pela resolução do h-map.Modifique o código de forma a que o utilizador possa indicar a resolução pretendida para o terreno, invocando a função terrainDim (int wWidth, int wLength);
• Note que para passar de coordenadas (x,z) do mundo para (xt, zt) do h-map deverá aplicar a função:
DI-UM Computação Gráfica 06/07 16
)*2,2*(),(),(wLength
GridLengthzGridLengthGridWidth
wWidth
GridWidthxzxfztxt