Aula 06 — Transformações Geométricas 3D em OpenGL
Objetivos
Ao final desta aula você deve ser capaz de:
- Estender as três transformações geométricas — translação, escala e rotação — de 2D (Aula 04) para 3D, com matrizes homogêneas 4×4.
- Explicar por que a rotação em 3D exige um eixo, não só um ângulo, e aplicar
glRotatefem torno de qualquer um dos três eixos principais. - Diferenciar a navegação da câmera (Aula 05) da navegação do objeto (esta aula): quem se move, e por que os mesmos comandos produzem efeitos diferentes na tela.
- Selecionar corretamente
GL_MODELVIEWeGL_PROJECTION, reinicializar a matriz corrente comglLoadIdentitye isolar instâncias comglPushMatrix/glPopMatrix. - Compor várias instâncias de um mesmo modelo 3D por meio de translação e escala, sem acumular acidentalmente as transformações entre os objetos.
- Criar, chamar e liberar uma display list no contexto OpenGL ativo, reutilizando a geometria sob transformações diferentes.
- Montar um objeto composto por primitivas diferentes, preservando o referencial local de cada parte com a pilha de matrizes.
Conteúdo
Retomando: da câmera para o objeto
Na Aula 05, a câmera navegava e os objetos ficavam parados, com vértices
puros — nenhuma chamada glTranslatef, glRotatef ou glScalef foi usada
naquela aula. A justificativa, na época, era isolar uma variável: só a
câmera deveria mudar a imagem, para que o efeito de gluLookAt ficasse
claro sem se misturar com transformações de objeto.
Essa restrição acaba aqui. Você já conhece glTranslatef, glRotatef e
glScalef desde a Aula 04 — só que em 2D, onde a rotação girava sempre em
torno do mesmo eixo implícito () e a translação/escala tinham só duas
componentes. Esta aula estende as três para os três eixos, e devolve aos
objetos a capacidade de se mover: agora é o objeto que navega, não (só) a
câmera.
Transformações Geométricas 3D
O Sistema de Referência do Universo (SRU) em 3D já apareceu na Aula 05: três eixos ortogonais , , , seguindo a regra da mão direita adotada pelo OpenGL. As três transformações fundamentais continuam as mesmas — translação, escala e rotação — mas cada uma ganha uma terceira componente.
Como em 2D (Aula 04), o processamento usa coordenadas homogêneas para permitir a composição por multiplicação de matrizes. A diferença é só o tamanho: em 3D, um ponto vira , e as matrizes passam a ser 4×4 — três eixos mais a linha/coluna homogênea, em vez das 3×3 da Aula 04.
Translação e escala generalizam de forma direta, só acrescentando e :
A rotação é onde 2D e 3D realmente divergem. Em 2D só existe um eixo perpendicular ao plano — por isso bastava um ângulo, e o eixo nem precisava ser mencionado. Em 3D existem infinitos eixos possíveis passando pela origem: um ângulo sozinho não diz em torno de que reta o objeto gira. Por isso a rotação 3D precisa de dois dados — ângulo e eixo —, e a forma matricial muda conforme o eixo escolhido. Para os três eixos principais:
Repare que é exatamente a rotação 2D da Aula 04, só emoldurada em 4×4 — faz sentido, já que girar em torno de não deveria mexer em . As três seguem a regra da mão direita revisada na Aula 05: com o polegar apontando no sentido positivo do eixo de rotação, os dedos fecham no sentido positivo do ângulo. Confira com aplicada a — o eixo positivo: o resultado é , exatamente a regra " gira para " já usada na Aula 05 para justificar o sentido do yaw da câmera.
glRotatef(ângulo, x, y, z) aceita qualquer vetor como eixo, não só os
três principais — é a chamada rotação de Rodrigues, e a matriz resultante
generaliza as três acima. Esta aula usa só os três eixos principais, que já
bastam para tudo que vem a seguir; a fórmula geral fica para quem quiser se
aprofundar (ver Referências).
Exemplo 1 — as três transformações, agora em três eixos
📥 Baixe o arquivo completo:
tg3d_cubo.py
glPushMatrix()
glTranslatef(0.0, 1.0, 0.0) # mesma base do cubo de referência
if self.modo == "T":
glTranslatef(self.tx, self.ty, self.tz)
elif self.modo == "E":
glScalef(self.ex, self.ey, self.ez)
else:
eixo_vetor = {"X": (1, 0, 0), "Y": (0, 1, 0), "Z": (0, 0, 1)}[self.eixo]
glRotatef(self.angulo, *eixo_vetor)
_desenhar_cubo_aramado(0.6)
glPopMatrix()
O que observar. Pressione T, E ou R para trocar de modo; no modo
R, X/Y/Z trocam o eixo de rotação. Gire em torno de Y até 90° e
compare com a conta de acima: uma aresta que apontava para
deve passar a apontar para . O glPushMatrix()/glPopMatrix() em
volta de cada cubo é exatamente a mesma disciplina de
pilha_instancias2d.py (Aula 04): sem ele, a transformação de um cubo
vazaria para o próximo.
Navegação: do observador ao objeto
Câmera e objeto entram na mesma matriz GL_MODELVIEW, embora sejam
configurados por chamadas diferentes — gluLookAt para a câmera e
glTranslatef/glRotatef para o objeto. O efeito na tela é diferente
porque o papel de cada transformação também é diferente:
- Mover a câmera (Aula 05, via
gluLookAt) reposiciona o referencial a partir do qual tudo é visto. Os objetos continuam parados no SRU; quem muda é o ponto de vista. - Mover o objeto (esta aula, via
glTranslatef/glRotatefdentro doglPushMatrix/glPopMatrixdaquele objeto) altera a posição de um objeto dentro do SRU, sem tocar nos demais nem na câmera.
Exemplo 2 — navegação do objeto
📥 Baixe o arquivo completo:
piramide_navegavel.py
def paintGL(self) -> None:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
gluLookAt(*OLHO, *ALVO, *UP) # câmera fixa, primeira chamada
self._desenhar_chao()
glPushMatrix()
glTranslatef(*self.pos)
glRotatef(self.rot_y, 0.0, 1.0, 0.0) # guinada: em torno de Y
glRotatef(self.rot_x, 1.0, 0.0, 0.0) # arfagem: em torno de X
desenhar_piramide_aramada()
glPopMatrix()
O que observar. As setas giram a pirâmide (guinada em Y, arfagem em
X); W/A/S/D a transladam. A câmera não se move em nenhum momento —
gluLookAt é chamado uma única vez, com os mesmos parâmetros, sempre. Esta
é a diferença central em relação à Aula 05: lá, o observador se movia sobre
objetos parados; aqui, o observador está parado e é o objeto que
acumula glTranslatef/glRotatef a cada tecla.
piramide_navegavel.py usa essa segunda abordagem — a mesma do exemplo
Exemplo3DPiramide.cpp do Prof. Rieder, em que as variáveis de translação
e rotação do objeto são atualizadas a cada tecla e reaplicadas no desenho,
do mesmo jeito que self.pos/self.rot_x/self.rot_y fazem aqui.
Não confunda essas variáveis com a função PosicionaObservador do mesmo
exemplo: aquela monta a câmera (é o gluLookAt da Aula 05, e o
equivalente dela no arquivo-base da atividade desta aula chama-se
_posicionar_observador); estas movem o objeto. As duas escrevem na
mesma GL_MODELVIEW, em momentos diferentes do mesmo quadro.
Transformações Geométricas 3D em OpenGL
As funções já são conhecidas da Aula 04 — a novidade é só a terceira componente:
| Função (2D, Aula 04) | Função (3D, esta aula) |
|---|---|
glTranslatef(Tx, Ty, 0) | glTranslatef(Tx, Ty, Tz) |
glScalef(Ex, Ey, 1) | glScalef(Ex, Ey, Ez) |
glRotatef(ângulo, 0, 0, 1) | glRotatef(ângulo, x, y, z) — eixo explícito |
As variantes com sufixo f recebem valores de precisão simples; as
variantes glTranslated, glScaled e glRotated recebem valores de
precisão dupla. O papel geométrico é o mesmo.
Antes de alterar uma matriz, é preciso selecionar qual delas ficará corrente:
| Chamada | Matriz selecionada | Uso nesta unidade |
|---|---|---|
glMatrixMode(GL_MODELVIEW) | modelo-visão | câmera e transformações dos objetos |
glMatrixMode(GL_PROJECTION) | projeção | glOrtho ou gluPerspective |
glMatrixMode(GL_TEXTURE) | textura | transformação de coordenadas de textura; não usada nos exemplos |
glLoadIdentity() reinicializa a matriz que estiver selecionada.
Portanto, a sequência segura é selecionar a matriz, reinicializá-la e só
então aplicar as operações daquela etapa. Trocar o modo no lugar errado
pode fazer uma transformação de objeto deformar a projeção, ou fazer uma
projeção entrar por engano na matriz de modelo-visão.
glPushMatrix, glPopMatrix e glLoadIdentity continuam exatamente como
na Aula 04 — e voltam a ser indispensáveis aqui: a Aula 05 não precisou
deles porque nenhum objeto se transformava individualmente; agora que
objetos voltam a se mover, isolar a transformação de um deles do próximo
volta a importar.
Display lists: compilar uma vez, reutilizar muitas vezes
Quando uma geometria é desenhada repetidamente sem mudar seus vértices, uma display list permite registrar uma sequência de comandos OpenGL e executá-la depois por um identificador. O padrão combina diretamente com o instanciamento desta aula: a lista guarda a geometria local; cada instância aplica sua própria matriz e chama a mesma lista.
Fonte desta seção: OpenGL Programming Guide — Chapter 7: Display Lists, com os exemplos adaptados para Python, PyOpenGL e o ciclo de vida do
QOpenGLWidgetdo PySide6.
lista_piramide = int(glGenLists(1))
glNewList(lista_piramide, GL_COMPILE)
desenhar_piramide() # glBegin, glVertex..., glEnd
glEndList()
# Em paintGL, sob a matriz de cada instância:
glCallList(lista_piramide)
# Antes de destruir o contexto:
glDeleteLists(lista_piramide, 1)
O ciclo de vida tem quatro etapas:
| Operação | Papel |
|---|---|
glGenLists(1) | reserva um identificador; no PyOpenGL, o retorno é usado diretamente como um inteiro |
glNewList(id, modo) ... glEndList() | delimita os comandos que serão compilados |
glCallList(id) | executa a sequência armazenada no estado OpenGL corrente |
glDeleteLists(id, 1) | libera o identificador e os recursos associados |
Com GL_COMPILE, os comandos são somente armazenados: a geometria não é
desenhada durante a criação da lista. GL_COMPILE_AND_EXECUTE armazena e
também executa os comandos naquela ocasião. Para inicializar recursos sem
produzir um quadro intermediário, GL_COMPILE costuma deixar a intenção mais
clara.
Display lists são um recurso legado, disponível no contexto OpenGL 2.1 de compatibilidade usado nesta unidade, mas ausente do perfil core moderno. Em aplicações atuais, buffers de vértices e objetos de vértices (VBOs/VAOs) são a abordagem usual. Aqui a lista é útil para compreender reutilização, estado e instanciamento no pipeline fixo — não como recomendação para um projeto OpenGL moderno.
O que realmente fica armazenado
Os valores enviados aos comandos OpenGL são avaliados durante a
compilação. Se uma variável Python mudar depois de glEndList(), a lista não
muda com ela. Laços, cálculos trigonométricos e chamadas de funções Python
também rodam naquele momento; o que fica armazenado é a sequência de comandos
OpenGL produzida por eles.
escala = 0.5
glNewList(modelo, GL_COMPILE)
glScalef(escala, escala, escala) # a lista registra 0.5
desenhar_piramide()
glEndList()
escala = 2.0 # não altera a lista já compilada
Uma lista não oferece acesso de leitura nem edição aos comandos internos. Para alterá-la, compile novamente o mesmo identificador ou apague-a e crie outra. Também não é um formato de arquivo: ela pertence ao contexto OpenGL corrente, não pode ser salva como um modelo e deixa de existir quando o contexto é destruído. Listas muito pequenas ainda podem custar mais para chamar do que economizam; elas fazem mais sentido quando há trabalho suficiente e bastante reutilização.
O construtor Python (__init__) acontece antes de existir um contexto OpenGL
ativo. Por isso, crie a lista em initializeGL, use-a em paintGL e chame
glDeleteLists enquanto o contexto ainda estiver corrente. Mantenha fora da
lista os estados que precisam variar por instância — no exemplo, cor,
translação e escala — e compile somente a geometria comum.
Exemplo 3 — uma lista, cinco instâncias
📥 Baixe o arquivo completo:
display_lists.py
def initializeGL(self):
self.lista_piramide = int(glGenLists(1))
glNewList(self.lista_piramide, GL_COMPILE)
desenhar_piramide()
glEndList()
def paintGL(self):
for x, escala, cor in INSTANCIAS:
glPushMatrix()
glTranslatef(x, 0.0, 0.0)
glScalef(escala, escala, escala)
glColor3f(*cor)
glCallList(self.lista_piramide)
glPopMatrix()
Execute o exemplo e pressione L: a cena alterna entre a display list e a
função de desenho imediato equivalente. As setas giram o conjunto para deixar
evidente que todas as pirâmides reutilizam a mesma geometria local. Observe que
glColor3f, glTranslatef e glScalef ficam fora da lista; se fossem
compilados dentro dela, todas as chamadas repetiriam aqueles valores.
Atividades de Laboratório
Aquecimento
Antes da atividade, use os dois exemplos da aula para experimentar:
- Em
tg3d_cubo.py, no modoR, gire em torno deXaté 90° e depois em torno deZaté 90°, partindo sempre de zero. O resultado final é o mesmo cubo na mesma orientação? Relacione com a não comutatividade da composição de matrizes, já vista na Aula 04. - Ainda em
tg3d_cubo.py, tente prever de cabeça o resultado deglRotatef(90, 0, 1, 0)sobre um vértice em , usando a matriz desta aula — depois confira girando o cubo e observando uma aresta que comece alinhada ao eixo . - Em
piramide_navegavel.py, translade a pirâmide para longe da câmera (Wrepetidas vezes) e gire-a 180° emY(Left/Right). Ela ainda aponta para o mesmo lugar? O que isso diz sobre a ordem translação-depois-rotação (ou o contrário) no seu código? - Compare
piramide_navegavel.py(Aula 06) comcena_navegavel_solucao.py(Aula 05): as duas têm teclas de seta para girar. Qual delas gira a câmera e qual gira o objeto? Como você percebe a diferença só olhando para a cena, sem ler o código?
Atividade Prática Individual — Pirâmides de Gizé
Objetivo. Reproduzir, em wireframe, as três pirâmides da Necrópole de
Gizé a partir de um único modelo. Cada instância deve preservar sua própria
translação e escala com glPushMatrix()/glPopMatrix().
Esta é uma Atividade Prática Individual da disciplina, avaliada como Task Point. A entrega é o código-fonte, submetido na tarefa correspondente do Moodle. Os valores numéricos das tabelas abaixo fazem parte do enunciado: reproduza-os como estão.
Ponto de partida. O arquivo-base já configura a janela, a projeção em
perspectiva, a câmera sintética e a função desenhar_piramide_aramada().
Complete apenas a lista de instâncias e o laço que as desenha. Ao rodar sem
os TODOs resolvidos, a janela abre vazia — o título continua mostrando
o estado da câmera, então dá para confirmar que o programa está de pé.
📥 Baixe o arquivo completo:
piramides_gize_base.py
Roteiro
Passo 1 — Preserve o modelo.
Não altere os vértices de desenhar_piramide_aramada(). As três pirâmides
devem ser instâncias do mesmo modelo, diferenciadas somente pelas matrizes
aplicadas antes da chamada de desenho.
Passo 2 — Defina as instâncias. Use os valores do material da disciplina:
| Pirâmide | Posição | Translação | Escala uniforme |
|---|---|---|---|
| Miquerinos | esquerda, menor | ||
| Quéfren | centro | ||
| Quéops | direita, maior |
Passo 3 — Isole cada transformação.
Para cada item da lista, salve a matriz com glPushMatrix(), aplique
glTranslatef e glScalef, desenhe a pirâmide e restaure a matriz com
glPopMatrix().
Dois cuidados neste passo. O primeiro é a ordem entre as duas transformações: pela regra "T, R, S no código" da Aula 04, a chamada mais próxima do desenho é a que age primeiro sobre o vértice. Você quer que a pirâmide seja redimensionada em torno da própria origem e só depois seja levada até a posição da tabela; a ordem oposta faria a escala multiplicar também o deslocamento.
O segundo é o isolamento em si. Vale rodar uma vez sem o
glPushMatrix()/glPopMatrix() antes de acrescentá-los: como as
transformações em OpenGL são cumulativas, a segunda pirâmide herda a
transformação da primeira e a terceira herda as duas anteriores — o
resultado é o quadro (a) da Figura 1, com as três encolhidas e amontoadas
em um canto. Ver o estrago na tela ensina mais do que ler sobre ele.
Passo 4 — Confira a aparência e o observador. O arquivo-base já traz tudo isto em constantes, uma por especificação do enunciado — confira que nada foi alterado:
| Especificação | Valor |
|---|---|
| Espessura de linha | 5.0 |
| Cor de linha | (0.863, 0.796, 0.710) |
| Cor de fundo | (0.0, 0.0, 0.0, 0.0) |
| Posição do observador | obs = (1.75, 1.75, 8.5) |
| Ângulos iniciais | rot_x = 0, rot_y = 45 |
O giro inicial de 45° em torno de não é decorativo: as três translações da tabela descrevem uma diagonal no plano , como a das pirâmides reais no platô de Gizé. Sem esse giro, a fileira recuaria quase na direção da visada e as pirâmides apareceriam uma atrás da outra.
Passo 5 — Confira o resultado.
As três pirâmides devem aparecer separadas, com tamanhos progressivos: a
menor à esquerda, a intermediária ao centro e a maior à direita, como no
quadro (b) da Figura 1. Use as setas para inspecionar a composição de
outros ângulos, W/S para aproximar e afastar o observador, e 0 para
voltar ao estado inicial.
Repare que a diferença de tamanho na tela é a soma de dois efeitos independentes: a escala do enunciado (Miquerinos é de fato a menor das três) e a projeção em perspectiva da Aula 05 (o que está mais longe projeta menor). Girando a cena até ver a fileira de outro ângulo, dá para separar um efeito do outro.
Checklist de conclusão
- As três instâncias usam a mesma função de desenho.
- Miquerinos, Quéfren e Quéops usam exatamente as translações e escalas da tabela.
- Cada instância está isolada por
glPushMatrix()/glPopMatrix(). -
glTranslatefvem antes deglScalefno código, de modo que a escala aja primeiro sobre o vértice. - Fundo, cor e espessura das linhas correspondem às especificações.
- Redimensionar a janela não distorce as pirâmides.
Para responder
Registre as respostas em um comentário no topo do arquivo:
- O que aconteceria com Quéfren e Quéops se o
glPopMatrix()fosse removido do laço? Explique em termos de acumulação de matrizes, e calcule — a partir da tabela — em que posição e com que escala cada uma das duas iria parar. - Por que é melhor reutilizar uma única função de desenho e variar apenas translação e escala do que criar três listas independentes de vértices?
- Se
glScaleffosse escrito antes deglTranslatefno laço, qual das três pirâmides sairia do lugar, e por que as outras duas não denunciariam o erro? (Olhe os valores da tabela antes de responder.) - O arquivo-base usa
FOVY = 78, mais aberto do que os 45–60° dos outros exemplos do curso. Troque por45.0e rode de novo: o que acontece com Quéops? Explique com o que você viu na Aula 05 sobre ofovydegluPerspectivee a forma do volume de visualização.
Atividade — Pedra Lapidada: composição de partes
Objetivo. Construir o objeto composto da Figura 2 e fazê-lo navegar como uma única unidade, sem incorporar as posições finais diretamente nas listas de vértices.
Esta atividade adapta o exercício de Visualização 3D às ferramentas atuais da disciplina. A janela, a câmera fixa, o teclado e as duas geometrias locais já estão preparados no arquivo-base.
Baixe o ponto de partida: pedra_lapidada_base.py.
Ao executar o arquivo sem completar os TODOs, aparece somente o cubo central.
Roteiro
Passo 1 — Reconheça os referenciais locais. O cubo tem lado 2 e está centrado na origem. A pirâmide reutilizável tem a base no plano local e o ápice em ; portanto, antes de qualquer transformação, ela aponta para .
Passo 2 — Acople a ponta direita.
Em desenhar_pedra_lapidada(), salve a matriz com glPushMatrix(), translade
a pirâmide para , chame desenhar_arestas() com sua geometria e
restaure a matriz. A base local deve coincidir com a face do cubo.
Passo 3 — Inverta a orientação sem duplicar vértices.
Para a ponta esquerda, salve novamente a matriz, translade para e
gire a pirâmide 180° em torno de . Pela ordem das chamadas OpenGL, escreva
glTranslatef antes de glRotatef: a rotação deve agir primeiro no modelo
local e a translação deve levar o resultado até a face esquerda.
Passo 4 — Navegue com o conjunto.
Use as setas para girar a pedra e W/S/A/D para transladá-la. As três
partes devem permanecer encaixadas em todos os ângulos. Essas transformações
do conjunto ficam fora dos glPushMatrix()/glPopMatrix() internos de cada
ponta.
Checklist de conclusão
- O cubo central e as duas pirâmides formam um único contorno fechado.
- As duas pontas reutilizam
VERTICES_PIRAMIDEeARESTAS_PIRAMIDE. - Cada pirâmide tem seu próprio par
glPushMatrix()/glPopMatrix(). - A ponta esquerda usa rotação de 180° em torno de , sem uma segunda lista de vértices.
- Girar ou transladar o conjunto não separa as três partes.
- A tecla
0restaura a posição e a orientação iniciais.
Para responder
- Por que a translação da ponta direita é exatamente , e não ?
- O que aconteceria se a rotação de 180° fosse aplicada também à ponta direita?
- Por que os
glPushMatrix()/glPopMatrix()das pontas ficam dentro da transformação global do conjunto? - Como você construiria uma versão mais alongada alterando a escala do cubo sem abrir uma fresta nas bases das pirâmides?
Exercícios
Questões dissertativas
Em 2D (Aula 04), a rotação bastava um ângulo. Em 3D, glRotatef exige também um eixo. Explique essa diferença em termos do número de eixos de rotação possíveis em cada dimensão.
Na atividade das Pirâmides de Gizé, por que cada instância deve ficar entre glPushMatrix e glPopMatrix? O que aconteceria se as três translações e escalas fossem aplicadas em sequência, sem restaurar a matriz?
Câmera (Aula 05) e objeto (Aula 06) entram na mesma matriz GL_MODELVIEW, mas são configurados por chamadas e com papéis diferentes. Explique essa diferença.
Em piramide_navegavel.py, o método paintGL chama glTranslatef(*self.pos) e só depois glRotatef(self.rot_y, ...)/glRotatef(self.rot_x, ...), antes de desenhar. As teclas W/A/S/D deslocam a pirâmide sempre nos mesmos eixos do mundo (x e z), mesmo depois de girá-la com as setas — o deslocamento nunca acompanha a orientação da pirâmide. Explique por que, usando a regra 'T, R, S no código' desta aula e da Aula 04.
Questões objetivas
1. glRotatef(90, 0, 1, 0) é aplicado a um vértice em (0, 0, 1). Qual é o resultado?
- a)(1, 0, 0)
- b)(-1, 0, 0)
- c)(0, 1, 0)
- d)(0, 0, -1)
- e)(0, 0, 1) — sem mudança
2. Por que a rotação 2D (Aula 04) bastava com um ângulo, mas a rotação 3D precisa também de um eixo?
- a)Por uma limitação da OpenGL, sem relação com a geometria
- b)Porque em 2D só existe um eixo de rotação possível (implícito, perpendicular ao plano); em 3D há infinitos eixos passando pela origem
- c)Porque em 3D os ângulos são medidos em radianos, não em graus
- d)Porque glRotatef não aceita rotações em torno de z
- e)Não há diferença real: o eixo em glRotatef é só um parâmetro decorativo
3. Na Aula 05, quem se move é a câmera; nesta aula, quem se move é o objeto. As duas abordagens alteram a mesma matriz OpenGL. Qual?
- a)GL_PROJECTION
- b)GL_MODELVIEW
- c)GL_TEXTURE
- d)GL_VIEWPORT — não existe esse modo de matriz
- e)As duas usam matrizes diferentes, sem relação
4. No laço das Pirâmides de Gizé, glTranslatef aparece ANTES de glScalef, antes da chamada de desenho. Qual transformação afeta os vértices PRIMEIRO?
- a)glTranslatef, por vir primeiro no código
- b)glScalef, por estar mais perto da chamada de desenho
- c)As duas ao mesmo tempo, como uma única operação
- d)Nenhuma: a ordem das chamadas não influencia o resultado
- e)Depende da versão do OpenGL
5. Em piramide_navegavel.py, glTranslatef(*self.pos) vem ANTES de glRotatef(...) no código, antes de desenhar a pirâmide. Pela regra 'T, R, S no código', as teclas W/A/S/D movem a pirâmide em relação a que referencial?
- a)Ao referencial do mundo (eixos x/z fixos) — o deslocamento não acompanha a rotação da pirâmide
- b)Ao referencial local da pirâmide — o deslocamento sempre acompanha para onde ela está apontando
- c)Depende do ângulo atual de rotação, varia a cada quadro
- d)Não há diferença: os dois referenciais coincidem sempre em OpenGL
- e)Ao referencial da câmera, já que gluLookAt também usa GL_MODELVIEW
6. Uma display list é compilada quando escala vale 0.5. Depois de glEndList(), a variável Python passa a valer 2.0, sem recompilar a lista. Qual escala a chamada glCallList reproduz?
- a)0.5, pois o argumento enviado ao comando OpenGL foi capturado durante a compilação
- b)2.0, pois a lista conserva uma referência para a variável Python
- c)1.0, pois display lists ignoram transformações geométricas
- d)A média 1.25 entre o valor antigo e o novo
- e)Depende da matriz GL_PROJECTION
Referências
Principais (essenciais)
- AZEVEDO, E.; CONCI, A.; LETA, F. R. Computação Gráfica. Rio de Janeiro: Elsevier, 2003–2008. 2 v. (004.92 A994c)
- FOLEY, J. D. et al. Computer Graphics: Principles and Practice. 3. ed. Addison-Wesley, 2013. (004.92 C738)
- HEARN, D.; BAKER, M. P.; CARITHERS, W. R. Computer Graphics with OpenGL. 4. ed. Pearson Prentice Hall, 2011. (004.92 H436co)
- OpenGL Programming Guide. Chapter 7 — Display Lists.
- The Khronos Group. OpenGL 2.1 Reference Pages — glRotate. Disponível em: registry.khronos.org/OpenGL-Refpages/gl2.1
Aprofundamento (opcionais)
- COHEN, M.; MANSSOUR, I. H. OpenGL: uma abordagem prática e objetiva. São Paulo: Novatec, 2006. (004.92 C678o)
- HETEM JUNIOR, A. Computação gráfica. Rio de Janeiro: LTC, 2006. (004.92 H589c)
- BURDEA, G.; COIFFET, P. Virtual Reality Technology. 2. ed. Wiley-Interscience, 2003. (004.94 B949v)
- Wikipedia. Rotation matrix. Disponível em: en.wikipedia.org/wiki/Rotation_matrix
- Wikipedia. Rodrigues' rotation formula. Disponível em: en.wikipedia.org/wiki/Rodrigues%27_rotation_formula