Aula 05 — Câmera Sintética e Projeções
Objetivos
Ao final desta aula você deve ser capaz de:
- Explicar por que visualizar uma cena 3D exige duas etapas que não existiam no pipeline 2D: definir uma câmera sintética e escolher uma projeção.
- Descrever os dois parâmetros que definem uma câmera sintética — posição e orientação (ponto-alvo e vetor up) — e o Sistema de Referência da Câmera (SRC) que nascem deles.
- Diferenciar projeção paralela ortográfica de projeção em perspectiva, pela forma das projetantes e pelo volume de visualização que cada uma produz.
- Relacionar os parâmetros de
gluLookAt,glOrthoegluPerspectivecom os conceitos de câmera e de volume de visualização. - Aplicar a regra da mão direita para prever o sentido de um ângulo de rotação em torno de um eixo — e verificar, em vez de supor, quando o vetor de partida não é um dos eixos do mundo.
- Implementar uma câmera navegável (posição e ângulo de visada controlados pelo teclado) e alternar, em tempo real, entre as duas projeções desta aula.
Conteúdo
Retomando: o que muda em relação à Aula 04
Até aqui, toda a cena era 2D: um conjunto de vértices no plano ,
posicionado pelas transformações geométricas da Aula 04 e mapeado da window
para a viewport. Bastava decidir que retângulo do mundo mostrar
(gluOrtho2D) e onde, na tela, mostrá-lo (glViewport).
Em 3D isso não é suficiente. Um objeto tem posição nos três eixos, mas a tela continua sendo uma superfície 2D — e existem infinitas maneiras de "achatar" uma cena 3D em uma imagem plana, dependendo de de onde e em que direção se olha, e de como as três dimensões viram duas. São exatamente essas duas decisões, novas nesta aula, que entram entre a modelagem da cena e o mapeamento já conhecido:
- Câmera sintética — de onde e para onde se olha.
- Projeção — como o volume 3D visível vira uma imagem plana.
Só depois dessas duas etapas o processo volta a ser o que já era: mapear o resultado para a viewport e rasterizar.
Visualização Tridimensional
O Sistema de Referência do Universo (SRU) em 3D é formado por três eixos ortogonais entre si — , e — em vez de dois. Toda coordenada no mundo passa a ser uma tripla .
A convenção de sinais entre os três eixos não é arbitrária: fixados dois deles, o terceiro só pode apontar para um de dois sentidos possíveis, e a escolha entre eles é a regra da mão direita. O OpenGL adota o SRU de mão direita: com o polegar no sentido positivo de um eixo, os dedos se fecham no sentido positivo de rotação em torno dele.
Isso já apareceu, sem nome, na Aula 04: um ângulo de rotação positivo é sempre o sentido anti-horário — quando visto de quem olha do eixo de rotação para a origem. Um ângulo negativo gira no sentido horário. A regra vale para qualquer eixo, não só para o eixo implícito das rotações 2D: é por isso que ela precisa de nome próprio a partir de agora, quando os três eixos entram em jogo ao mesmo tempo.
Visualizar uma cena 3D é mais complexo do que visualizar uma cena 2D justamente por isso: além da posição dos objetos, é preciso decidir de onde a cena é observada — e essa decisão, sozinha, já muda a imagem final sem que um único vértice da cena tenha sido tocado.
Câmera Sintética
Um mesmo conjunto de objetos, visto de lugares diferentes, produz imagens diferentes — a mesma ideia por trás de uma fotografia: a cena não muda, muda o lugar de onde e a direção para onde a máquina aponta.
Uma câmera sintética formaliza essa escolha com dois grupos de parâmetros:
- Posição do observador — um ponto no SRU: de onde se olha.
- Orientação do observador — para onde e com que inclinação vertical se olha, dada por um ponto-alvo (o que a câmera está olhando, normalmente o centro da cena) e um vetor up (que direção é "para cima" do ponto de vista da câmera).
A partir da posição e da orientação, é possível construir um novo sistema de referência, centrado no observador: o Sistema de Referência da Câmera (SRC). No pipeline clássico do OpenGL, esse referencial continua seguindo a regra da mão direita: o eixo aponta do alvo para o observador e, por isso, a câmera olha no sentido de . Alguns materiais descrevem a imagem vista pela câmera com uma convenção de mão esquerda; aqui adotaremos a convenção efetivamente usada pelas matrizes de visualização do OpenGL. É esse referencial que permite responder perguntas como "qual objeto está mais perto?" ou "um objeto está encobrindo outro?": a resposta depende de onde está o observador, não apenas da posição dos objetos no SRU.
Exemplo 1 — quatro pontos de vista, uma cena só
📥 Baixe o arquivo completo:
camera_sintetica.py
PONTOS_DE_VISTA = [
((0.0, 3.0, 9.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0)), # 1: frontal
((9.0, 2.0, 0.0), (0.0, 0.0, 0.0), (0.0, 1.0, 0.0)), # 2: lateral
((0.0, 9.0, 0.01), (0.0, 0.0, 0.0), (0.0, 0.0, -1.0)), # 3: vista de pássaro
((-3.0, 0.6, 3.0), (1.0, 0.5, -1.0), (0.0, 1.0, 0.0)), # 4: rente ao chão
]
def paintGL(self) -> None:
glLoadIdentity()
olho, alvo, up = PONTOS_DE_VISTA[self.indice_vista]
gluLookAt(*olho, *alvo, *up)
# ... desenha a cena, que não muda ...
O que observar. Pressione 1, 2, 3 e 4 e compare os quatro
quadros. Nenhum vértice da cena mudou entre um e outro — só os três
parâmetros de gluLookAt (olho, alvo, up). O ponto de vista 3
(olho quase sobre o alvo, olhando para baixo) exige um up diferente de
: com a câmera olhando quase reto para baixo, o vetor "para cima
do mundo" deixa de servir como "para cima da câmera", e é preciso escolher
outro — aqui, .
gluLookAt recebe nove números, não umTrês parâmetros bastariam para a posição. Mas orientação sozinha — "olhando
para ali" — ainda deixa a câmera livre para girar em torno do próprio eixo
de mira, como uma câmera de mão que pode ficar "de cabeça para baixo"
apontando para o mesmo lugar. O vetor up resolve essa liberdade que sobra:
ele não precisa ser exatamente perpendicular à mira (gluLookAt corrige
isso internamente), só precisar não ser paralelo a ela.
Projeções
Com a câmera definida, a cena já está posicionada em relação ao observador — mas ainda em três dimensões. Projetar é o processo que reduz essa cena 3D a uma imagem 2D: cada vértice do objeto é ligado ao centro de projeção (ou a uma direção comum, na paralela) por uma projetante, e o ponto em que essa projetante cruza um plano de projeção é a posição do vértice na imagem.
Nem toda a cena é projetada: só o que está dentro do volume de visualização (view frustum) — a região do espaço delimitada pela window, e por um plano frontal (near) e um plano traseiro (far), que descartam o que está longe demais ou perto demais da câmera. A forma desse volume — e portanto o que "perto" e "longe" significam para o objeto — é justamente o que distingue os dois tipos de projeção desta aula.
Projeção Paralela Ortográfica
As projetantes são paralelas entre si e cruzam o plano de projeção em um ângulo de 90°. O volume de visualização resultante é um paralelepípedo: um objeto tem o mesmo tamanho na imagem estando perto ou longe da câmera, porque a distância não entra em nenhuma conta.
No referencial da câmera, quando o plano de projeção está alinhado a , a conta assume uma forma especialmente simples: a profundidade não altera as coordenadas projetadas e . Por isso, dois objetos iguais conservam o mesmo tamanho aparente mesmo estando a profundidades diferentes. Faces inclinadas em relação ao plano de projeção ainda sofrem encurtamento aparente; para obter medidas diretamente comparáveis, o desenho técnico usa vistas ortográficas alinhadas às faces de interesse.
Projeção em Perspectiva
As projetantes convergem para um único ponto, o centro de projeção — a posição do observador. O volume de visualização é um tronco de pirâmide: objetos mais distantes projetam menores do que objetos próximos do mesmo tamanho, exatamente como no olho humano ou em uma câmera fotográfica real.
Exemplo 2 — ortográfica × perspectiva lado a lado
📥 Baixe o arquivo completo:
projecoes_comparacao.py
def _desenhar_metade(self, x0, largura, altura, ortografica: bool) -> None:
glViewport(x0, 0, largura, altura)
aspecto = largura / float(altura)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
if ortografica:
meia_h = ORTHO_META_ALTURA
glOrtho(-meia_h * aspecto, meia_h * aspecto, -meia_h, meia_h, 0.1, 100.0)
else:
gluPerspective(35.0, aspecto, 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(*OLHO, *ALVO, *UP)
self._desenhar_cena()
O que observar. Os dois blocos têm exatamente o mesmo tamanho real
(SEMI_LADO = 0.6) e estão ligeiramente separados na horizontal para que
um não encubra o outro; a diferença relevante é a distância à câmera. Na metade
ortográfica, os dois aparecem do mesmo tamanho na tela — a distância
não afeta a projeção. Na metade em perspectiva, o bloco distante
aparece visivelmente menor. É a mesma diferença da Figura 3, agora com uma
cena real desenhada dos dois jeitos ao mesmo tempo.
Câmera e Projeção em OpenGL
Há uma função para cada um dos três conceitos desta aula. Repare no
prefixo: glOrtho é do núcleo do OpenGL, enquanto gluPerspective e
gluLookAt vêm da GLU, a biblioteca utilitária apresentada na Aula 01
— as duas são conveniências construídas sobre chamadas mais primitivas.
| Função | Etapa | Parâmetros |
|---|---|---|
gluLookAt(obsx, obsy, obsz, alvox, alvoy, alvoz, upx, upy, upz) | Câmera sintética | Posição do observador; ponto-alvo; vetor up |
glOrtho(left, right, bottom, top, near, far) | Projeção paralela ortográfica | Limites da window nos três eixos |
gluPerspective(fovy, aspect, near, far) | Projeção em perspectiva | Ângulo de visão vertical; proporção da viewport; planos de corte |
Repare que glOrtho recebe seis limites (como uma extensão 3D do
gluOrtho2D já conhecido), enquanto gluPerspective recebe um ângulo
de abertura (fovy, em graus) e a proporção da viewport — é essa
combinação que determina a forma do tronco de pirâmide, sem que seja
preciso calcular os quatro cantos à mão.
Em gluPerspective, near e far são distâncias positivas medidas a
partir do observador, com 0 < near < far. Eles não são coordenadas
assinadas. Já em glOrtho, os dois valores entram como limites do volume
ortográfico; em ambos os casos, tudo que fica fora do intervalo de
profundidade é recortado.
glMatrixMode: em qual matriz cada chamada escreve
Nenhuma dessas três funções recebe como parâmetro qual matriz deve
alterar: todas escrevem na matriz corrente. Quem escolhe a matriz
corrente é glMatrixMode(modo), e há três modos:
| Modo | Matriz selecionada | Quem escreve nela |
|---|---|---|
GL_MODELVIEW | Modelo-visão: posiciona a cena em relação ao observador | gluLookAt; glTranslatef, glRotatef, glScalef (Aula 04, retomadas em 3D na Aula 06) |
GL_PROJECTION | Projeção: a forma do volume de visualização | glOrtho, gluPerspective e o gluOrtho2D da Aula 03 |
GL_TEXTURE | Textura: transforma as coordenadas de textura, não a geometria | fora do escopo desta aula — volta na Aula 07 |
glLoadIdentity() também age sobre a matriz corrente: ele a reinicia como
matriz identidade, isto é, "nenhuma transformação aplicada". É por isso que
quase todo resizeGL desta disciplina tem sempre a mesma forma — seleciona
GL_PROJECTION, chama glLoadIdentity(), monta a projeção e volta para
GL_MODELVIEW. Essa última linha parece supérflua e não é: sem ela, as
transformações do paintGL acabam sendo escritas na matriz de projeção, e a
cena some ou aparece deformada sem nenhuma mensagem de erro.
Traduzindo a tabela para as três funções desta aula:
glOrthoegluPerspectiveescrevem na matriz de projeção, exatamente comogluOrtho2Dna Aula 03: elas descrevem a forma do volume de visualização, sem dizer nada sobre onde a câmera está.gluLookAtescreve na matriz de modelo-visão — a mesma que já carregava, na Aula 04, as transformações geométricas dos objetos (glTranslatef,glRotatef,glScalef), e que voltará a carregá-las em 3D na Aula 06. Ela entra como se fosse a transformação inversa do observador: em vez de levar a câmera até a cena, traz a cena inteira até a câmera, que fica parada na origem do SRC. Por issogluLookAté sempre a primeira chamada depois deglLoadIdentity()nopaintGL— tudo que for desenhado depois herda essa base.
As duas matrizes são independentes uma da outra. Antes de desenhar, ambas
precisam estar corretamente configuradas, e gluLookAt deve entrar na
modelo-visão recém-reinicializada antes das transformações dos objetos.
Nos programas em C com IUP do material do Prof. Rieder, em que a projeção e
o desenho acontecem na mesma função, isso vira uma regra literal de ordem no
texto do programa: gluPerspective sempre antes de gluLookAt, e em
GL_PROJECTION. Nos exemplos desta disciplina a separação é mais visível — a
projeção fica no resizeGL (ou no topo do paintGL, quando depende de um
estado que o usuário controla, como o fovy do Exemplo 3) e gluLookAt abre
o paintGL —, mas a exigência é exatamente a mesma.
glPushMatrix / glPopMatrix não aparecem nesta aulaVocê já os conhece da Aula 04: eles isolam transformações para que uma não vaze para o próximo objeto. Nesta aula, porém, nenhum objeto é transladado, rotacionado ou escalado individualmente — só a câmera muda —, e por isso não há nada a isolar. Eles voltam a ser indispensáveis na Aula 06, quando as transformações geométricas passam a valer para os três eixos.
Exemplo 3 — zoom e pan em 3D
📥 Baixe o arquivo completo:
zoom_pan_3d.py
def keyPressEvent(self, event) -> None:
tecla = event.key()
if tecla in (Qt.Key.Key_Plus, Qt.Key.Key_Equal):
self.fovy = max(FOVY_MIN, self.fovy / FATOR_ZOOM)
elif tecla == Qt.Key.Key_Minus:
self.fovy = min(FOVY_MAX, self.fovy * FATOR_ZOOM)
elif tecla in (Qt.Key.Key_Left, Qt.Key.Key_Right):
lateral = self._vetor_lateral()
sinal = -1.0 if tecla == Qt.Key.Key_Left else 1.0
for i in range(3):
desloc = sinal * PASSO_PAN * lateral[i]
self.olho[i] += desloc
self.alvo[i] += desloc
O que observar. Compare com zoom_pan.py da Aula 03: lá o zoom
mudava os limites de gluOrtho2D; aqui ele estreita ou alarga o fovy de
gluPerspective — uma lente mais "fechada" ou mais "aberta", sem mover a
câmera do lugar. O pan também muda de mecanismo: em vez de deslocar o
centro da window (que em 3D nem existe como conceito isolado), ele
desloca olho e alvo juntos, na direção lateral da câmera — calculada
pelo produto vetorial entre a mira e o up, a mesma conta que
gluLookAt faz por baixo dos panos para montar o SRC.
Repare também que, como em zoom_pan.py, a projeção é recalculada a
cada quadro dentro de paintGL, e não só no resizeGL: ela depende de
um estado que o usuário controla (self.fovy), não só do tamanho da
janela.
O processo de visualização 3D
As duas últimas etapas — mapeamento e rasterização — são exatamente as da
Aula 03, agora aplicadas ao resultado já achatado em 2D pela projeção. É
por isso que uma cena 3D, no fim, passa pelo mesmo glViewport que uma
cena 2D: a diferença toda aconteceu antes, nas etapas de câmera e
projeção.
Atividades de Laboratório
Aquecimento
Antes da atividade, use os três exemplos da aula para experimentar:
- Em
camera_sintetica.py, alterne entre os pontos de vista1a4e, para cada um, escreva de memória (antes de olhar o código) os valores de olho que você espera — depois confira no título da janela. - Ainda em
camera_sintetica.py, no ponto de vista3(vista de pássaro), tente trocar o up de volta para e rode de novo. O que acontece? Por que o alvo deixa de ajudar a definir a orientação quando a mira fica quase paralela ao up? - Em
projecoes_comparacao.py, mudeDISTANCIA_BLOCO_LONGEpara um valor mais próximo deDISTANCIA_BLOCO_PERTOe rode de novo. O que acontece com a diferença de tamanho na metade em perspectiva? E na ortográfica? - Em
zoom_pan_3d.py, pressione-repetidamente atéfovychegar perto deFOVY_MAX. O que acontece com a cena? Relacione com a Figura 3: o que muda na forma do tronco de pirâmide quando o ângulo de abertura cresce? - Ainda em
zoom_pan_3d.py, pressione+repetidamente atéfovychegar perto deFOVY_MIN. Esse efeito de campo de visão muito estreito tem nome em fotografia — pesquise "efeito teleobjetiva" e relacione com o que você está vendo.
Atividade — Cena Navegável 3D
Objetivo. Implementar uma câmera navegável — posição e ângulo de visada controlados pelo teclado — sobre uma cena 3D fixa, e alternar em tempo real entre projeção ortográfica e projeção em perspectiva.
Ponto de partida. O programa já abre a janela, configura o contexto e desenha um chão em grade; os blocos da cena e a lógica da câmera estão por sua conta.
📥 Baixe o arquivo completo:
cena_navegavel_base.py
Você já sabe posicionar objetos com glTranslatef desde a Aula 04, e aqui a
restrição é deliberada: os blocos desta cena são desenhados com vértices
puros, para que a única coisa capaz de mudar a imagem seja a câmera.
gluLookAt não move os vértices de cada objeto separadamente. Ele monta a
transformação de visualização, equivalente a aplicar à cena o movimento
inverso da câmera. A distinção entre câmera e objeto — e por que ambas entram
na mesma matriz GL_MODELVIEW — é o assunto da nota "Por que glPushMatrix /
glPopMatrix não aparecem nesta aula", mais acima.
Roteiro
Passo 1 — Modele a cena.
Em BLOCOS, acrescente pelo menos quatro blocos — (cx, cy, cz, semi-lado, cor) — em posições e profundidades diferentes, seguindo o layout relativo
da Figura 5. Lembre-se de que, na convenção desta aula, a câmera parte
olhando para : coloque os blocos em valores de negativos em
relação à posição inicial do observador (self.eye), ou eles nascerão
atrás de você.
Passo 2 — Calcule a direção da frente.
Complete _direcao_frente. Em self.yaw = 0 ela deve devolver — já é o que o método faz. O que falta é generalizar para qualquer
self.yaw: é uma rotação em torno do eixo , partindo desse vetor.
Antes de escrever a fórmula, responda no papel: girando o SRU de mão direita em torno de no sentido positivo (Figura 1, dedos de para ), para que lado o vetor se move — para ou para ? Guarde a resposta: o Passo 4 pede para compará-la com o sentido que você escolher para as teclas de rotação, e as duas coisas não são obrigadas a coincidir.
Passo 3 — Calcule a direção lateral.
Complete _direcao_lateral, a partir de self._direcao_frente() e do
vetor UP fixo — é o mesmo produto vetorial que
zoom_pan_3d.py usa para o pan, só que agora recalculado a cada quadro
porque a frente muda com self.yaw.
Confira no interpretador, sem depender da tela: em self.yaw = 0,
_direcao_lateral() deve devolver algo paralelo a .
Passo 4 — Monte o alvo e chame gluLookAt.
Em paintGL, calcule o ponto-alvo como self.eye deslocado por
_direcao_frente() e passe self.eye, o alvo e UP para gluLookAt.
Sem este passo, a chamada provisória continua olhando para a origem e a
orientação não acompanha corretamente a posição e o yaw do observador.
Passo 5 — Alterne a projeção.
Em _configurar_projecao, complete o if: quando self.ortografica for
True, chame glOrtho com meia-altura ORTHO_META_ALTURA (a meia-largura
é a meia-altura vezes o aspect ratio da janela) e planos near/far
0.1 e 100.0; senão, mantenha gluPerspective(FOVY, aspecto, 0.1, 100.0).
Passo 6 — Implemente a navegação.
Em keyPressEvent, complete o bloco de W/S/A/D: W e S andam
para frente e para trás (usando _direcao_frente()); A e D fazem
strafe lateral (usando _direcao_lateral()), sem girar self.yaw.
PASSO_MOVIMENTO é o tamanho do passo. As teclas de rotação (Left e
Right) e a de alternar projeção (O) já estão prontas — foi decidido por
você, no Passo 2, se elas giram para o lado esperado.
Se o sentido da rotação estiver invertido em relação à sua expectativa, não troque
Qt.Key.Key_LeftporQt.Key.Key_Rightsó para "consertar na tecla" — volte ao Passo 2 e descubra qual sinal da fórmula está causando isso: um defeito de sinal se corrige na origem, não no sintoma.
Passo 7 — Confronte com a referência.
Compare o layout da sua cena, de cima, com a Figura 5. Navegue até
conseguir ver todos os blocos a partir da posição inicial, girando só com
Left/Right. Alterne O em pelo menos duas posições diferentes e
confirme que a projeção ortográfica "achata" a diferença de tamanho entre
blocos próximos e distantes, como no Exemplo 2.
Checklist de conclusão
- Pelo menos quatro blocos aparecem, em profundidades diferentes.
-
W/Sandam para frente/trás;A/Dfazem strafe sem girar. -
Left/Rightgiram o ângulo de visada sem transladar o observador. -
Oalterna entre as duas projeções, visivelmente. - Nenhuma chamada
glTranslatef,glRotatefouglScaleffoi usada. - Redimensionar a janela não distorce a cena em nenhuma das duas projeções.
Para responder
Registre as respostas em um comentário no topo do arquivo:
- No Passo 2, qual sinal você escolheu para a fórmula de
_direcao_frente, e ele coincidiu com a previsão que você fez pela regra da mão direita antes de escrever o código? Se não coincidiu, explique por que não — a resposta tem a ver com o vetor de partida ser , não . - Suponha que
UPfosse em vez de , sem mudar mais nada. O que aconteceria com a navegação? (Não precisa testar — raciocine a partir do que_direcao_lateralcalcula.) - Se você quisesse impedir o observador de atravessar os blocos — uma forma simples de detecção de colisão —, em que método do arquivo essa verificação entraria, e o que ela precisaria comparar?
Exercícios
Questões dissertativas
Por que a visualização de uma cena 3D precisa de duas etapas — câmera sintética e projeção — que não existiam no pipeline 2D da Aula 03?
gluLookAt recebe posição, alvo E vetor up — três grupos de parâmetros, não dois. Por que a posição e o alvo sozinhos não bastam para definir a orientação da câmera?
Um engenheiro projetando uma peça mecânica e um jogo em primeira pessoa precisam, cada um, de um tipo de projeção diferente. Diga qual é cada um e justifique pela forma do volume de visualização.
gluLookAt altera a matriz GL_MODELVIEW; glOrtho e gluPerspective alteram a matriz GL_PROJECTION. Explique a diferença de papel entre as duas matrizes, e por que gluLookAt não poderia estar do lado da projeção.
Na Atividade, girar o SRU em torno de +y no sentido positivo (regra da mão direita) leva +z para +x. Mas para o vetor de frente da câmera — que parte de -z, não de +z — 'yaw crescente' precisou ser definido com o sinal invertido para girar o observador para a direita. Explique por que essas duas rotações, aparentemente a mesma regra, produzem sentidos opostos.
No Exemplo 1 (janela_viewport.py, Aula 03), um viewport com proporção diferente da window fazia a cena esticar. Em gluPerspective, o parâmetro aspect cumpre o papel equivalente. O que acontece se ele for passado com um valor errado — por exemplo, sempre 1.0, independente do tamanho real da janela?
Questões objetivas
1. Uma câmera é definida por gluLookAt(5, 0, 0, 0, 0, 0, 0, 1, 0). Qual vetor representa o eixo zc do SRC (do alvo para o observador)?
- a)(1, 0, 0)
- b)(-1, 0, 0)
- c)(0, 1, 0)
- d)(0, 0, 1)
- e)(0, 0, -1)
2. Dois blocos do mesmo tamanho real estão a distâncias diferentes da câmera. Sob projeção paralela ortográfica, como eles aparecem na imagem?
- a)Do mesmo tamanho, como no Exemplo 2 desta aula
- b)O mais distante aparece maior
- c)O mais distante aparece menor, como na perspectiva
- d)Nenhum dos dois aparece, por estarem fora do volume
- e)O tamanho depende só do fovy
3. O fovy de uma câmera em gluPerspective é reduzido de 90° para 20°, mantendo aspect, near e far. O que acontece com a cena?
- a)Nada muda: fovy só afeta a cor do fundo
- b)O campo de visão se estreita; objetos parecem mais próximos e maiores (efeito teleobjetiva)
- c)O campo de visão se alarga; mais cena passa a caber na tela
- d)A projeção deixa de ser em perspectiva
- e)A cena passa a ser cortada pelo plano near
4. Girando o SRU de mão direita em torno do eixo +x no sentido positivo, para onde o eixo +y se move?
- a)Em direção a +z
- b)Em direção a -z
- c)Em direção a +x (não se move)
- d)Em direção a -y
- e)A regra da mão direita não se aplica ao eixo x
5. Por que glOrtho (3D) exige os parâmetros near e far, que gluOrtho2D (Aula 03) não tinha?
- a)Porque em 3D a window sozinha não delimita o volume ao longo da profundidade — near/far fecham essa dimensão que o 2D não tinha
- b)Por compatibilidade com versões antigas do OpenGL, sem efeito real
- c)Porque near/far substituem left/right/bottom/top
- d)Porque glOrtho não aceita coordenadas negativas sem eles
- e)Near e far só existem em gluPerspective; glOrtho não os usa de fato
6. Qual é o formato do volume de visualização de uma projeção em perspectiva?
- a)Paralelepípedo
- b)Cone
- c)Tronco de pirâmide
- d)Cilindro
- e)Esfera
7. Um resizeGL faz glMatrixMode(GL_PROJECTION), glLoadIdentity(), gluPerspective(...) — e esquece de voltar para glMatrixMode(GL_MODELVIEW) no fim. O que acontece?
- a)Nada: o modo de matriz volta sozinho ao padrão a cada quadro
- b)O programa lança um erro de OpenGL na próxima chamada de desenho
- c)As chamadas seguintes (gluLookAt, glTranslatef...) passam a escrever na matriz de PROJEÇÃO, e a cena aparece deformada ou some — sem nenhum erro
- d)Só a próxima chamada é afetada; da seguinte em diante tudo volta ao normal
- e)gluPerspective é ignorado, e a projeção continua a padrão
8. Em um programa, gluLookAt é chamado DEPOIS de glTranslatef(2, 0, 0) no mesmo paintGL, sem glLoadIdentity() entre os dois. O que acontece?
- a)gluLookAt sobrescreve o efeito de glTranslatef, porque só um deles vale por vez
- b)As duas transformações se combinam na mesma matriz GL_MODELVIEW, na ordem em que foram chamadas — o resultado não é simplesmente 'a câmera em gluLookAt'
- c)O programa lança um erro, porque gluLookAt exige ser a primeira chamada após glLoadIdentity()
- d)glTranslatef é ignorado, porque só afeta GL_PROJECTION
- e)A ordem não importa: multiplicação de matrizes é comutativa
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)
- The Khronos Group. OpenGL 2.1 Reference Pages — gluLookAt. Disponível em: registry.khronos.org/OpenGL-Refpages/gl2.1
- The Khronos Group. OpenGL 2.1 Reference Pages — gluPerspective. 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)
- The Khronos Group. OpenGL 2.1 Reference Pages — glOrtho. Disponível em: registry.khronos.org/OpenGL-Refpages/gl2.1
- Wikipedia. Viewing frustum. Disponível em: en.wikipedia.org/wiki/Viewing_frustum
- Wikipedia. Right-hand rule. Disponível em: en.wikipedia.org/wiki/Right-hand_rule