inquiro
offline
Опыт:
721Активность: |
Кватернион вращения
Может ли кто-нибудь доходчиво объяснить, что из себя представляет кватернион вращения и как можно его рассчитать (по каким формулам), исходя из угла поворота вокруг осей? Отредактировано inquiro, 27.11.2006 в 12:09. |
27.11.2006, 10:38 | #1
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Алексей
Где кошачья мята?!
offline
Опыт:
26,543Активность: |
И как этот вопрос относится к Warcraft'у?
Это скорее по 3D-графике. Кстати, в сети полно информации по кватернионам (хотя вся она, похоже, заимствована из одного источника - перевода Demo.Design FAQ, т.ч. там полно ошибок). Кватернион это (если не вдаваться в математические подробности) просто 4D-вектор: q=(x; y; z; w), подобранный так, что x*x+y*y+z*z+w*w=1 (это т.н. нормированный кватернион - именно их обычно и используют). Его можно также условно разбить на два компонента: векторный - v=(x; y; z) и скалярный - w. Чем удобен кватернион? Да тем, что позволяет очень просто работать с вращениями. Например, все операции с матрицами крайне ресурсоёмки (чего стоит, к примеру, нахождение обратной матрицы поворота!), а работа с углами Эйлера - вообще самый ненадёжный способ представления вращения. . Новички чаще всего (по себе знаю!) в своих программах реализуют вращение с помощью углов Эйлера - т.е. простых поворотов вокруг осей x,y,z. В "профессиональных" играх такой подход не используется, т.к.:
. Кватернион задаёт поворот не вокруг осей x,y,z, а вокруг любой, ПРОИЗВОЛЬНОЙ оси. Итак, если нужно повернуть сцену вокруг некоторого вектора с координатами (x;y;z) на угол A, то кватернион, осуществляющий такой поворот, можно вычислить так: q.x=x*Sin(A/2) q.y=y*Sin(A/2) q.z=z*Sin(A/2) q.w=Cos(A/2) Только потом важно не забыть нормировать кватернион - т.е. сделать так, чтобы выполнялось вышеуказанное правило - x*x+y*y+z*z+w*w=1 Это можно сделать, например, так: n=1/sqrt(q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w) q.x=q.x*n q.y=q.y*n q.z=q.z*n q.w=q.w*n Кватернионы хороши тем, что с ними очень легко работать. Например, их можно складывать (покомпонентно). Сумма кватернионов - это "смесь" тех поворотов, которые они задают. Т.е. конечный кватернион будет представлять некий усреднённый поворот. Кватернионы, как и матрицы, можно перемножать. Допустим, объект нужно повернуть сперва с помощью кватерниона A, затем - с помощью кватерниона B. Тогда поворот можно осуществить одной операцией, повернув объект кватернионом C=A*B. Произведение кватернионов не коммутативно, т.е. AB не равно BA. Перемножение кватернионов описывается довольно сложной формулой, но есть способы его ускорить - в сети полно "быстрых" методов умножения кватернионов. Вот, например, так можно вычислить произведение q1*q2: Код:
Метод кажется очень громоздким, т.к. требует от процессора выполнения 12 умножений и 35 сложений. Однако единственная альтернатива - перемножение матриц поворота - требует 27 умножений и 18 сложений. Учитывая, что на операцию сложения (и вычитания, которая тоже считается сложением ;) процессор тратит всего 1 такт, а умножение осуществляется за 4 такта, перемножение кватернионов будет быстрее умножения матриц (83 такта против 126 тактов). Более того: из этих 12 перемножений здесь есть 4 умножения на 0.5, которые вычисляются тоже за 1 такт. В результате перемножения нормированных кватернионов всегда получается нормированный кватернион. . Ну, а теперь - чуть ближе к сути вопроса. Допустим, нам нужно сперва повернуть объект вокруг оси X на угол A, затем - вокруг оси Y на угол B, и наконец - вокруг оси Z на угол C. Кватернион, задающий вращение, эквивалентное всем трём поворотам, можно вычислить так: qx.x=sin(A/2) qx.y=0 qx.z=0 qx.w=cos(A/2) qy.x=0 qy.y=sin(B/2) qy.z=0 qy.w=cos(B/2) qz.x=0 qz.y=0 qz.z=sin(C/2) qz.w=cos(C/2) q=qx*qy*qz ну, о перемножении кватернионов я уже говорил. Кстати, в DirectX (точнее, в D3dx9.lib) есть специальная функция для умножения кватернионов - D3DXQuaternionMultiply, хотя она работает не слишком быстро. Бесконечные преобразования поворотов (кватерниона в матрицу, углов Эйлера - в кватернион и др.) очень ресурсоёмки, т.к. используют тригонометрические функции и требуют кучи умножений. Поэтому в высокоскоростных 3D-приложениях (играх, например) все повороты нужно хранить единообразно - чтобы обходиться без преобразований. Где можно подробнее почитать о кватернионах? Ну, например, на Gamedev'е:
Отредактировано Алексей, 27.11.2006 в 12:58. |
27.11.2006, 12:24 | #2
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
NETRAT
offline
Опыт:
83,712Активность: |
Тему в трактир переношу ...
NETRAT добавил: Да, я повороты матрицами делал(просто не знал для чего кватернионы, благодаря тебе, знаю). Углы Эйлера, имхо - геморрой |
27.11.2006, 12:48 | #3
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
inquiro
offline
Опыт:
721Активность: |
ВАХ!... Сейчас у меня голова взорвется!
Давно я не брал в руки счеты... Цитата:
А вращение объектов (костей к примеру) разве не кватерионом задается? Если задавать поворот в mdl мощнейшим инструментом программирования 3D графики - блокнотом, то без этого не обойтись. Цитата:
Потому, что без стакана не разберешься?... СПАСИБО, Алексей!!! |
||
27.11.2006, 19:41 | #4
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
Q
offline
Опыт:
360,164Активность: |
inquiro вообще Алексей написал как раз MDLVis
|
27.11.2006, 19:51 | #5
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|
inquiro
offline
Опыт:
721Активность: |
Я знаю! СПАСИБО ему еще много раз! Я бы за это Алексея на руках поносил бы, но не знаю, где его взять... Отредактировано Q, 28.11.2006 в 23:28. |
27.11.2006, 20:33 | #6
+0/−0
Профиль |
Приват |
Поиск |
Цитата |
IP: Записан
|