GLM: Кути Ейлера до Кватерніона


12

Я сподіваюся, що ви знаєте GL Mathematics ( GLM ), тому що у мене проблема, я не можу зламати:

У мене є набір Ейлерових кутів, і мені потрібно виконати плавну інтерполяцію між ними. Найкращий спосіб - перетворити їх на кватерніони та застосувати SLERP- алрогіртму.

У мене є питання, як ініціалізувати glm :: quaternion з Ейлером Кутом, будь ласка?

Я читав Документацію GLM знову і знову, але не можу знайти відповідного Quaternion constructor signature, який би зайняв три кути Ейлера. Найближчим, який я знайшов, є функція angleAxis () , яка приймає значення кута та вісь для цього кута. Зауважте, будь ласка, що я шукаю як спосіб, як розібратися RotX, RotY, RotZ.


Для вашої інформації, це вище metnioned angleAxis () функція підпису :

detail::tquat< valType > angleAxis (valType const &angle, valType const &x, valType const &y, valType const &z)

Відповіді:


13

Я не знайомий з GLM, але за відсутності функції прямого перетворення з кутів Ейлера в кватерніони ви можете самостійно використовувати функції "обертання навколо осі" (наприклад, "angleAxis").

Ось як (псевдокод):

Quaternion QuatAroundX = Quaternion( Vector3(1.0,0.0,0.0), EulerAngle.x );
Quaternion QuatAroundY = Quaternion( Vector3(0.0,1.0,0.0), EulerAngle.y );
Quaternion QuatAroundZ = Quaternion( Vector3(0.0,0.0,1.0), EulerAngle.z );
Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ;

(Або вам може знадобитися перемикати множення кватерніона навколо, залежно від порядку, в якому призначені ваші повороти кута ейлера)

Крім того, переглядаючи документацію GLM, виявляється, що ви можете перетворити кути ейлера -> matrix3 -> кватерніон так:

toQuat( orient3( EulerAngles ) )

хороша відповідь, оскільки це менш неоднозначно щодо порядку заявки.
Річард Фабіан

@Trevor: +1, привіт Тревор, дякую за добру відповідь. Це виглядає як найбільш практичне рішення тут. Я можу легко перемикатися між порядком множення обертання. Можливо, кількість комбінацій є причиною того, чому перетворення кута Ейлера в Кватерйон не доступне в GLM.
Bunkai.Satori

Хоча всі відповіді хороші та цінні, на мою думку, це найбільш практична. Я хотів би відзначити це як прийнятий відповідь .
Bunkai.Satori

@Trevor: У Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ ;, яке множення ви мали на увазі? Я здивований, що GLM не перевантажує operator *для розмноження Кватерніона, тому, можливо, мені доведеться перетворювати множення вручну .
Bunkai.Satori

3
@Bunkai поняття множення кватерніона схоже на матричне множення, воно не є ні крапковим, ні перехресним добутком. Якщо ви хочете зрозуміти використання кватерніонів, то звикніть до матриць і зрозумійте осі кути, їх основна концепція досить схожа на кватерніони, математика трохи більш досконала, але коли ви зрозуміли осі кути, то кватерніони не є далеко вже.
Майк Семдер

16
glm::quat myquaternion = glm::quat(glm::vec3(angle.x, angle.y, angle.z));

Де angleвідповідно glm::vec3міститься смола, позіхання, котиться .

PS. Якщо ви сумніваєтесь, просто зайдіть до заголовків і подивіться. Визначення можна знайти в glm / gtc / quaternion.hpp:

explicit tquat(tvec3<T> const & eulerAngles) {
        tvec3<T> c = glm::cos(eulerAngle * value_type(0.5));
    tvec3<T> s = glm::sin(eulerAngle * value_type(0.5));

    this->w = c.x * c.y * c.z + s.x * s.y * s.z;
    this->x = s.x * c.y * c.z - c.x * s.y * s.z;
    this->y = c.x * s.y * c.z + s.x * c.y * s.z;
    this->z = c.x * c.y * s.z - s.x * s.y * c.z;    
}

Де quatпоплавковий типdef tquat.


Це зовсім неоднозначно, в якому порядку вони застосовуватимуться? Ейлери мають упорядковані обертання, і конструктор кватерніона тут, здається, не хвилює цього.
Річард Фабіан

Визначення функції точно таке ж, як і ваше; Я розмістив це у своїй відповіді, якщо це має значення.
deceleratedcaviar

не порядок аргументів, порядок застосування обертання. Моя відповідь містить замовлення XYZ, взяті з статті wikipedia, проте ми використовуємо замовлення заявки на ZYX у моїй старій компанії, а YZX - на моїй нинішній. кут x все ще є першим значенням у списку векторів / аргументів у всіх випадках, але фактичне результуюче перетворення неоднакове.
Річард Фабіан

Я виправив свою відповідь на обертанняQuat, так що ви можете бачити, як ви могли легко змінити порядок. За замовчуванням він приймає XYZ, але ви можете легко змінити це.
deceleratedcaviar

2
-1 за те, що не
згадуєте

7

Рішення знаходиться у wikipedia: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

використовуючи це:

sx = sin(x/2); sy = sin(y/2); sz = sin(z/2);
cx = cos(x/2); cy = cos(y/2); cz = cos(z/2);

q( cx*cy*cz + sx*sy*sz,
   sx*cy*cz - cx*sy*sz,
   cx*sy*cz + sx*cy*sz,
   cx*cy*sz - sx*sy*cz ) // for XYZ application order

q( cx*cy*cz - sx*sy*sz,
   sx*cy*cz + cx*sy*sz,
   cx*sy*cz - sx*cy*sz,
   cx*cy*sz + sx*sy*cz ) // for ZYX application order

Конструктори для кватерніона, задані Ейлером (де застосування обертання - XYZ або ZYX). Однак це лише дві з шести можливих комбінацій кутів Ейлера. Вам дійсно потрібно з’ясувати, в якому порядку будуються кути Ейлера при перетворенні в матрицю перетворення. Тільки тоді рішення можна визначити.

У старій компанії, в якій я працював, у нас було Z як вперед (як і у більшості відеокарт), тому замовлення заявки було ZYX, а в моїй теперішній компанії вісь Y спрямована вперед, а Z - вгору, тож наше замовлення - YZX. Цей порядок - це порядок, у який ви множите ваші кватерніони разом, щоб генерувати остаточну трансформацію, а питання порядку обертання - множення не є комутаційними.


1
+1, привіт і дякую за чудову відповідь. Коли я використовую OpenGL , значення Z виходить із екрана. У своїй програмі я виконую замовлення на множення ZYX . Спочатку я думав, що GLM має цю функціональність, але я бачу, вони ще не реалізували її, тому однією з альтернатив є створення перетворення вручну , як ви рекомендуєте.
Bunkai.Satori

Тут найкраща відповідь.
плазмацель

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.