Як вирішується проблема фіксованого перемикання за допомогою накопичувальних матричних перетворень


12

Я читаю онлайн-книгу "Навчання сучасного 3D-графічного програмування" Джейсона Л. Маккесона

На сьогоднішній день я вирішував проблему блокування карданних виробів і як її вирішити за допомогою кватерніонів.

Однак тут, на сторінці Кватерніонів .

Частина проблеми полягає в тому, що ми намагаємось зберігати орієнтацію у вигляді серії з 3 накопичених осьових обертів. Орієнтації - це орієнтації, а не обертання. І орієнтації - це, звичайно, не ряд обертів. Тому нам потрібно ставитися до орієнтації корабля як до орієнтації, як до конкретної кількості.

Я думаю, що це перше місце, яке я починаю плутати, причина в тому, що я не бачу різкої різниці між орієнтаціями та обертаннями. Я також не розумію, чому орієнтація не може бути представлена ​​рядом обертів ...

Також:

Першою думкою до цієї мети було б зберегти орієнтацію як матрицю. Коли настає час змінити орієнтацію, ми просто застосуємо перетворення до цієї матриці, зберігаючи результат як нову поточну орієнтацію.

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

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

Ось код:

void display()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glutil::MatrixStack currMatrix;
    currMatrix.Translate(glm::vec3(0.0f, 0.0f, -200.0f));
    currMatrix.RotateX(g_angles.fAngleX);
    DrawGimbal(currMatrix, GIMBAL_X_AXIS, glm::vec4(0.4f, 0.4f, 1.0f, 1.0f));
    currMatrix.RotateY(g_angles.fAngleY);
    DrawGimbal(currMatrix, GIMBAL_Y_AXIS, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f));
    currMatrix.RotateZ(g_angles.fAngleZ);
    DrawGimbal(currMatrix, GIMBAL_Z_AXIS, glm::vec4(1.0f, 0.3f, 0.3f, 1.0f));

    glUseProgram(theProgram);
    currMatrix.Scale(3.0, 3.0, 3.0);
    currMatrix.RotateX(-90);
    //Set the base color for this object.
    glUniform4f(baseColorUnif, 1.0, 1.0, 1.0, 1.0);
    glUniformMatrix4fv(modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));

    g_pObject->Render("tint");

    glUseProgram(0);

    glutSwapBuffers();
}

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

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

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

Ось чому химерний замок відбувається правильно? Це тому, що ми обертаємо об'єкт навколо осей X, Y і Z, а не обертаємо об'єкт навколо власних відносних осей. Або я помиляюся?

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

Отже, підсумовуючи:

  • Яка різниця між обертанням і орієнтацією?
  • Чому код пов'язаний не в прикладі накопичення матричних перетворень?
  • Яке справжнє, конкретне призначення матриці, якщо я помилився?
  • Як можна було б реалізувати вирішення проблеми фіксації каркаса за допомогою накопичення матричних перетворень?
  • Також як бонус: Чому перетворення після обертання все ще відносяться до "простору моделі?"
  • Ще один бонус: чи помиляюсь у припущенні, що після перетворення відбудуться подальші перетворення відносно струму?

Крім того, якщо це не малося на увазі, я використовую OpenGL, GLSL, C ++ та GLM, тож приклади та пояснення з точки зору цього високо оцінюються, якщо не потрібно.

Чим більше деталей, тим краще!

Заздалегідь спасибі.

Відповіді:


11

Я не впевнений у хорошому способі передмови цього, окрім того, як я сподіваюся, це добре поєднається до кінця. Це сказало, давайте зануримось у:

Обертання та орієнтація відрізняються тим, що перша описує перетворення, а друга описує стан. Обертання - це те, як об’єкт потрапляє в орієнтацію , а орієнтація - локальний обертовий простір об'єкта . Це може бути безпосередньо пов'язано з тим, як вони представлені математично: матриця зберігає перетворення з одного простору координат в інший (у вас це було правильно), а кватерніон безпосередньо описує орієнтацію. Матриця, отже, може описувати лише те, як об’єкт потрапляє в орієнтацію , через ряд обертів. Проблема в цьому, однак, полягає у фіксації Gimbal.

Гимбальний замок демонструє труднощі приведення об'єкта в орієнтацію за допомогою серії обертів. Проблема виникає, коли принаймні дві осі обертання вирівнюються:

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

Зараз я фактично скептично ставлюсь до накопичення матриць як до повного рішення цього питання, адже накопичувальні матриці (тому накопичувальні обертання) - саме те, що може спричинити проблему блокування Gimbal в першу чергу. Правильним способом обробки перетворення кватерніоном є виконання мультиплікації кватерніона в точці:

pTransformed = q * pAsQuaternion * qConjugate

або перетворення кватерніона в матрицю і перетворення точки за допомогою цієї матриці.

Просте обертання матриці (наприклад, 45-градусне проникнення) завжди визначатиметься в глобальному просторі. Якщо ви хочете застосувати перетворення в локальному просторі, вам доведеться перетворити трансформацію в локальний простір цих об'єктів. Це звучить дивно, тому я докладно докладу. Ось тут важлива порядок обертів. Я рекомендую захопити тут книгу, щоб ви могли слідувати за перетвореннями.

Почніть з плоскої книги, її обкладинка звернена до стелі, орієнтована так, ніби ви збираєтесь її відкрити і почати читати. Тепер нахиліть лицьову сторону книги на 45 градусів (передня панель повинна приблизно бути спрямована до вас):

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(45);

Скажімо, ви хотіли відрегулювати поворот книги на 45 градусів (я думаю, я припускаю праворучну систему координат, тому це буде змінювати заголовок вліво), і ви хочете, щоб це стосувалося місцевої книги координуйте простір, щоб обкладинка книги все ще стикалася з вами:

bookMatrix.RotateY(45);

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

glutil::MatrixStack bookMatrix;
bookMatrix.RotateY(45);
bookMatrix.RotateX(45);

Спробуй! Повторіть книгу обличчям до стелі знову. Змініть її позіхання на 45 градусів, а потім наведіть його на 45 градусів уздовж глобальної осі X (працює зліва направо). Ця орієнтація ви очікували з кроком 45 та позіском 45 у локальному просторі книги.

Що це означає? Все, до чого насправді зводиться, - це порядок проведення операцій. Трансформації, зроблені спочатку, стають локальними перетвореннями в контексті трансформацій, що здійснюються після цього. Це стає багато, щоб обернути голову, і саме так кватерніони рятують багато неприємностей. Пропустіть усі матеріали, що залежать від замовлення.

Інша величезна перевага, яку надають кватерніони, - це те, що вони дозволяють здійснювати інтерполяцію орієнтацій. Спроба інтерполяції між кутами Ейлера майже неможлива через залежність від порядку. Математичні властивості кватерніона дозволяють чітко визначити сферичну лінійну інтерполяцію між ними.

Щоб підвести підсумки та вирішити своє первісне питання: перетворення накопичувальної матриці дійсно не вирішать проблему блокування Gimbal, якщо тільки перетворення не будуть ретельно вибрані та застосовані в точному порядку. Тому завжди використовуйте кватерніони та застосовуйте кватерніони до точок, використовуючи кватерніон множення.

Сподіваюся, це допомагає :)


4
тільки для запису, кватерніони все ще можуть ввести карданний замок, якщо це описано через кути Ейлера; як ви будете робити один і той же розрахунок по-іншому (кватерніони, а не матриці)
concept3d

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

кватерніони важко уявити, як я завжди думаю про це, що вони (одиничні кватерніони) представляють 3-сферовий простір, отже, вони можуть представляти будь-яку орієнтацію, тоді як я розумію кути Ейлера кожен представляють кола / туро, отже, це не повна сфера не дуже точний спосіб представити орієнтацію (3 кола / тору не можуть реально генерувати всі можливі орієнтації, якщо вони не обертаються незалежно, що неможливо у випадку кутів ейлера), не впевнений, чи я пояснив точно :)
concept3d

1

Матричні накопичення можуть насправді вирішити замок Gimbal. Нагромаджуючи обертання, ви додаєте карданчики, дозволяючи будь-яке довільне обертання. Діаграма, яку надав ktodisco, показує фіксацію каркаса на лівій схемі. Матрицю для цієї орієнтації можна визначити як:

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(90);
bookMatrix.RotateY(90);
bookMatrix.RotateZ(90);

Через обертання y gimbal, X і Z гімбали тепер заблоковані, тому ми втратили один ступінь руху. На даний момент у нас немає позіхання (локальне y, глобальне z) за допомогою цих трьох кардан. Але, додавши ще один кардан, я можу обертатися локально навколо y:

glutil::MatrixStack bookMatrix;
bookMatrix.RotateX(90);
bookMatrix.RotateY(90);
bookMatrix.RotateZ(90);
bookMatrix.RotateY(90);

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

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