ПрограммированиеСтатьиОбщее

ЧАВО по матрицам и кватернионам (5 стр)

Автор:

КВАТЕРНИОНЫ

Что такое кватернионы?

Кватернионы — расширение понятия вращения в трех измерениях в четыре. Это позволяет обойти проблему фиксации оси и дает возможность реализовать гладкое и непрерывное вращение. Их можно представить в виде дополнительного угла вращения к сферическим координатам, иначе говоря, долгота, широта и вращение.
 
Кватернион описывается четырьмя числами \(x, y, z, w\). Они считаются как комбинация трех координатных осей вращения и угла вращения. Кватернион можно обозначить так:

\(q = (w, \vec{v})\)

Какое место занимают кватернионы в 3D анимации?

Как говорилось до этого, углы Эйлера страдают от так называемой фиксации оси (gimbal lock), из-за которой объект перестает вращаться так, как от него этого ждут, в зависимости от последовательности вращений.

Кватернионы — решение этой проблемы. Вместо вращения объекта через серию поворотов, кватернион дает программисту возможность повернуть объект по любой оси на любой угол.

Вращение все равно происходит через матричную математику. Однако, вместо умножения матриц, кватернион представляет оси вращения вместе и результат переводится в нужную матрицу вращения.

Так как вращение описывается в единичным вектором направления, он может быть также вычислен через векторную математику или из сферических координат (долгота, широта).
 
Кватернионы дают еще один плюс — их можно интерполировать, что дает гладкое и предсказуемое вращение.

Как вычислить сопряжение кватернионов?

Это можно сделать через изменение полярности векторной части кватерниона.

\(q^* = (w, -\vec{v})\)

  quaternion_conjugate( QUAT *qr, QUAT *q ){
    qr -> qw =  q -> qw;
    qr -> qx = -q -> qx;
    qr -> qy = -q -> qy;
    qr -> qz = -q -> qz;
  } 

Как вычислить обратный кватернион?

Это эквивалентно вычислению сопряжения кватерниона.

Как вычислить длину кватерниона?

Длина кватерниона рассчитывается через умножение кватерниона на сопряженный:

\(|q| = \sqrt{q^* \cdot q}\)

В коде это будет выглядеть так:

  QFLOAT quaternion_magnitude( QUAT *qa )
  {
    return( sqrt(qa->qw*qa->qw+
                 qa->qx*qa->qx+ qa->qy*qa->qy+qa->qz*qa->qz) )
  }

Как нормализовать кватернион?

Кватернион может быть нормализован также как вектор. Сначала вычисляют длину кватерниона. Затем обе части кватерниона делятся на это значение.

Единичный кватернион всегда имеет длину 1.0.

Как умножить два кватерниона?

Дано два кватерниона Q1 и Q2, задача - найти комбинацию Qr:

\(q = q_1 \cdot q_2\)

Это можно сделать так:

\(q_1 \cdot q_2 = (w_1 w_2 - \vec{v_1} \cdot \vec{v_2}, w_1 \vec{v_2} + w_2 \vec{v_1} + \vec{v_1} \times \vec{v_2}),\)

где \(\vec{v_1} = (x, y, z)\) кватерниона \(q_1\),
  \(w_1 = w\) кватерниона \(q_1\),
  \(\vec{v_2} = (x, y, z)\) кватерниона \(q_2\),
  \(w_2 = w\) кватерниона \(q_2\),
  \(\cdot\) — скалярное произведение векторов,
  \(\times\) — векторное произведение

В коде это будет выглядеть так:

  quaternion_multiply( QUAT *qr, QUAT *qa, QUAT *qb )
  {
    qr.scalar = v3_dot( &qa->vector, &qb->vector );

    v3_cross(  &va, &qa->vector, &qb->vector );
    v3_scalef( &vb, &qa->vector, &qb->scalar );
    v3_scalef( &vc, &qb->vector, &qa->scaler );
    v3_add(    &va,         &va, &vb );
    v3_add(    &qr->vector, &va, &vc );

    quaternion_normalise( qr );
  }

Как мне перевести кватернион в матрицу вращения?

  Пусть кватернион задан так:

    Q = |X Y Z W|

То кватернион может быть переведён в матрицу вращения 3х3 так:

        |       2     2                                |
        | 1 - 2Y  - 2Z    2XY - 2ZW      2XZ + 2YW     |
        |                                              |
        |                       2     2                |
    M = | 2XY + 2ZW       1 - 2X  - 2Z   2YZ - 2XW     |
        |                                              |
        |                                      2     2 |
        | 2XZ - 2YW       2YZ + 2XW      1 - 2X  - 2Y  |
        |                                              |

Если матрица нужна матрица 4х4, то добавляют
  еще один нижний ряд и правую колонку.
 
  Матрица создается по следующему правилу
 

    xx      = X * X;
    xy      = X * Y;
    xz      = X * Z;
    xw      = X * W;

    yy      = Y * Y;
    yz      = Y * Z;
    yw      = Y * W;
    zz      = Z * Z;
    zw      = Z * W;

    mat[0]  = 1 - 2 * ( yy + zz );
    mat[1]  =     2 * ( xy - zw );
    mat[2]  =     2 * ( xz + yw );

    mat[4]  =     2 * ( xy + zw );
    mat[5]  = 1 - 2 * ( xx + zz );
    mat[6]  =     2 * ( yz - xw );

    mat[8]  =     2 * ( xz - yw );
    mat[9]  =     2 * ( yz + xw );
    mat[10] = 1 - 2 * ( xx + yy );

    mat[3]  = mat[7] = mat[11 = mat[12] = mat[13] = mat[14] = 0;
    mat[15] = 1;

Как мне перевести матрицу в кватернион?


--------------------------------------------------------
 
  Вращение может быть превращено обратно в кватернион
  с помощью следующего алгоритма:

  Процесс состоит из следующих шагов:
 
    Посчитать проекцию матрицы T из уравнения:

                2     2     2
      T = 4 - 4x  - 4y  - 4z

                 2    2    2
        = 4( 1 -x  - y  - z )

        = mat[0] + mat[5] + mat[10] + 1

Если проекция больше 0,
  то делаем "мнгновенное" преобразование.

  
      S = 0.5 / sqrt(T)
      W = 0.25 / S
      X = ( mat[9] - mat[6] ) * S
      Y = ( mat[2] - mat[8] ) * S
      Z = ( mat[4] - mat[1] ) * S

Если проекция меньше или равно 0 ищем в главной диагонали
  самое большое значение.
 
  В зависимости от этого значения считаем:

      Колонка 0:

        S  = sqrt( 1.0 + mr[0] - mr[5] - mr[10] ) * 2;

        Qx = 0.5 / S;
        Qy = (mr[1] + mr[4] ) / S;
        Qz = (mr[2] + mr[8] ) / S;
        Qw = (mr[6] + mr[9] ) / S;

Колонка 1:

        S  = sqrt( 1.0 + mr[5] - mr[0] - mr[10] ) * 2;

        Qx = (mr[1] + mr[4] ) / S;
        Qy = 0.5 / S;
        Qz = (mr[6] + mr[9] ) / S;
        Qw = (mr[2] + mr[8] ) / S;

Колонка 2:

        S  = sqrt( 1.0 + mr[10] - mr[0] - mr[5] ) * 2;

        Qx = (mr[2] + mr[8] ) / S;
        Qy = (mr[6] + mr[9] ) / S;
        Qz = 0.5 / S;
        Qw = (mr[1] + mr[4] ) / S;

Кватернион задан так:

       Q = | Qx Qy Qz Qw |
Страницы: 1 2 3 4 5 6 Следующая »

#C++, #FAQ, #OpenGL, #кватернионы, #математика, #матрицы

9 марта 2011 (Обновление: 5 дек 2021)

Комментарии [40]