Curso
de Especialização em Desenvolvimento de Jogos Digitais
Programação
2D
AULA PRÁTICA -
TRANSFORMAÇÕES GEOMÉTRICAS HIERÁRQUICAS
O objetivo deste exercício é exercitar a
criação de grafos de cena.
Descompacte os fontes deste link e
inclua-os em um projeto com OpenGL.
Para obter instruções sobre como criar um projeto OpenGL
usando o Visual Studio acesse a página da última aula prática.
Compile o programa e controle os objetos na tela com as seguintes
teclas:
- 0,1, 2: definem qual é objeto ativo;
- teclas de seta LEFT, RIGHT: movem o objeto ativo para
frente/trás.
- teclas de seta UP, DOWN: giram o objeto
ativo para esquerda/direita.
- barra de espaço: imprime no console as coordenadas do objeto
ativo.
DESCRIÇÃO DOS FONTES
Tools.cpp
e Tools.h
Contém funções auxiliares de cálculos
matemáticos. Analise o Tools.cpp para ver a
descrição das funções.
void
InverteMatriz( float a[4][4], float b[4][4]);
void
MultiplicaMatriz(float m1[4][4], float m2[4][4], float m[4][4]);
float
calculaDistancia(float P1[3], float P2[3]);
Desenhos.cpp e
Desenhos.h
Contém as funções de desenhos dos objetos em
coordenadas do sistema de referência do objeto, ou seja, SEM as
transformacoes geométricas que definem a
posição, a rotação e a escala de
uma instância
Via de regra, é neste fonte que devem ser colocadas os comandos
OpenGL que fazem os desenhos.
void DesenhaContornoCirculo(GLfloat
raio, GLfloat centrox, GLfloat centroy);
void
DesenhaCirculo(GLfloat raio, GLfloat centrox, GLfloat centroy);
void DesenhaTexto(char
*string, GLfloat posX, GLfloat posY);
void DesenhaCarro();
void
DesenhaHelicoptero();
Objeto.cpp e
Objeto.h
Contém a estrutura capaz de armazenar uma instância de um
objeto. Os métodos que aplicam as transformações
geométricas estão nestes fontes.
A struct que define esta instância é a seguinte:
typedef struct Objeto {
int
tipo;
int
nroDeFilhos;
bool
eh_filho;
GLfloat M[4][4];
Objeto *Filho;
Objeto *Pai;
void
setTipo(int t);
void
Init();
void
Rotate(float ang, float x, float y, float z);
void
Translate(float x, float y, float z);
void
Scale(float x, float y, float z);
void
Draw();
void
ImprimeMatriz(const char *msg);
void
InstanciaPonto(float PontoIN[3], float PontoOUT[3]);
void
AdicionaFilho(Objeto *filho);
void
RemoveFilho();
} Objeto;
Os atributos têm o seguinte significado:
int tipo; // define se o objeto é um helicoptero(0) ou um
carro(1)
int nroDeFilhos; //define quantos filhos tem o objeto no momento
bool eh_filho; // informa se o objeto é filho de algum outro
objeto do cenário
Objeto *Filhos; // vetor com apontadores para os filhos do objeto
GLfloat M[4][4]; // matriz de transformação do objeto
Objeto *Pai; // Ponteiro para o pai do objeto
Analise o fonte Objeto.cpp
e veja a descrição de cada
função.
TransfHierarq.cpp
Módulo principal que controla a exibição do
cenário.
O programa trabalha com o conceito de objeto
ativo, que define sobre qual objeto as
transformações comandadas pelo teclado serão
aplicadas. Para ativar um objeto pressione 0, 1 ou 2.
As instancias dos objeto estão armazenadas no vetor
Objeto Cenario[10];
As principais funções do módulo são:
Função Init():
Faz as iniciaizações de OpenGL e cria as instâncias
que compõem o cenário.
O trecho de código abaixo é que
inicializa as instâncias. No caso, há 3 instâncias.
A ZERO é um helicóptero e as demais são carros.
QTD_OBJETOS = 3;
ObjetoAtivo =
0;
for(int i=1;
i<QTD_OBJETOS;i++)
{
Cenario[i].Init();
Cenario[i].Translate(i*600,i*300,0);
Cenario[i].setTipo(2); // carro
}
Cenario[0].Init();
Cenario[0].setTipo(1); // Helicoptero
Função Desenha():
Realiza o desenho do cenário. O principal trecho é o que
desenha cada objeto armazenado no vetor "Cenario".
// Desenha o
cenario todo
for(int i=0;
i<3;i++)
{
Cenario[i].Draw();
}
Também se pode, nesta função imprimir as
posições de cada objeto do cenário com o trecho
apresentado a seguir. A variáriavel imprimeCoordenadas é
alterada pela tecla barra-de-espaco.
if (imprimeCoordenadas)
{
GLfloat P1[] = {0,0,0};
GLfloat P2[3];
imprimeCoordenadas = false;
printf("Posicoes do objetos:\n");
for(int i=0; i<QTD_OBJETOS; i++)
{
printf("Objeto %d: ",i);
Cenario[i].InstanciaPonto(P1,P2);
for (int j=0; j<3;j++)
printf("%7.2f ", P2[j]);
printf("\n");
}
EXERCÍCIO
O objetivo deste exercício é permitir que o
helicoptero possa pegar um carro e transportá-lo pelo
cenário até um ponto desejado, onde será
'largado'. O comando de 'pegar' só deve funcionar quando o
helicóptero for o objeto ativo.
Para resolver o exercício proposto,
utilize o material apresentado na aula
teórica.
O carro a ser pego deve ser o mais próximo do helicoptero.
ATENÇÃO: Note que comando de pegar deve estar na
função que trata as teclas void Teclado (unsigned char key, int
x, int y),
case 'p': // faz o helicoptero pegar um dos objetos do cenario
case
'P': if(ObjetoAtivo != 0)
{
tentaPegar = true;
}
Porém esta função deve apenas alterar uma
variável que será testada na rotina de desenho void Desenha(void), com algo
como :
if (tentaPegar)
{
// acha o carro mais
próximo do helicoptero
proximo = MaisProximo(Cenario[0]);
// adiciona o carro mais
próximo como filho do helicoptero
Cenario[0].AdicionaFilho(&Cenario[proximo]);
}
O mesmo processo deve ser implementado para largar o carro.
FIM.