Computação Gráfica 205/6 Parte Cena Simples Interativa com Câmara Fixa Breve Introdução ao Tema O jogo Micro Machines foi o primeiro de uma série de jogos baseados nos famosos carros de brinquedo com o mesmo nome. Este jogo foi lançado originalmente em 99 tendo, até à última versão em 2006, sido lançadas versões para um vasto conjunto de plataformas. O jogador controla um carro de brincar em ambientes pouco convencionais, tal como uma cozinha ou um jardim. O carro tem de percorrer uma pista, evitando os mais diversos obstáculos. Ao embater ou passar por cima de obstáculos o carro perde velocidade ou torna-se mais difícil de controlar. É possível assistir a cerca de sete minutos de gameplay no canal NESguide do Youtube. Nos últimos anos têm aparecido inúmeras versões deste jogo, incluindo algumas reimplementações com o grafismo original, ilustrado na figura anterior, juntamente com a capa do jogo. Algumas destas versões podem ser jogadas online 2. https://www.youtube.com/watch?v=bmpzznee74i 2 http://www.classicgamesarcade.com/game/268/micro-machines-drivingracing-game.html
Trabalho a realizar O objectivo dos trabalhos de laboratório de Computação Gráfica deste ano é recriar este clássico numa versão 3D, recorrendo a C++ e OpenGL. A ideia é manter a jogabilidade original alterando a perspectiva gráfica para que os vários elementos do jogo tenham um aspecto 3D. Podem ver um exemplo para inspiração na figura seguinte. O trabalho está dividido em quatro partes que serão avaliadas individualmente ao longo do semestre. Em cada uma destas avaliações existem objectivos e tarefas específicas para que possam explorar as várias componentes do programa de Computação Gráfica. O resto deste documento refere-se à primeira parte do trabalho. As outras três partes serão publicadas ao longo do semestre. 2
Objectivos Os objectivos da primeira parte dos trabalhos de laboratório são compreender e implementar a arquitectura de uma aplicação gráfica interativa e explorar os conceitos básicos de modelação. A avaliação da primeira parte do trabalho será realizada na semana de 2 a 6 de Outubro e corresponde a 6 valores da nota do laboratório. A realização deste trabalho tem um esforço estimado de 4 horas por elemento do grupo, distribuído por três semanas. Não esquecer de preencher e submeter a timesheet correspondente com as horas despendidas pelo grupo na realização deste trabalho. Tarefas As tarefas para a primeira parte são:. Modelar a mesa usando um cubo e modelar a estrada definindo as suas bermas usando pequenos torus (toros, em Português), simulando cheerios. Definir uma câmara fixa com uma vista de topo sobre a cena utilizando uma projecção ortogonal (semelhante à vista 2D do jogo original). Neste primeiro laboratório, toda a pista deve ficar visível. [,5 valores] 2. Modelar o carro, três laranjas e cinco pacotes de manteiga, recorrendo a objectos geométricos tridimensionais simples (cubos, esferas e torus). O carro deve ser composto por mais do que um objecto geométrico, num mínimo de cinco objectos. A representação destes objectos deve alternar entre modelo de arames e sólida usando a tecla A. [2,5 valores] 3. Controlar o movimento do carro com o teclado utilizando as teclas das setas para virar para esquerda e direita, assim com o para acelerar para a frente ou para trás. O carro não deve atingir a velocidade máxima imediatamente após pressionar a tecla ou parar quando se larga. O carro deve ter um movimento uniformemente variado, considerando a velocidade e a aceleração escalares, sendo a direcção do movimento dada por um vector tridimensional. [2,0 valores] 3
Informação Importante A implementação do trabalho desenvolvido nos laboratórios de computação gráfica deve usar o ciclo de animação (update/display cycle). Este padrão de desenho, usado nas aplicações de computação gráfica interactiva, está ilustrado na figura abaixo e separa o desenho da cena no ecrã da actualização do estado do jogo em duas fases distintas. Na fase de display são cumpridos três passos base: limpar o buffer; desenhar a cena e forçar o processamento dos comandos. Na fase de update todos os objectos do jogo são actualizados de acordo com a física inerente. Para este trabalho pode-se aplicar apenas a equação do movimento linear uniforme. É ainda nesta fase que se processa a detecção de colisões e implementação dos respectivos comportamentos. Para além de dos acontecimentos de update e display existem mais um conjunto de acontecimentos, tais como teclas pressionadas ou soltas, temporizadores e redimensionamento,. Estes devem ser tratados pelas respectivas funções de callback de forma independente. Por fim, sublinhamos que deve ser aplicada uma programação orientada a objectos, com a estrutura de classes apresentada nos diagramas UML em anexo. Siga sempre boas práticas de programação que permitam a reutilização do código em entregas posteriores e facilitem a escalabilidade futura. 4
Sugestões. Desenhar os objectos em papel antes de escrever o código OpenGL ajuda muito a perceber que primitivas e transformações devem ser aplicadas. No anexo B pode encontrar um exemplo de um esboço em papel para um objecto (não usar este esboço). 2. As rodas do carro podem ser criadas recorrendo a torus. 3. Para esta avaliação não existem colisões entre os objectos nem as laranjas se movem. Estes serão objectivos de uma futura entrega. 4. Algumas das funções a estudar: - glviewport, glmatrixmode, glortho - gltranslate, glrotate, glscale - glpushmatrix, glpopmatrix - glutsolidcube, glutsolidsphere, glutsolidtorus - glutkeyboardfunc - gluttimerfunc - glutget(glut_elapsed_time) 5
Anexo A Diagramas UML A. Gestor de Jogo e classes associadas Vector3 #_x : double #_y : double #_z : double +Vector3() +Vector3(in x : double, in y : double, in z : double) +~Vector3() +getx() : double +gety() : double +getz() : double +set(in x : double, in y : double, in z : double) +operator=(in vec : const Vector3 &) : Vector3 +operator(in num : double) : Vector3 +operator+(in vec : const Vector3 &) : Vector3 +operator-(in vec : const Vector3 &) : Vector3 -_position Entity +Entity() +~Entity() +getpostion() : Vector3 +setposition(in x : double, in y : double, in z : double) : Vector3 +setposition(in p : const Vector3 &) : Vector3 Camera #_near : double #_far : double +Camera(in near : double, in far : double) +~Camera() +computeprojectionmatrix() +computevisualizationmatrix() GameObject +GameObject() +~GameObject() +update(in delta_t : double) LightSource -_ambient [4] : double -_diffuse [4] : double -_specular [4] : double -_cut_off : double -_exponent : double -_num : GLenum -_state : bool +LightSource(in number : GLenum) +~LightSource() +getstate() : bool +setstate(in state : bool) : bool +getnum() : GLenum +setposition(in position : const Vector4 &) +setdirection(in direction : const Vector3 &) +setcutoff(in cut_off : double) +setexponent(in exponent : double) +setambient(in ambient : const Vector4 &) +setdiffuse(in diffuse : const Vector4 &) +setspecular(in specular : const Vector4 &) -_ -_cameras -_light_sources GameManager +GameManager() +~GameManager() +display() +reshape(in w : GLsizei, in h : GLsizei) +keypressed() +ontimer() +idle() +init() -_game_objects 6
A2. Objecto do Jogo e classes associadas Entity +Entity() +~Entity() +getpostion() : Vector3 +setposition(in x : double, in y : double, in z : double) : Vector3 +setposition(in p : const Vector3 &) : Vector3 -_position GameObject +GameObject() +~GameObject() +update(in delta_t : double) Vector3 #_x : double #_y : double #_z : double +Vector3() +Vector3(in x : double, in y : double, in z : double) +~Vector3() +getx() : double +gety() : double +getz() : double +set(in x : double, in y : double, in z : double) +operator=(in vec : const Vector3 &) : Vector3 +operator(in num : double) : Vector3 +operator+(in vec : const Vector3 &) : Vector3 +operator-(in vec : const Vector3 &) : Vector3 StaticObject DynamicObject -_speed +StaticObject() +~StaticObject() +DynamicObject() +~DynamicObject() +update(in delta_t : double) +setspeed(in speed : const Vector3 &) +setspeed(in x : double, in y : double, in z : double) +getspeed() : Vector3 River Roadside +River() +~River() +Roadside() +~Roadside() Car Obstacle +Car() +~Car() +Obstacle() +~Obstacle() Butter Orange +Butter() +~Butter() +Orange() +~Orange() 7
A3. Câmara Virtual e classes associadas Entity +Entity() +~Entity() +getpostion() : Vector3 +setposition(in x : double, in y : double, in z : double) : Vector3 +setposition(in p : const Vector3 &) : Vector3 -_position Vector3 #_x : double #_y : double #_z : double +Vector3() +Vector3(in x : double, in y : double, in z : double) +~Vector3() +getx() : double +gety() : double +getz() : double +set(in x : double, in y : double, in z : double) +operator=(in vec : const Vector3 &) : Vector3 +operator(in num : double) : Vector3 +operator+(in vec : const Vector3 &) : Vector3 +operator-(in vec : const Vector3 &) : Vector3 GameManager +GameManager() +~GameManager() +display() +reshape(in w : GLsizei, in h : GLsizei) +keypressed() +ontimer() +idle() +init() -_cameras Camera #_near : double #_far : double +Camera(in near : double, in far : double) +~Camera() +computeprojectionmatrix() +computevisualizationmatrix() -_up -_center -_at PerspectiveCamera -_fovy : double -_aspect : double +computeprojectionmatrix() +computevisualizationmatrix() +PerspectiveCamera(in fovy : double, in aspect : double, in znear : double, in zfar : double) +~PerspectiveCamera() OrthogonalCamera -_left : double -_right : double -_bottom : double -_top : double +computeprojectionmatrix() +computevisualizationmatrix() +OrthogonalCamera(in left : double, in right : double, in bottom : double, in top : double, in near : double, in far : double) +~OrthogonalCamera() 8
A4. Fonte de Luz Vector3 -_direction -_position #_x : double #_y : double #_z : double +Vector3() +Vector3(in x : double, in y : double, in z : double) +~Vector3() +getx() : double +gety() : double +getz() : double +set(in x : double, in y : double, in z : double) +operator=(in vec : const Vector3 &) : Vector3 +operator(in num : double) : Vector3 +operator+(in vec : const Vector3 &) : Vector3 +operator-(in vec : const Vector3 &) : Vector3 LightSource -_ambient [4] : double -_diffuse [4] : double -_specular [4] : double -_cut_off : double -_exponent : double -_num : GLenum -_state : bool +LightSource(in number : GLenum) +~LightSource() +getstate() : bool +setstate(in state : bool) : bool +getnum() : GLenum +setposition(in position : const Vector4 &) +setdirection(in direction : const Vector3 &) +setcutoff(in cut_off : double) +setexponent(in exponent : double) +setambient(in ambient : const Vector4 &) +setdiffuse(in diffuse : const Vector4 &) +setspecular(in specular : const Vector4 &) -_light_sources GameManager +GameManager() +~GameManager() +display() +reshape(in w : GLsizei, in h : GLsizei) +keypressed() +ontimer() +idle() +init() 9
Anexo B Esboço de Objecto Importante: Não usar este esboço exemplificativo como base dos modelos a desenvolver no trabalho de laboratório. Os objectos apresentados devem ser desenhados pelos alunos. 0