O que são quaterniões?

Os quaterniões estendem o conceito de rotação em três dimensões para a rotação em quatro dimensões. Isso evita o problema do “gimbal-lock” e permite a implementação de rotações suaves e contínuas.

Na prática, eles podem ser considerados como a adição de um ângulo de rotação adicional às coordenadas esféricas, ou seja, longitude, latitude e ângulos de rotação.

Um quaternião é definido usando quatro valores de ponto flutuante x y z w|x\ y\ z\ w|.

Esses valores são calculados a partir da combinação das três coordenadas do eixo de rotação e o ângulo de rotação.

Como os quaterniões se relacionam com animação 3D?

Como mencionado antes, os ângulos de Euler têm a desvantagem de serem suscetíveis ao “Gimbal lock”, onde tentativas de rotacionar um objeto falham devido à ordem na qual as rotações são realizadas.

Os quaterniões são uma solução para esse problema. Em vez de rotacionar um objeto por meio de uma série de rotações sucessivas, um quaternião permite ao programador rotacionar um objeto através de um único eixo de rotação arbitrário.

Como o eixo de rotação é especificado como um vetor de direção unitário, ele pode ser calculado por meio de matemática vetorial ou a partir de coordenadas esféricas, ou seja, (longitude/latitude).

Os quaterniões oferecem outra vantagem: eles podem ser interpolados. Isso permite efeitos de rotação suaves e previsíveis.

Como converter um quaternião para uma matriz de rotação?

Supondo que um quaternião tenha sido criado na forma:

Q=X Y Z W Q = |X\ Y\ Z\ W|

Então, o quaternião pode ser convertido em uma matriz de rotação 4x4 usando a seguinte expressão:

$$ M = \begin{pmatrix} 1 - 2Y^2 - 2Z^2 & 2XY - 2ZW & 2XZ + 2YW \
2XY + 2ZW & 1 - 2X^2 - 2Z^2 & 2YZ - 2XW \
2XZ - 2YW & 2YZ + 2XW & 1 - 2X^2 - 2Y^2 \end{pmatrix} $$

Se for necessária uma matriz 4x4, então a última linha e a coluna à direita podem ser adicionadas.

A matriz pode ser gerada usando a seguinte expressão:

xx=XX;xy=XY;xz=XZ;xw=XW; xx = X \cdot X; \quad xy = X \cdot Y; \quad xz = X \cdot Z; \quad xw = X \cdot W; yy=YY;yz=YZ;yw=YW; yy = Y \cdot Y; \quad yz = Y \cdot Z; \quad yw = Y \cdot W; zz=ZZ;zw=ZW; zz = Z \cdot Z; \quad zw = Z \cdot W;

mat[0]=12(yy+zz);mat[1]=2(xyzw);mat[2]=2(xz+yw); \text{mat}[0] = 1 - 2 \cdot (yy + zz); \quad \text{mat}[1] = 2 \cdot (xy - zw); \quad \text{mat}[2] = 2 \cdot (xz + yw); mat[4]=2(xy+zw);mat[5]=12(xx+zz);mat[6]=2(yzxw); \text{mat}[4] = 2 \cdot (xy + zw); \quad \text{mat}[5] = 1 - 2 \cdot (xx + zz); \quad \text{mat}[6] = 2 \cdot (yz - xw); mat[8]=2(xzyw);mat[9]=2(yz+xw);mat[10]=12(xx+yy); \text{mat}[8] = 2 \cdot (xz - yw); \quad \text{mat}[9] = 2 \cdot (yz + xw); \quad \text{mat}[10] = 1 - 2 \cdot (xx + yy); mat[3]=mat[7]=mat[11]=mat[12]=mat[13]=mat[14]=0;mat[15]=1; \text{mat}[3] = \text{mat}[7] = \text{mat}[11] = \text{mat}[12] = \text{mat}[13] = \text{mat}[14] = 0; \quad \text{mat}[15] = 1;

Como converter uma matriz de rotação para um quaternião?

Uma rotação pode ser convertida de volta para um quaternião através do uso do seguinte algoritmo:

O processo é realizado nas seguintes etapas:

  1. Calcular o traço da matriz TT a partir da equação:

T=44x24y24z2 T = 4 - 4x^2 - 4y^2 - 4z^2

ou seja,

T=4(1x2y2z2) T = 4(1 - x^2 - y^2 - z^2)

T=mat[0]+mat[5]+mat[10]+1 T = \text{mat}[0] + \text{mat}[5] + \text{mat}[10] + 1

  1. Se o traço da matriz for maior que zero, então realizar um cálculo “instantâneo”:

S=0.5T S = \frac{0.5}{\sqrt{T}} W=0.25S W = \frac{0.25}{S} X=(mat[9]mat[6])S X = (\text{mat}[9] - \text{mat}[6]) \cdot S Y=(mat[2]mat[8])S Y = (\text{mat}[2] - \text{mat}[8]) \cdot S Z=(mat[4]mat[1])S Z = (\text{mat}[4] - \text{mat}[1]) \cdot S

  1. Se o traço da matriz for menor ou igual a zero, então identificar qual elemento da diagonal principal tem o maior valor.

Dependendo desse valor, calcular o seguinte:

  • Coluna 0: S=1.0+mr[0]mr[5]mr[10]2; S = \sqrt{1.0 + \text{mr}[0] - \text{mr}[5] - \text{mr}[10]} \cdot 2;

    Qx=1S;Qy=mr[1]+mr[4]S;Qz=mr[2]+mr[8]S;Qw=mr[6]+mr[9]S; Qx = \frac{1}{S}; \quad Qy = \frac{\text{mr}[1] + \text{mr}[4]}{S}; \quad Qz = \frac{\text{mr}[2] + \text{mr}[8]}{S}; \quad Qw = \frac{\text{mr}[6] + \text{mr}[9]}{S};

  • Coluna 1: S=1.0+mr[5]mr[0]mr[10]2; S = \sqrt{1.0 + \text{mr}[5] - \text{mr}[0] - \text{mr}[10]} \cdot 2;

    Qx=mr[1]+mr[4]S;Qy=1S;Qz=mr[6]+mr[9]S;Qw=mr[2]+mr[8]S; Qx = \frac{\text{mr}[1] + \text{mr}[4]}{S}; \quad Qy = \frac{1}{S}; \quad Qz = \frac{\text{mr}[6] + \text{mr}[9]}{S}; \quad Qw = \frac{\text{mr}[2] + \text{mr}[8]}{S};

  • Coluna 2: S=1.0+mr[10]mr[0]mr[5]2; S = \sqrt{1.0 + \text{mr}[10] - \text{mr}[0] - \text{mr}[5]} \cdot 2;

    Qx=mr[2]+mr[8]S;Qy=mr[6]+mr[9]S;Qz=1S;Qw=mr[1]+mr[4]S; Qx = \frac{\text{mr}[2] + \text{mr}[8]}{S}; \quad Qy = \frac{\text{mr}[6] + \text{mr}[9]}{S}; \quad Qz = \frac{1}{S}; \quad Qw = \frac{\text{mr}[1] + \text{mr}[4]}{S};

O quaternião é então definido como:

Q=Qx Qy Qz Qw Q = |Qx\ Qy\ Qz\ Qw|

Como converter um eixo de rotação e um ângulo para um quaternião?

Dado o eixo de rotação e o ângulo, o seguinte algoritmo pode ser usado para gerar um quaternião:

sin(α)=sin(aˆngulo2) \sin(\alpha) = \sin\left(\frac{\text{ângulo}}{2}\right) cos(α)=cos(aˆngulo2) \cos(\alpha) = \cos\left(\frac{\text{ângulo}}{2}\right) qx=eixo>xsin(α) qx = \frac{\text{eixo}->x}{\sin(\alpha)} qy=eixo>ysin(α) qy = \frac{\text{eixo}->y}{\sin(\alpha)} qz=eixo>zsin(α) qz = \frac{\text{eixo}->z}{\sin(\alpha)} qw=cos(α) qw = \cos(\alpha)

Como converter um quaternião para um eixo de rotação e ângulo?

Um quaternião pode ser convertido de volta para um eixo de rotação e um ângulo utilizando o seguinte algoritmo:

cos(aˆngulo)=qr>qw; \cos(\text{ângulo}) = qr->qw; aˆngulo=arccos(cos(aˆngulo))2RADIANS; \text{ângulo} = \arccos(\cos(\text{ângulo})) \cdot 2 \cdot \text{RADIANS}; sin(aˆngulo)=1.0cos(aˆngulo)2; \sin(\text{ângulo}) = \sqrt{1.0 - \cos(\text{ângulo})^2};

Se sin(aˆngulo)<0.0005|\sin(\text{ângulo})| < 0.0005, então sa=1sa = 1.

eixo>vx=qr>qxsa; \text{eixo}->vx = \frac{qr->qx}{sa}; eixo>vy=qr>qysa; \text{eixo}->vy = \frac{qr->qy}{sa}; eixo>vz=qr>qzsa; \text{eixo}->vz = \frac{qr->qz}{sa};

Como converter ângulos de rotação esféricos para um quaternião?

Um eixo de rotação pode ser definido usando coordenadas esféricas (latitude e longitude) e um ângulo de rotação.

Neste caso, o quaternião pode ser calculado da seguinte forma:

sin(α)=sin(aˆngulo2) \sin(\alpha) = \sin\left(\frac{\text{ângulo}}{2}\right) cos(α)=cos(aˆngulo2) \cos(\alpha) = \cos\left(\frac{\text{ângulo}}{2}\right) sin(latitude)=sin(latitude) \sin(\text{latitude}) = \sin(\text{latitude}) cos(latitude)=cos(latitude) \cos(\text{latitude}) = \cos(\text{latitude}) sin(longitude)=sin(longitude) \sin(\text{longitude}) = \sin(\text{longitude}) cos(longitude)=cos(longitude) \cos(\text{longitude}) = \cos(\text{longitude})

Então o quaternião é:

Q=longitudesin(α)latitudesin(α)sin(latitude)cos(α)cos(α) Q = | \text{longitude}\cdot\sin(\alpha) \quad \text{latitude}\cdot\sin(\alpha) \quad \sin(\text{latitude}) \cdot \cos(\alpha) \quad \cos(\alpha) |

Como usar quaterniões para realizar interpolação cúbica entre matrizes?

Para algumas aplicações, pode não ser conveniente ou possível usar interpolação linear para fins de animação. Nesse caso, a interpolação cúbica é outra alternativa.

Para usar interpolação cúbica, pelo menos quatro matrizes de rotação devem ser conhecidas.

Cada uma delas é então convertida em um conjunto de rotações esféricas via quaterniões e ângulos de rotação esféricos (ou seja, longitude, latitude e ângulo de rotação).

Essas rotações são então multiplicadas com a matriz base para uma curva Cardinal spline. Essa matriz de interpolação pode então ser usada para determinar os ângulos de rotação esféricos intermediários.

Uma vez conhecidos os coordenadas interpoladas (latitude, longitude e ângulo de rotação), a matriz de rotação interpolada pode então ser gerada através da conversão para quaterniões.

Usando uma biblioteca de matriz 4x4, o algoritmo é o seguinte:

for (n = 0; n < 4; n++)
  m4_to_spherical(mat[n], &v_sph[n]);      /* Coordenadas esféricas */

m4_multspline(m_cardinal, v_sph, v_interp); /* Vetor de interpolação */

...

v3_cubic(v_pos, v_interp, t);            /* Interpolação */

m4_from_spherical(m_rot, v_pos);        /* De volta a uma matriz */

Como converter uma matriz de rotação para um quaternião?

Uma rotação pode ser convertida de volta para um quaternião através do uso do seguinte algoritmo:

O processo é realizado nas seguintes etapas:

  1. Calcule o traço da matriz TT a partir da equação:

    T=44x24y24z2 T = 4 - 4x^2 - 4y^2 - 4z^2

    Ou equivalentemente:

    T=4(1x2y2z2) T = 4( 1 - x^2 - y^2 - z^2 )

    E também:

    T=mat[0]+mat[5]+mat[10]+1 T = \text{mat}[0] + \text{mat}[5] + \text{mat}[10] + 1

  2. Se o traço da matriz for maior que zero, então realize um cálculo “instantâneo”:

    S=0.5T S = \frac{0.5}{\sqrt{T}}

    W=0.25S W = \frac{0.25}{S}

    X=(mat[9]mat[6])×S X = (\text{mat}[9] - \text{mat}[6]) \times S

    Y=(mat[2]mat[8])×S Y = (\text{mat}[2] - \text{mat}[8]) \times S

    Z=(mat[4]mat[1])×S Z = (\text{mat}[4] - \text{mat}[1]) \times S

  3. Se o traço da matriz for menor ou igual a zero, então identifique qual elemento da diagonal principal tem o maior valor.

Dependendo deste valor, calcule o seguinte:

  • Coluna 0:

    S=1.0+mr[0]mr[5]mr[10]×2 S = \sqrt{1.0 + \text{mr}[0] - \text{mr}[5] - \text{mr}[10]} \times 2

    Qx=0.5S Qx = \frac{0.5}{S}

    Qy=mr[1]+mr[4]S Qy = \frac{\text{mr}[1] + \text{mr}[4]}{S}

    Qz=mr[2]+mr[8]S Qz = \frac{\text{mr}[2] + \text{mr}[8]}{S}

    Qw=mr[6]+mr[9]S Qw = \frac{\text{mr}[6] + \text{mr}[9]}{S}

  • Coluna 1:

    S=1.0+mr[5]mr[0]mr[10]×2 S = \sqrt{1.0 + \text{mr}[5] - \text{mr}[0] - \text{mr}[10]} \times 2

    Qx=mr[1]+mr[4]S Qx = \frac{\text{mr}[1] + \text{mr}[4]}{S}

    Qy=0.5S Qy = \frac{0.5}{S}

    Qz=mr[6]+mr[9]S Qz = \frac{\text{mr}[6] + \text{mr}[9]}{S}

    Qw=mr[2]+mr[8]S Qw = \frac{\text{mr}[2] + \text{mr}[8]}{S}

  • Coluna 2:

    S=1.0+mr[10]mr[0]mr[5]×2 S = \sqrt{1.0 + \text{mr}[10] - \text{mr}[0] - \text{mr}[5]} \times 2

    Qx=mr[2]+mr[8]S Qx = \frac{\text{mr}[2] + \text{mr}[8]}{S}

    Qy=mr[6]+mr[9]S Qy = \frac{\text{mr}[6] + \text{mr}[9]}{S}

    Qz=0.5S Qz = \frac{0.5}{S}

    Qw=mr[1]+mr[4]S Qw = \frac{\text{mr}[1] + \text{mr}[4]}{S}

O quaternião é então definido como:

Q=[QxQyQzQw] Q = \begin{bmatrix} Qx & Qy & Qz & Qw \end{bmatrix}

Como converter um eixo de rotação e um ângulo para um quaternião?

Dado o eixo de rotação e o ângulo, o seguinte algoritmo pode ser usado para gerar um quaternião:

$$ sin_a = sin(ângulo / 2) cos_a = cos(ângulo / 2)

qx = eixo_x / sin_a qy = eixo_y / sin_a qz = eixo_z / sin_a qw = cos_a $$

Como converter um quaternião para um eixo de rotação e um ângulo?

Um quaternião pode ser convertido de volta para um eixo de rotação e um ângulo usando o seguinte algoritmo:

cos(ângulo) = q_r -> qw
ângulo = acos(cos(ângulo)) * 2 * RADIANS
sin(ângulo) = sqrt(1.0 - cos(ângulo)^2)

se (fabs(sin(ângulo)) < 0.0005)
   sa = 1

eixo_x = q_r -> qx / sa
eixo_y = q_r -> qy / sa
eixo_z = q_r -> qz / sa

Como converter ângulos de rotação esféricos para um quaternião?

Um eixo de rotação pode ser definido usando coordenadas esféricas (latitude e longitude) e um ângulo de rotação. Neste caso, o quaternião pode ser calculado da seguinte forma:

sin_a = sin(ângulo / 2)
cos_a = cos(ângulo / 2)

sin_lat = sin(latitude)
cos_lat = cos(latitude)

sin_long = sin(longitude)
cos_long = cos(longitude)

qx = sin_a * cos_lat * sin_long
qy = sin_a * sin_lat
qz = sin_a * sin_lat * cos_long
qw = cos_a

Como converter um quaternião para ângulos de rotação esféricos?

Um quaternião pode ser convertido para coordenadas esféricas estendendo o processo de conversão:

Como usar quaterniões para realizar interpolação linear entre matrizes?

Interpolação Linear entre Matrizes de Rotação

Para muitas aplicações de animação, é necessário interpolar entre duas posições de rotação de um determinado objeto. Essas posições podem ter sido especificadas usando animação por keyframes ou cinemática inversa.

Usando qualquer um dos métodos, pelo menos duas matrizes de rotação devem ser conhecidas: a matriz inicial (MsM_s) e a matriz final (MfM_f). O objetivo é interpolar entre essas matrizes.

Usando interpolação linear, a matriz de rotação interpolada (MIM_I) é gerada utilizando uma equação de mistura com o parâmetro TT, que varia de 0.0 a 1.0.

  • Quando T=0T = 0, a matriz interpolada é igual à matriz inicial.
  • Quando T=1T = 1, a matriz interpolada é igual à matriz final.

A matriz de rotação interpolada (MIM_I) é especificada como:

MI=F(Ms,Mf,T) M_I = F(M_s, M_f, T)

onde FF é uma função de mistura.

A primeira etapa na interpolação entre as duas matrizes é determinar a matriz de rotação que converterá MsM_s para MfM_f. Isso é alcançado usando a seguinte expressão:

T=Ms1Mf T = M_s^{-1} \cdot M_f

onde MsM_s é a matriz inicial, MfM_f é a matriz final, e TT é a matriz intermediária.

A próxima etapa é converter essa matriz intermediária em um eixo de rotação e um ângulo. Isso é feito convertendo a matriz em um quaternião e, posteriormente, no eixo e ângulo de rotação necessários.

Para gerar a matriz de rotação interpolada, basta escalar o ângulo de rotação e converter esse ângulo e o eixo de rotação de volta em uma matriz de rotação.

Usando uma biblioteca de matrizes 4x4, o algoritmo é o seguinte:

m4_transpose(mt, ms);                /* Inversa */
m4_mult(ms, mt, mb);                 /* Matriz de rotação */
m4_to_axisangle(ms, eixo, angulo);   /* Eixo/ângulo de rotação */

for (t = 0; t < 1.0; t += 0.05) {
    m4_from_axisangle(mi, eixo, angulo * t); /* Interpolação final */

    /* Processar o que for necessário */
}

onde tt é o fator de interpolação variando de 0.0 a 1.0.

Como usar quaterniões para realizar interpolação cúbica entre matrizes?

Para algumas aplicações, pode não ser conveniente ou possível usar interpolação linear para fins de animação. Nesse caso, a interpolação cúbica é uma alternativa viável.

Para usar interpolação cúbica, pelo menos quatro matrizes de rotação devem ser conhecidas. Cada uma dessas matrizes é então convertida em um conjunto de rotações esféricas utilizando quaterniões e ângulos de rotação esférica (latitude, longitude e ângulo de rotação).

Esses valores são multiplicados por uma matriz base para gerar uma curva spline cardinal. A matriz de interpolação obtida pode ser utilizada para determinar os ângulos intermediários de rotação esférica.

Depois que as coordenadas interpoladas (latitude, longitude e ângulo de rotação) são calculadas, a matriz de rotação interpolada pode ser gerada através da conversão para quaterniões.

Usando uma biblioteca de matrizes 4x4, o algoritmo é descrito da seguinte forma:

for (n = 0; n < 4; n++) {
    m4_to_spherical(mat[n], &v_sph[n]);        /* Coordenadas esféricas */
}

m4_multspline(m_cardinal, v_sph, v_interp);   /* Vetor de interpolação */

/* Outras operações podem ser realizadas aqui */

v3_cubic(v_pos, v_interp, t);                 /* Interpolação cúbica */

m4_from_spherical(m_rot, v_pos);              /* Conversão para matriz */

Neste algoritmo:

  • nn representa o índice das matrizes conhecidas.
  • tt é o fator de interpolação cúbica.
  • As coordenadas interpoladas (vposv_pos) são calculadas para cada passo, e a matriz de rotação resultante é gerada a partir dessas coordenadas esféricas.