Як я можу обертатись навколо довільної точки в 3D (замість початку)?


15

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

Усі афінні перетворення в моєму механізмі візуалізації / фізики зберігаються за допомогою SQT (шкала, кватерніон, переклад; ідея, запозичена з книги Game Engine Architecture .) Тому я будую матрицю кожного кадру з цих компонентів і передаю їх у вершину шейдера. У цій системі застосовується переклад, потім масштаб, потім обертання.

В одному конкретному випадку мені потрібно перевести об’єкт у світовий простір, масштабувати його та обертати його навколо вершини, не орієнтованої на місцеве походження об'єкта.

Питання: Враховуючи обмеження моєї поточної системи, описані вище, як я можу досягти локального обертання, орієнтованого на точку, відмінну від початку? Автоматичне оновлення для всіх, хто може описати, як це зробити, використовуючи лише матриці :)


Кватерніони вже описують обертання навколо довільної осі; у вас є проблеми з побудовою такого кватерніона з даних, які у вас є?
Мартін Сойка

3
Серйозно, чи могли люди, які підтримують відповіді, насправді їх прочитали ? Я дав метод, ефективну формулу і навіть демонстрацію. І все ж єдиний схвалений відповідь, надаючи цінну інформацію (а також явно неправильну інформацію), не містить жодної з них і навіть не відповідає на питання!
sam hocevar

@MartinSojka, це приблизно і довільна точка, а не довільна вісь.
notlesh

@SamHocevar Обидві ваші відповіді були корисними. Я вибрав вашу, тому що вона була більш ретельною і допомогла мені знайти рішення. Дякую вам обом.
notlesh

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

Відповіді:


17

Коротко

Потрібно лише змінити T у формі SQT.

Замініть вектор перекладу vтим, v' = v-invscale(p-invrotate(p))де vзнаходиться початковий вектор перекладу, pце точка, навколо якої ви хочете, щоб відбулося обертання, invrotateі invscaleє обертаннями обертання та масштабу.

Швидка демонстрація

Нехай pбуде точка, навколо якої ви застосовуєте обертання r. Нехай sбудуть ваші параметри масштабування та vваш перекладний вектор. Кінцеве перетворення матриці T(p)R(r)T(-p)S(s)T(v)замість R(r)S(s)T(v).

Те, що ви хочете, - це нові параметри перетворення v', r'і s'такі, що остаточне перетворення матриці - це R(r')S(s')T(v')і ми маємо:

T(p)R(r)T(-p)S(s)T(v) = R(r')S(s')T(v')

Поведінка у нескінченності вказує на те, що параметри обертання та параметри масштабування не можуть змінюватись (це можна було продемонструвати). Таким чином у нас є r = r'і s = s'. Тому єдиним відсутнім параметром є v'ваш новий вектор перекладу:

T(p)R(r)T(-p)S(s)T(v) = R(r)S(s)T(v')

Якщо ці матриці рівні, їх обертання рівні:

T(-v)S(-s)T(p)R(-r)T(-p) = T(-v')S(-s)R(-r)

Особливо це стосується походження O:

T(-v)S(-s)T(p)R(-r)T(-p)O = T(-v')S(-s)R(-r)O

Масштабування та обертання походження дають початок, при цьому отримують:

T(-v)S(-s)T(p)R(-r)(-p) = -v'

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


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

Виправте мене, якщо я помиляюся, але здається, що іншим рішенням було б зберігати ваш Quaternion як звичайний, і якщо вам потрібно врахувати переклад навколо довільної точки / осі, тоді побудуйте матрицю Q з цією включеною, просто витягніть вектор перекладу з цієї матриці (зазвичай останній стовпець) і додайте її до вектора перекладу об'єктів, а потім викиньте свою тимчасову матрицю.
johnbakers

15

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

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

Але якщо замість цього ви хотіли обернути його навколо правого верхнього кута (розташованого в 1,1), то спочатку слід перекласти його так, щоб цей кут був у витоку. Це можна досягти за допомогою перекладу -1,-1. Потім ви можете обертати об'єкт, як і раніше, але ви повинні слідувати за цим, перекладаючи його назад (на 1,1). Таким чином, для досягнення матриці обертання Rдля обертання rприблизно точки Pви зробите:

R = translate(-P) * rotate(r) * translate(P)

де translateі rotateє канонічні матриці перекладу / обертання відповідно. Як це буває, це масштабується тривіально до 3D, за винятком того, що потрібно також подавати вісь до обертання - ви можете завжди завжди вибирати канонічні матриці обертання осі X, Y або Z, але це було б тьмяно. Вам потрібно використовувати матрицю обертання довільної осі-кута . Таким чином, ваш фінал Rу 3D - це:

R = translate(-P) * rotate(a,r) * translate(P)

де aє одиничним вектором, що представляє вісь обертання, і Pтепер є 3D-точкою в просторі моделі, що представляє точку обертання.

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

Також:

Тому я візуалізую це як обертання навколо вектора, хвіст якого розташований не за місцевим початком.

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


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

Він ідеально вписується у ваші обмеження. Матриця R (виготовлена ​​як перекладати-повертати-перекладати-назад) - це ваша матриця обертання. Замініть Q на R у вашій системі "SQT", щоб у вас з'явилася більш поширена парадигма масштабу повернути-перекласти, і ви закінчите. Останній переклад не залежить від двох проміжних перекладів, зроблених для створення бажаного обертання.

Ви пропонуєте замінити кватерніон матрицею? Це ще 12 байт на об’єкт (8, якщо я зберігаю його як матриця 4x3)! Я все ж замовчу оптиміста в мені і дам цьому вир. (Це насправді, можливо, навіть не збільшиться на 2 кб збільшення площі…) Дякую за ваші відповіді.
нотлеш

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

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