Використання кватерніонів: Що я можу зробити з ними? (без математики)


24

Я розробник ігор і не вивчав математику. Тому я хочу лише використовувати кватерніони як інструмент. І щоб мати можливість працювати з 3D-обертанням, необхідно використовувати Quaternions (або матриці, але давайте зупинимось на Quaternions тут, у цьому запитанні). Я думаю, що багатьом розробникам важливо використовувати їх. Тому я хочу поділитися своїми знаннями і сподіваюся заповнити дірки, які у мене є. Тепер….

Наскільки я зрозумів:

Кватерніон може описати 2 речі:

  1. Поточна орієнтація 3d-об’єкта.
  2. Перетворення обертання, яке може зробити Об'єкт. (обертанняЗміна)

Ви можете зробити з кватерніоном:

Множення:

  1. Quaternion endOrientation = Обертання QaternionChange * Quaternion currentOrientation;

    Так, наприклад: Мій 3D-об'єкт повернутий на 90 ° вліво - і моє обертання, яке я множу, - це обертання на 180 ° вправо, врешті-решт мій 3D-об’єкт на 90 ° повернутий праворуч.

  2. Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    Цим ви отримуєте обертанняChange, яке можна застосувати до іншої Орієнтації.

  3. Vector3 endPostion = Обертання четвертинного Змінити * Vector3 currentPosition;

    Так, наприклад: Мій 3D-об’єкт знаходиться в положенні (0,0,0), а обертання, яке я помножую, - це обертання на 180 ° вправо, моя кінцева позиція - це щось на зразок (0, -50,0). Всередині цього Кватерніона є вісь - і обертання навколо цієї осі. Ви повертаєте точку навколо цієї осі Y градусів.

  4. Vector3 rotatoOffsetVector = Обертання четвертинного Змінити * Vector3 currentOffsetVector;

    Наприклад: Мій напрямок початку показує вгору - (0,1,0), а обертання, яке я множу, - це поворот на 180 ° вправо, мій кінцевий напрямок показується вниз. (0, -1,0)

Змішування (Lerp і Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)

    якщо інтерполятор дорівнює 1: currentOrientation = endOrientation

    якщо інтерполятор дорівнює 0: currentOrientation = startOrientation

    Серпп інтерполює точніше, Лерп інтерполює більш ефективно.

Мої питання:

Чи правильно все, що я пояснив дотепер?

Це "все", що ви можете зробити з кватерніонами? (звичайно не)

Що ще можна зробити з ними?

Для чого хороший продукт Dot та продукт Cross між двома кватерніонами?

Редагувати:

Оновлено запитання з деякими відповідями


Скажімо, у вас не 2, а nрізні орієнтації (ставлення, пози тощо). Тоді ви можете їх порівняти за допомогою ваг, ефективно узагальнюючи slerp / lerp. Ви також можете перетворити кватерніон у ротор, що еквівалентно застосуванню кутової швидкості протягом певного часу до жорсткого тіла. Отже, ви можете описати інтеграцію кутових швидкостей також з кватерніонами. Ви також можете оцінити, наскільки дві орієнтації відрізняються (обчисліть довжину дуги, що охоплюється двома кватерніонами на гіперсфері).
теодрон

І так, на перший погляд, ваше обгрунтування правильне (ваше розуміння кватерніонів цілком добре для нетехнічної людини). Це не підходить для коментаря, але вітаю! Навіть технічно обдаровані не знають усіх застосувань кватерніона, хоча вони використовують їх як інструменти інженерії програмного забезпечення для певної мети.
теодрон

4
"І щоб мати можливість працювати з 3D-обертанням, необхідно використовувати Quaternions". Я не можу наголосити, наскільки помилковим є це речення. Для розробки ігор можна використовувати кути Ейлера або Тайт-Брайана, єдина проблема - це фіксація карданчика. Якщо ви хочете бути розробником гри, вам знадобиться математика в один момент, вивчіть її.
Балінт

1
"розробник ігор" і "не вивчає математику" - це оксиморон.
Маргарет Блум

2
Я ціную те, що ви намагаєтесь зробити з питанням, але відповіді повинні бути у відповіді, а не в питанні. Складіть "резюме" відповідь, якщо ви вважаєте, що варто їх зіставити.
Основні

Відповіді:


23

Множення

Принаймні з точки зору реалізації Unity Quaternions, порядок множення, описаний у запитанні, не є правильним. Це важливо, оскільки обертання 3D не є комутативним .

Отже, якщо я хочу обертати об'єкт, rotationChangeпочинаючи з його, currentOrientationя напишу його так:

Quaternion newOrientation = rotationChange * currentOrientation;

(тобто. Перетворення складаються вліво - те саме, що і матрична конвенція Unity. Найправіше обертання застосовується спочатку / на "найбільш локальному" кінці)

І якби я хотів перетворити вектор напрямку чи зміщення обертанням, я б написав це так:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity створить помилку компіляції, якщо ви зробите навпаки)

Змішування

У більшості випадків ви можете піти від обертів Лерпінга. Це тому, що кут, що використовується «під капотом» у кватерніоні, - це половина кута повороту, що робить його істотно ближчим до лінійного наближення Лерпа, ніж щось подібне до Матриці (що взагалі не буде Лерпа добре!). Перегляньте приблизно 40 хвилин цього відео, щоб отримати додаткові пояснення .

Єдиний випадок, коли вам дійсно потрібен Slerp, це коли вам потрібна послідовна швидкість у часі, як інтерполяція між ключовими кадрами на часовій шкалі анімації. У випадках, коли вам просто важливо, щоб вихід був проміжним між двома входами (наприклад, змішування шарів анімації), зазвичай Lerp служить досить добре.

Що ще?

Скалярний твір двох одиничних кватерніонів дає косинус кута між ними, так що ви можете використовувати продукт крапки в якості міри схожості , якщо вам потрібно порівняти ротацію. Це трохи незрозуміло, тому для більш розбірливого коду я часто використовую Quaternion.Angle (a, b) замість цього, що більш чітко виражає, що ми порівнюємо кути, у знайомих одиницях (градусах).

Такі типи зручностей, які Unity забезпечує для Quaternions, дуже корисні. Майже в кожному проекті я використовую цей принаймні кілька разів :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

Це створює кватерніон, який:

  • обертає локальну вісь z +, щоб вказувати точно вздовж forwardвекторного аргументу
  • обертає локальну вісь y +, щоб вказувати якомога ближче до upвекторного аргументу, якщо він наданий, або до того, (0, 1, 0)якщо його не було

Причиною "вгору" стає "як можна ближче" є те, що система переопределена. Облицювання z + до forwardвикористання двох ступенів свободи (тобто позіхання і крок), тому у нас залишається лише один ступінь свободи (рулон).

Мені досить часто здається, що я хочу щось із властивостями, що мають протилежну точність: я хочу, щоб локальний y + вказував точно уздовж up, а локальний z + максимально наблизився до forwardрешти свободи.

Це з'являється, наприклад, при спробі сформувати відносно камери координатний кадр для введення руху: я хочу, щоб мій локальний напрямок вгору залишався перпендикулярним до підлоги чи похилої поверхні нормальним, тому мій вхід не намагається тунель персонажа на місцевість або левити їх від цього.

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

Ми можемо створити власну функцію зручності для цього, використовуючи LookRotationдля важкого підйому:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

Тут ми спочатку обертаємо локальні y + to z +, а локальні z + to y-.

Тоді ми повертаємо новий z + до нашого напрямку вгору (таким чином, чистий результат є локальним y + точок прямо вздовж exactUp), а новий y + максимально наближений до запереченого напрямку вперед (тому чистий результат є локальним z + точок, як можна ближче уздовж approximateForward)

Ще один зручний метод зручності Quaternion.RotateTowards, який я часто використовую так:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

Це дозволяє нам увімкнутись targetRotationіз послідовною, керованою швидкістю незалежно від частоти кадрів - важливо для обертів, які впливають на результат / справедливість механіки ігрового процесу (як, наприклад, повернення руху персонажа чи відстеження башти гравця). Наївно Лерпінг / Сперпінг у цій ситуації може легко призвести до випадків, коли рух стає сприятливішим у високих рамках, впливаючи на ігровий баланс. (Це не означає, що ці методи неправильні - є способи їх правильного використання, не змінюючи справедливості. Це просто вимагає обережності. RotateTowardsДає зручний ярлик, який береться за це для нас)


Порада: Додайте & t = 40 м до кінця URL-адреси відео, щоб воно переходило прямо там (необов'язково, наприклад, 40m5s). Точкові вироби з кватерніона дуже корисні і при роботі з сферичними ігровими світами - або в більш широкому плані при орієнтації на шматки обертових сфер.
Люк Бріггс

@Luke Briggs: Світова точка сферичної гри звучить так, що варто було б детальніше розібратися у власній відповіді (особливо з діаграмами), якби ви її вирішили. :)
DMGregory

Чудова ідея - це 3 ранку тут (тому я думаю, що вийшло б трохи хитрості!), Але я б радий щось завтра зібрати (якщо я пам’ятаю!)
Люк Бріггс

1
Редагувати: Я трохи захопився думкою про відповідь, щоб прийняти виклик! Я, принаймні, відзначу це грубим розрізом, щоб люди могли знати про опік пізньої ночі, який потрапив у нього: P
Люк Бріггс

Там ми йдемо! Я спробував розкрити це в сенсі графічного огляду, виходячи з того, що ваша відповідь дуже добре охоплює основні функції. Я думаю, що час для сну!
Люк Бріггс

14

Де використовується точковий продукт?

В Unity, один з найпоширеніших користувачів точкового продукту - це кожен раз, коли ви перевіряєте, чи два кватерніона рівні через ==або !=. Unity обчислює точковий продукт для перевірки подібності, а не безпосередньо порівняння внутрішніх значень x, y, z, w. Варто пам’ятати про це, оскільки це робить дзвінок дорожчим, ніж можна було очікувати.

Ми також використовуємо його в цікавому випадку використання ..

Весело з продуктами з кватерніонними крапками - сферичними світами та орбіталями

Симуляції цілих планет і навіть цілих сонячних систем стають все більш поширеними. Для того, щоб зняти це в режимі реального часу, нам також потрібен точковий продукт кватерніона. Багато їх. Продукт з кватерніонним крапкою дуже використовується, але він, безумовно, має своє використання - Погляньмо!

По-перше, у нас є цілий ряд обертів:

  1. (За бажанням) Зірка навколо галактичного центру
  2. Планета навколо зірки
  3. Нахил планети
  4. Спініт планети
  5. Положення прилеглих клітин сітки (обертається навколо ядра планет) *
  6. Кілька орбітальних площин

Об'єднайте їх усі разом, і ви закінчитесь з великою складністю (і з величезною кількістю!). Коли глядач стоїть на поверхні планети, ми не хочемо, щоб вони нападали з якоюсь шаленою швидкістю через наш простір ігрового світу. Насправді ми хотіли б, щоб вони були нерухомими, а десь поблизу від джерела - замість цього переміщували Всесвіт навколо гравця.

Обертається планета

Важливо, що для того, щоб ми могли отримати правильний відкат і нахил планети в цьому сценарії, нам потрібно зафіксувати вісь полюса, щоб він міг лише гойдатися вгору / вниз по зображенню вгорі (тобто гойдатися "вгору", коли гравець подорожує північ). Ось тут і потрапляє крапковий продукт кватерніона. Якщо ми тут не використали крапковий продукт, а натомість просто помножили нахил, це станеться:

Невірно нахилена "планета"

Зверніть увагу, як полюси наших «планет» на орбіті завжди нахиляються до зірки. Це не те, що відбувається насправді - нахил у фіксованому напрямку .

Не надто далеко за темою, ось короткий підсумок:

  • На кулі орієнтація також акуратно описує положення поверхні.
  • У нас є багато обертань, щоб поєднати разом.
  • Охарактеризуйте все як обертання; позиція глядача теж. Це допомагає підвищити продуктивність, оскільки в кінцевому підсумку ми робимо менше операцій.
  • Кут між обертаннями (наш точковий виріб) допомагає вимірювати довготу і особливо добре справляється з нахилами.

Отримавши лише кут, ми скидаємо частину цього небажаного обертання . У той же час ми також закінчили вимірювання довготи, що корисно для навігації, а також місцевого клімату.

* Планети побудовані з безлічі осередків сітки . Насправді відображаються лише найближчі.


2
Це чудова робота, що створює сцену та мотивує проблему, але я все ще трохи нечіткий щодо того, як математика кватерніону крапкового продукту (тобто скалярний продукт dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wна відміну від кватерніонної композиції, яку ми використовуємо для з’єднання ланцюгів обертання) допомогли б нам вирішити цю проблему. Я з задоволенням підкажу, якщо ви зможете детальніше розібратися з цим пізніше (я не маю на увазі, щоб утримати вас від вашого серпа ... Я маю на увазі сон!)
DMGregory

@DmGregory коротка відповідь є нахилом - непарна; все складається добре, за винятком тієї (планета, здавалося б, коливається навколо своєї зірки в іншому випадку). Я завтра (сподіваюся!) Додамо ще трохи контексту!
Люк Бріггс

@DMGregory Я додав додаткову інформацію (я не міг спати!) - сподіваємось, це стане зрозумілішим.
Люк Бріггс

1
Вибачте, якщо я трохи щільний, але після перечитування декількох разів я все ще не знаю, як би я використав точковий продукт у формулі, щоб досягти перетворення, яке ви описуєте. Чи зможете ви додати трохи псевдокоду, викладаючи операції, які виконуються явно?
DMGregory

@DMGregory Я не знайомий з кватерніонами, але якщо це обертання на кулі, то це не композиції обертання. Для цього використовується сферична геометрія з векторами для обчислення нормального вектора для "лінії" на поверхні сфери AKA будь-якої окружності. Знову ж таки, відповідь має мало сенсу, а також це питання, але я вважаю, що вони використовують сферичну геометрію.
Велика качка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.