Войти
Sergei ShaykinСтатьи

Кватернионы в программировании игр. (2 стр)

Автор:

Гладкая интерполяция

Одним из наиболее полезных свойств кватернионов является достижение гладкой анимации при интерполяции. Рассмотрим интерполяцию между двумя кватернионами, которые задают вращение. При этом интерполяция происходит вдоль кратчайшей дуги. Этого можно достичь при помощи сферической линейной интерполяции (SLERP - Spherical Linear intERPolation):

SLERP(t) =  (p sin((1–t)a) – q sin(ta)) / sin(a)

где q и p - кватернионы.
t - изменяется от 0 до 1,
a - угол между q и p, cos(a) = (q,p)/(|q|*|p|) = (q,p).

При очень маленьких a, чтобы избежать деления на ноль, пользуйтесь обычной линейной интерполяцией. Реализация:

void Slerp(Quaternion * res
           Quaternion * q, Quaternion * p, float t)
{
  float p1[4];
  double omega, cosom, sinom, scale0, scale1;

  // косинус угла
  cosom = q->x*p->x + q->y*p->y + q->z*p->z + q->w*p->w;

  if ( cosom <0.0 )
  { 
    cosom = -cosom;
    p1[0] = - p->x;  p1[1] = - p->y;
    p1[2] = - p->z;  p1[3] = - p->w;
  }
  else
  {
    p1[0] = p->x;    p1[1] = p->y;
    p1[2] = p->z;    p1[3] = p->w;
  }

  if ( (1.0 - cosom) > DELTA )
  {
    // стандартный случай (slerp)
    omega = acos(cosom);
    sinom = sin(omega);
    scale0 = sin((1.0 - t) * omega) / sinom;
    scale1 = sin(t * omega) / sinom;
  }
  else
  {        
    // если маленький угол - линейная интерполяция
    scale0 = 1.0 - t;
    scale1 = t;
  }

  res->x = scale0 * q->x + scale1 * p1[0];
  res->y = scale0 * q->y + scale1 * p1[1];
  res->z = scale0 * q->z + scale1 * p1[2];
  res->w = scale0 * q->w + scale1 * p1[3];
}

Кватернионы в DirectX

Вместе с DirectX SDK поставляется утилитная библиотека Direct3DX utility library. В ней немного места уделено и кватернионам. Кватернион задается структурой:

typedef struct D3DXQUATERNION {
  FLOAT x,y,z,w;
} D3DXQUATERNION;

Есть набор функций для работы со стандартными возможностями кватернионов:

Перемножение двух кватернионов:
  D3DXQuaternionMultiply()

Получить размер:
  D3DXQuaternionLength()

Нормализация:
  D3DXQuaternionNormalize()

Преобразование улов Эйлера в кватернион:
  D3DXQuaternionRotationYawPitchRoll()

Преобразование матрицы вращения в кватернион и обратно:
  D3DXQuaternionRotationMatrix()
  D3DXMatrixRotationQuaternion()

Сферическая линейная интерполяция:
  D3DXQuaternionSlerp()

И т.д. Полное описание всех функций смотрите в DirectX SDK.

Кватернионы в MAX SDK

В Max SDK кватернионы описываются классом С++:

class Quat{...};

Класс наполнен необходимыми методами и операторами. Конструкции языка С++ позволяют перегружать операторы, например, для кватернионов можно записать сумму в более читаемом виде:

q = q1+q2;

Кроме методов класса Quat, в классе для матриц Matrix3 есть метод преобразования из кватерниона:
void SetRotate(const Quat& q);

Кватернион, задающий вращение, можно получить для любого объекта сцены. Трансформация хранится в объектах класса INode. Сначала, нужно получить контроллер вращения из контроллера трансформации, затем воспользоваться методом GetValue() для этого контроллера:

void GetQuat(Quat * pQuat, const pNode * pNode)
{
  Control * pTransf = pNode->GetTMController();
  if(pTransf)
  {
    Control * pCtrl = pTransf->GetRotationController();
    if(pCtrl)
      pCtrl->GetValue(0, pQuat, NEVER, CTRL_ABSOLUTE);
  }
}

Во время экспорта будьте внимательны с координатными системами. Ваша координатная система может не совпадать с координатной системой выбранной в 3D Studio MAX. Например, ось z здесь направлена вверх, а многие другие API, включая DirectX и OpenGL, направляют вверх ось y. По этой причине в полученных кватернионах параметр y может не соответствовать вашему y. Например, при экспорте в координатную систему DirectX можно пользоваться следующим преобразованием, обратите внимание на знаки и на компоненты y и z:

dx_quat.x = -max_quat.x;
dx_quat.y = -max_quat.z;
dx_quat.z = -max_quat.y;
dx_quat.w =  max_quat.w;

Ссылки по теме

Вращение и кватернионы. Сборник рецептов.

http://www.enlight.ru/faq3d/articles/77.htm
http://www.flipcode.com/documents/matrfaq.html
http://www.gamasutra.com/features/19980703/quaternions_01.htm

Страницы: 1 2

#кватернионы, #математика

5 августа 2001 (Обновление: 29 дек. 2013)

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