6.3 Espaço euclidiano

O espaço euclidiano é um espaço afim que inclui a operação de produto escalar, também chamada de produto interno.

O produto escalar produz um escalar a partir de dois vetores. Com isso é possível definir conceitos como distância e ângulo.

O espaço euclidiano inclui o espaço vetorial de números reais \(\mathbb{R}^n\). Seus elementos são \(n\)-tuplas de números reais \((a_1, a_2, \dots, a_n)\) que denotam coordenadas do sistema de coordenadas cartesiano. A figura 6.9 ilustra a representação de um ponto em coordenadas cartesianas no espaço euclidiano de três dimensões (espaço 3D).

Representação de um ponto no espaço 3D.

Figura 6.9: Representação de um ponto no espaço 3D.

As operações do espaço vetorial são definidas como:

\[ \begin{align} \mathbf{u}+\mathbf{v}&=(u_1 + v_1, u_2 + v_2, \dots, u_n + v_n),\\ a \mathbf{v}&=(av_1, av_2, \dots, av_n). \end{align} \]

As operações afins são definidas como:

\[ \begin{align} P-Q &= (p_1 - q_1, p_2 - q_2, \dots, p_n - q_n),\\ P+\mathbf{u} &= (p_1 + u_1, p_2 + u_2, \dots, p_n + u_n). \end{align} \]

Frames

Assim como no mundo físico não existe um ponto de referência absoluto (uma “origem” no universo), no espaço euclidiano qualquer ponto pode ser considerado como a origem. Desse modo, para definir unicamente vetores e pontos, precisamos de uma base e um ponto de referência. Um frame cumpre esse papel27.

Um frame de um espaço euclidiano de \(n\) dimensões é composto por:

  • Um ponto de referência \(P_0\);
  • Uma base composta por \(n\) vetores linearmente independentes \(\mathbf{v}_1, \dots, \mathbf{v}_n\).

Dado um frame \(\{P_0, \mathbf{v}_1, \dots, \mathbf{v}_n\}\), um vetor

\[\mathbf{u}=(u_1, \dots, u_n)\]

pode ser escrito unicamente como

\[\mathbf{u}=u_1 \mathbf{v}_1 + u_2 \mathbf{v}_2 + \cdots + u_n \mathbf{v}_n.\]

Um ponto

\[P=(p_1, \dots, p_n)\]

pode ser escrito unicamente como

\[P=P_0 + p_1\mathbf{v}_1 + p_2\mathbf{v}_2 + \cdots + p_n\mathbf{v}_n.\]

O ponto de referência \(P_0\) representa a origem do frame. No frame cartesiano padrão,

\[P_0=(0, \dots, 0),\]

e a base é formada pelo conjunto de tuplas

\[ \begin{align} \mathbf{e}_1 &= (1, 0, 0, \dots, 0),\\ \mathbf{e}_2 &= (0, 1, 0, \dots, 0),\\ &\;\;\vdots\\ \mathbf{e}_n &= (0, 0, 0, \dots, 1),\\ \end{align} \] No \(\mathbb{R}^3\), a base é frequentemente denotada por vetores \(\hat{\mathbf{i}}\), \(\hat{\mathbf{j}}\), \(\hat{\mathbf{k}}\):

\[ \begin{align} \hat{\mathbf{i}} &= (1, 0, 0),\\ \hat{\mathbf{j}} &= (0, 1, 0),\\ \hat{\mathbf{k}} &= (0, 0, 1). \end{align} \]

O conceito de frame é importante em computação gráfica pois é comum que os modelos geométricos 3D sejam representados originalmente em um frame local no qual a origem é o centro ou a base do objeto. Esses modelos podem ser dispostos em uma cena virtual 3D que usa outro frame de referência. Além disso, durante o processamento geométrico do pipeline de renderização, os objetos da cena podem ser expressos em relação ao frame da câmera virtual, cuja origem é frequentemente o centro de projeção. Veremos futuramente como realizar essas mudanças de representação através de matrizes de transformação.

Produto escalar

Sejam \(\mathbf{u}=(u_1, \dots, u_n)\) e \(\mathbf{v}=(v_1, \dots, v_n)\) dois vetores do \(\mathbb{R}^n\). O produto escalar, denotado por \(\mathbf{u} \cdot \mathbf{v}\), é a soma da multiplicação componente a componente das tuplas. O resultado é, portanto, um escalar:

\[\mathbf{u} \cdot \mathbf{v} = \sum_{i=1}^n u_i v_i = u_1 v_1 + u_2 v_2 + \cdots + u_n v_n.\]

As seguintes propriedades se aplicam:

  • \(\mathbf{u} \cdot \mathbf{v}= \mathbf{v} \cdot \mathbf{u}\).
  • \((a \mathbf{u} + b \mathbf{v}) \cdot \mathbf{w} = a \mathbf{u} \cdot \mathbf{w} + b \mathbf{v} \cdot \mathbf{w}\).
  • \(\mathbf{v} \cdot \mathbf{v} \geq 0\), e \(\mathbf{v} \cdot \mathbf{v} = 0\) se e somente se \(\mathbf{v}=\mathbf{0}\).
  • \(\mathbf{0} \cdot \mathbf{0} = 0\).

Ortogonalidade

Se \(\mathbf{u} \cdot \mathbf{v} = 0\), então \(\mathbf{u}\) e \(\mathbf{v}\) são ortogonais, isto é, os vetores são perpendiculares entre si.

Quando todos os vetores de uma base são ortogonais, temos uma base ortogonal.

A base padrão \(\mathbf{e}_1, \dots, \mathbf{e}_n\) de \(\mathbb{R}^n\) é um exemplo de base ortogonal, pois \(\mathbf{e}_i \cdot \mathbf{e}_j = 0\) para \(i \neq j\).

Comprimento e distância

No espaço euclidiano, a magnitude ou comprimento de um vetor \(\mathbf{u}=(u_1, u_2, \dots, u_n)\) é definida pela norma euclidiana:

\[ \begin{align} |\mathbf{u}| &= \sqrt{\mathbf{u} \cdot \mathbf{u}}\\ & = \sqrt{u_1^2 + u_2^2 + \cdots + u_n^2}. \end{align} \]

A norma euclidiana permite calcular a distância entre pontos. Como \(P - Q\) é um vetor de deslocamento de \(Q=(q_1, \dots, q_n)\) para \(P=(p_1, \dots, p_n)\), a distância entre os dois pontos pode ser calculada como

\[ \begin{align} |P - Q| &= \sqrt{(P-Q) \cdot (P-Q)}\\ &= \sqrt{\sum_{i=1}^n (q_i - p_i)^2}. \end{align} \]

A figura 6.10 ilustra a distância euclidiana entre dois pontos \(P=(p_x, p_y)\) e \(Q=(q_x, q_y)\). Observe sua relação com o teorema de Pitágoras.

Distância entre dois pontos no plano.

Figura 6.10: Distância entre dois pontos no plano.

Normalização

Se \(|\mathbf{v}|=1\), dizemos que \(\mathbf{v}\) é um vetor unitário. Podemos transformar qualquer vetor \(\mathbf{v}\) não nulo em um vetor unitário na mesma direção, denotado por \(\hat{\mathbf{v}}\), se dividirmos todos os elementos de \(\mathbf{v}\) por seu comprimento: \[\hat{\mathbf{v}}=\frac{\mathbf{v}}{|\mathbf{v}|}.\] A figura 6.11 ilustra o resultado da normalização de vetores no \(\mathbb{R}^2\). Observe que os vetores normalizados desenhados a partir da origem ficam inscritos em um círculo unitário.

Um conjunto de vetores (esquerda) e seus correspondentes vetores normalizados (direita).

Figura 6.11: Um conjunto de vetores (esquerda) e seus correspondentes vetores normalizados (direita).

Sempre que possível trabalharemos com vetores unitários. O uso de vetores unitários simplifica o cálculo do sombreamento e iluminação de superfícies.

Quando dois vetores unitários são ortogonais, dizemos que os vetores são ortonormais. A base padrão \(\mathbf{e}_1, \dots, \mathbf{e}_n\) do \(\mathbb{R}^n\) é uma base ortonormal pois possui vetores de base unitários (isto é, \(|\mathbf{e}_i|=1\)) e ortogonais entre si.

Ângulo entre vetores

O produto escalar entre dois vetores \(\mathbf{u}\) e \(\mathbf{v}\) não nulos é proporcional ao cosseno do ângulo \(\theta\) formado entre esses vetores:

\[\mathbf{u} \cdot \mathbf{v} = |\mathbf{u}||\mathbf{v}|\cos \theta.\] Logo,

\[\cos \theta = \frac{\mathbf{u} \cdot \mathbf{v}}{|\mathbf{u}||\mathbf{v}|}.\]

Se os vetores são ortogonais, \(\cos \theta = 0\). Se os vetores são paralelos e na mesma direção, \(\cos \theta = 1\).

O menor ângulo não negativo entre dois vetores (\(\theta \in [0, \pi]\)) pode ser calculado como:

\[\theta = \cos^{-1} \left( \frac{\mathbf{u} \cdot \mathbf{v}}{|\mathbf{u}||\mathbf{v}|} \right).\] Note que, para vetores unitários, a expressão é mais simples:

\[\cos \theta = \mathbf{u} \cdot \mathbf{v}\] e

\[\theta = \cos^{-1}(\mathbf{u} \cdot \mathbf{v}).\] A relação entre \(\theta\) e \(\mathbf{u} \cdot \mathbf{v}\) é como segue:

\[ \begin{align} \nonumber \textbf{u} \cdot \textbf{v} \begin{cases} >0, \quad \text{para }0 \leq \theta < \frac{\pi}{2} \\[4pt] =0, \quad \text{para }\theta = \frac{\pi}{2} \\[4pt] <0, \quad \text{para } \frac{\pi}{2} < \theta \leq \pi \end{cases} \end{align} \] A figura 6.12 mostra exemplos dos diferentes valores do produto escalar usando vetores no plano.

Valor do produto escalar e ângulo entre vetores.

Figura 6.12: Valor do produto escalar e ângulo entre vetores.

Projeção ortogonal

Dado um vetor \(\mathbf{w}\) e um vetor \(\mathbf{v}\) não nulo, podemos decompor \(\mathbf{w}\) como uma soma de dois vetores, sendo um paralelo a \(\mathbf{v}\) e outro ortogonal a \(\mathbf{v}\) (figura 6.13):

\[\mathbf{w} = a\mathbf{v} + \mathbf{u},\]

  • \(a \mathbf{v}\) é o vetor paralelo, chamado de projeção de \(\mathbf{w}\) sobre \(\mathbf{v}\), sendo que

    \[a = \frac{\mathbf{w} \cdot \mathbf{v}}{\mathbf{v} \cdot \mathbf{v}}.\]

  • \(\mathbf{u}\) é o vetor ortogonal a \(\mathbf{v}\) (isto é, \(\mathbf{u} \cdot \mathbf{v}=0\)) e

    \[\mathbf{u}=\mathbf{w}-a \mathbf{v}.\]

Projeção ortogonal de um vetor sobre outro.

Figura 6.13: Projeção ortogonal de um vetor sobre outro.

Note que, se \(\mathbf{v}\) é um vetor unitário,

\[a=\mathbf{w} \cdot \hat{\mathbf{v}}=|\mathbf{w}|\cos \theta,\]

onde \(\theta\) é o ângulo entre \(\mathbf{w}\) e \(\hat{\mathbf{v}}\).

Produto vetorial

Sejam \(\mathbf{u}\) e \(\mathbf{v}\) dois vetores do \(\mathbb{R}^3\). O produto vetorial ou produto externo de \(\mathbf{u}\) e \(\mathbf{v}\) é definido como

\[\mathbf{u} \times \mathbf{v} = |\mathbf{u}| |\mathbf{v}| \sin(\theta) \hat{\mathbf{n}},\]

onde \(\hat{\mathbf{n}}\) é um vetor unitário ortogonal a \(\mathbf{u}\) e \(\mathbf{v}\), e \(\theta\) é o ângulo entre \(\mathbf{u}\) e \(\mathbf{v}\). Assim, \(\mathbf{u} \times \mathbf{v}\) é um vetor ortogonal aos dois vetores, com magnitude \(|\mathbf{u} \times \mathbf{v}| = |\mathbf{u}| |\mathbf{v}| |\sin \theta|\) como mostra a figura 6.14.

Produto vetorial.

Figura 6.14: Produto vetorial.

A direção do vetor ortogonal é dada pela regra da mão direita: usando a mão direita, se o indicador apontar na direção de \(\mathbf{u}\) e o dedo médio apontar na direção de \(\mathbf{v}\), o vetor ortogonal \(\mathbf{u} \times \mathbf{v}\) apontará na direção do dedão (figura 6.15).

Direção do produto vetorial segundo a regra da mão direita (imagem modificada do [original](https://en.wikipedia.org/wiki/File:Right_hand_rule_cross_product.svg)).

Figura 6.15: Direção do produto vetorial segundo a regra da mão direita (imagem modificada do original).

O produto vetorial é anticomutativo, isto é,

\[\mathbf{u} \times \mathbf{v} = -(\mathbf{v} \times \mathbf{u}).\]

Assim, se a ordem dos operandos for invertida, o vetor ortogonal apontará para a direção oposta, como mostra a figura 6.16 (pela regra da mão direita, o dedão apontará para baixo).

A ordem dos operandos determina a direção do vetor ortogonal.

Figura 6.16: A ordem dos operandos determina a direção do vetor ortogonal.

O produto vetorial é calculado como

\[ \mathbf{u} \times \mathbf{v} = (u_y v_z - u_z v_y, u_z v_x - u_x v_z, u_x v_y - u_y v_x). \]

Para memorizar mais facilmente, podemos expressar o produto vetorial como um determinante de ordem 3:

\[ \mathbf{u} \times \mathbf{v} = \begin{vmatrix} \hat{\mathbf{i}} & \hat{\mathbf{j}} & \hat{\mathbf{k}} \\ u_x & u_y & u_z \\ v_x & v_y & v_z \end{vmatrix}. \] Usando expansão de cofatores:

\[ \begin{align} \mathbf{u} \times \mathbf{v} &= \begin{vmatrix} u_y & u_z \\ v_y & v_z \end{vmatrix}\hat{\mathbf{i}} - \begin{vmatrix} u_x & u_z \\ v_x & v_z \end{vmatrix}\hat{\mathbf{j}} + \begin{vmatrix} u_x & u_y \\ v_x & v_y \end{vmatrix}\hat{\mathbf{k}}\\ &= (u_y v_z - u_z v_y)\hat{\mathbf{i}}-(u_x v_z - u_z v_x)\hat{\mathbf{j}}+(u_x v_y - u_y v_x)\hat{\mathbf{k}}\\ &= (u_y v_z - u_z v_y, u_z v_x - u_x v_z, u_x v_y - u_y v_x) \end{align} \] Uma vez que o vetor ortogonal tem tamanho proporcional ao seno do ângulo entre os vetores, o produto vetorial de dois vetores paralelos é o vetor nulo:

\[ \begin{align} \mathbf{u} \times \mathbf{u} &= \mathbf{0},\\ -\mathbf{u} \times \mathbf{u} &= \mathbf{0}. \end{align} \]

Outras propriedades são dadas a seguir:

  • \(\mathbf{u} \times (\mathbf{v} + \mathbf{w}) = (\mathbf{u}\times\mathbf{v})+(\mathbf{u}\times\mathbf{w})\).
  • \((a\mathbf{u}) \times \mathbf{v} = \mathbf{u} \times (a \mathbf{v}) = a (\mathbf{u} \times \mathbf{v})\).
  • \(\mathbf{u} \cdot (\mathbf{v} \times \mathbf{w}) = (\mathbf{u} \times \mathbf{v}) \cdot \mathbf{w}\).
  • \(\mathbf{u} \times (\mathbf{v} \times \mathbf{w})=(\mathbf{u} \cdot \mathbf{w})\mathbf{v} - (\mathbf{u} \cdot \mathbf{v})\mathbf{w}\).

Além disso,

\[ \begin{align} \hat{\mathbf{i}} \times \hat{\mathbf{j}} = \hat{\mathbf{k}},\\ \hat{\mathbf{j}} \times \hat{\mathbf{k}} = \hat{\mathbf{i}},\\ \hat{\mathbf{k}} \times \hat{\mathbf{i}} = \hat{\mathbf{j}}. \end{align} \]

Vetor normal

Um vetor normal, ou simplesmente “normal,” é um vetor perpendicular ao plano que tangencia uma superfície em um dado ponto. Em computação gráfica, vetores normais são essenciais para o cálculo correto do sombreamento e iluminação de superfícies.

Se considerarmos a superfície de uma esfera de raio \(r>0\) dada pela equação

\[x^2+y^2+z^2=r^2,\] a normal de um ponto \(P=(x,y,z)\) sobre essa esfera é o vetor \(\mathbf{n}=(2x, 2y, 2z)\) (figura 6.17). O vetor no sentido oposto, \(-\mathbf{n}\), também é um vetor normal. Entretanto, em superfícies fechadas como a esfera, geralmente estamos interessados nas normais que apontam para fora da superfície.

Vetor normal em um ponto na superfície de uma esfera.

Figura 6.17: Vetor normal em um ponto na superfície de uma esfera.

O cálculo do vetor normal em superfícies suaves frequentemente exige o uso de ferramentas de geometria diferencial. Por exemplo, em uma superfície definida implicitamente como uma função level set \(f(x,y,z)=c\), o vetor normal é calculado através do gradiente

\[ \begin{align} \mathbf{n} = \nabla f(x,y,z) = \frac{\partial f}{\partial x}\hat{\mathbf{i}} + \frac{\partial f}{\partial y}\hat{\mathbf{j}} + \frac{\partial f}{\partial z}\hat{\mathbf{k}}. \end{align} \] De fato, para a esfera centralizada na origem,

\[f(x,y,z)=x^2+y^2+z^2\]

e

\[ \begin{align} \mathbf{n} = \nabla f(x,y,z) &= 2x\,\hat{\mathbf{i}} + 2y\,\hat{\mathbf{j}} + 2z\,\hat{\mathbf{k}}\\ &= (2x, 2y, 2z). \end{align} \]

Entretanto, neste curso não trabalharemos com superfícies implícitas. Utilizaremos apenas superfícies formadas por malhas de triângulos, uma vez que o pipeline gráfico do OpenGL trabalha apenas com pontos, segmentos e triângulos. Se quisermos renderizar uma esfera, teremos de usar uma malha triangular que aproxime essa esfera. A figura 6.18 ilustra uma malha que aproxima uma esfera. Essa malha pode ser descrita unicamente por triângulos, pois cada quadrilátero pode ser formado por dois triângulos.

Vetor normal em uma malha que aproxima a superfície de uma esfera.

Figura 6.18: Vetor normal em uma malha que aproxima a superfície de uma esfera.

Em geral, dada uma malha de triângulos, não temos acesso à representação implícita ou paramétrica da superfície que a malha tenta aproximar. Assim, no caso geral, a normal \(n\) mostrada na figura 6.18 precisa ser calculada utilizando unicamente os triângulos que formam a malha.

Calculando o vetor normal de um triângulo.

Figura 6.19: Calculando o vetor normal de um triângulo.

Para calcular a normal de um triângulo \(\triangle ABC\), basta definir dois vetores sobre o plano do triângulo, e então calcular o produto vetorial desses vetores. Os dois vetores podem ser obtidos através da subtração dos vértices que formam quaisquer duas arestas do triângulo (figura 6.19):

\[ \begin{align} \mathbf{u}&=A-C,\\ \mathbf{v}&=B-C,\\ \mathbf{n}&=\mathbf{u} \times \mathbf{v}.\\ \end{align} \] Em geral, desejaremos trabalhar com normais unitárias. Nesse caso, a normal será calculada como

\[ \begin{align} \hat{\mathbf{n}}&=\frac{\mathbf{u} \times \mathbf{v}}{|\mathbf{u} \times \mathbf{v}|}.\\ \end{align} \] Como o triângulo é uma superfície planar, o vetor normal é o mesmo para todos os pontos do triângulo. Entretanto, isso evidencia um problema com o cálculo do vetor normal em vértices de uma malha que aproxima uma superfície suave. Observe na figura 6.20 o detalhe ampliado da esfera da figura 6.18. Cada face, formada por dois triângulos (mostrados pelo tracejado), é uma superfície planar. Portanto, cada face tem o mesmo vetor normal para todos os pontos. Por outro lado, o ponto \(P\) é compartilhado por quatro faces (seis triângulos). Qual das normais (\(\mathbf{n}_1\), \(\mathbf{n}_2\), \(\mathbf{n}_3\), \(\mathbf{n}_4\)) deve ser utilizada em \(\mathbf{n}_p\)?

Detalhe ampliado de uma esfera aproximada por uma malha.

Figura 6.20: Detalhe ampliado de uma esfera aproximada por uma malha.

Como a malha de triângulos aproxima uma superfície suave, podemos calcular um vetor normal em \(P\) como uma média dos vetores normais de todos os \(n\) triângulos que usam \(P\). Uma forma simples de fazer isso é através da normalização da soma dessas normais

\[ \begin{align} \hat{\mathbf{n}}_p&=\frac{\sum_{i=1}^n \mathbf{n}_i}{|\sum_{i=1}^n \mathbf{n}_i|},\\ \end{align} \] onde \(\mathbf{n}_i\) é o vetor normal do \(n\)-ésimo triângulo que usa \(P\). O resultado é um vetor normalizado chamado de normal de vértice. A figura 6.21 ilustra, em um corte bidimensional, como a normal do vértice \(P\) aproxima a superfície suave mostrada no tracejado.

Normal de vértice como aproximação da normal da superfície suave.

Figura 6.21: Normal de vértice como aproximação da normal da superfície suave.

Podemos utilizar este método sempre que soubermos que a malha aproxime uma superfície suave. Veremos nas próximas seções que esse é o método ideal para ser utilizado com geometria indexada, que é a geometria em que os atributos de um vértice são compartilhados com todas as faces adjacentes. Entretanto, se a malha representar um objeto com quinas, tal como um cubo ou pirâmide, então cada face precisará ser renderizada com vértices não compartilhados, pois queremos evidenciar a descontinuidade da superfície. Se esse fosse o caso da geometria ilustrada na figura 6.20, quatro vértices teriam de ser utilizados em \(P\): um para cada face (quadrilátero formado por dois triângulos). Os vértices teriam a mesma posição de \(P\), mas cada um usaria a normal da face correspondente.


  1. Nesse contexto, frame é um quadro de referência (frame of reference) de um sistema de coordenadas e não tem relação com o termo frame utilizado para descrever uma imagem renderizada.↩︎