У меня есть Vector3, который имеет угол Эйлера для каждой оси.
Обычно, когда я хочу создать матрицу вращения, я буду использовать функции, такие как D3DXMatrixRotationX, передавая соответствующий угол из моего вектора вращения выше, и умножать матрицы (ZXY), чтобы создать общую матрицу вращения, которая используется для формирования полной матрицы преобразования объекта.
Однако этот метод будет производить набор поворотов в пространстве объектов. То есть передача вектора (90, 0, 90) в мой метод создаст вращение в мировом пространстве эффективно (90, 90, 0).
Есть ли способ всегда гарантировать, что каждый компонент моего вектора вращения приводит к вращению вокруг соответствующих осей, выровненных по пространству мира?
РЕДАКТИРОВАТЬ:
Это анимация происходящего в настоящее время - я хочу, чтобы способ вращался вокруг синих осей, а не красных.
РЕДАКТИРОВАТЬ 2:
Просто чтобы заметить, я не ищу решение, включающее углы Эйлера, а просто способ, которым я могу представить преобразование нескольких вращений вокруг мировых осей.
источник
Ответы:
Исходя из ваших комментариев, кажется, что вы сохраняете ориентацию объекта в виде набора углов Эйлера и увеличиваете / уменьшаете углы, когда игрок поворачивает объект. То есть у вас есть что-то вроде этого псевдокода:
Как отмечает Чарльз Битти , из-за того, что вращения не коммутируют, это не будет работать так, как ожидалось, если игрок не поворачивает объект в том же порядке, в котором
eulerAnglesToMatrix()
применяет вращения.В частности, рассмотрим следующую последовательность вращений:
В наивном представлении угла Эйлера, как реализовано в псевдокоде выше, эти повороты будут отменены, и объект вернется к своей первоначальной ориентации. В реальном мире этого не происходит - если вы мне не верите, возьмите шестигранный кубик или кубик Рубика, пусть x = y = 90 °, и попробуйте сами!
Решение, как вы заметили в своем собственном ответе , состоит в том, чтобы сохранить ориентацию объекта в виде матрицы вращения (или кватерниона) и обновить эту матрицу на основе пользовательского ввода. То есть вместо псевдокода выше вы бы сделали что-то вроде этого:
(Технически, так как любая матрица поворота или кватернионы может быть представлена в виде набора углов Эйлера, то есть их можно использовать для хранения ориентации объекта. Но физически правильное правило для объединения два последовательных поворотов, каждый из которых представлен в виде углов Эйлера, в одно вращение довольно сложно, и, по сути, сводится к преобразованию вращений в матрицы / кватернионы, умножению их, а затем преобразованию результата обратно в углы Эйлера.)
источник
Проблема с вращениями заключается в том, что большинство людей думают об этом с точки зрения углов Эйлера, поскольку их легко понять.
И все же большинство людей забывают, что углы Эйлера - это три последовательных угла . Это означает, что вращение вокруг первой оси сделает следующее вращение относительно первого первоначального вращения, поэтому вы не можете независимо вращать вектор вокруг каждой из трех осей, используя углы Эйлера.
Это напрямую переводит в матрицы, когда вы умножаете две матрицы, вы можете думать об этом умножении как о преобразовании одной матрицы в пространство другой матрицы.
Это должно происходить с любыми 3 последовательными вращениями, даже при использовании кватернионов.
Я хочу подчеркнуть тот факт, что кватернионы не являются решением для блокировки gimble. На самом деле блокировка будет всегда происходить, если вы представляли углы Эйлера с помощью кватернионов. Проблема не в представлении, проблема в 3 последовательных шагах.
Решение?
Решение для поворота вектора вокруг 3-х осей независимо состоит в объединении в одну ось и один угол, таким образом вы можете избавиться от шага, на котором вы должны выполнить последовательное умножение. Это будет эффективно переводить на:
Моя матрица вращения представляет результат вращения вокруг X, Y и Z.
а не эйлерова интерпретация
Моя матрица вращения представляет вращение вокруг X, затем Y, затем Z.
Чтобы прояснить это, я процитирую из теоремы Эйлера о вращении:
Обратите внимание, что умножение 3 матриц всегда будет представлять 3 последовательных поворота.
Теперь для того, чтобы объединить вращения вокруг 3 осей, вам нужно получить одну ось и один угол, который представляет вращение вокруг X, Y, Z. Другими словами, вам нужно использовать представление оси / угла или кватерниона, чтобы избавиться от последовательных поворотов.
Обычно это делается, начиная с начальной ориентации (ориентацию можно рассматривать как угол оси), обычно представляемой как кватернион или угол оси, и затем изменяя эту ориентацию, чтобы представить ориентацию назначения. Например, вы начинаете с кватерона идентификации, а затем поворачиваетесь на разницу, чтобы достичь ориентации назначения. Таким образом, вы не теряете никакой степени свободы.
источник
Переключение комбинации вращений из пространства объектов в мировое пространство тривиально: вам просто нужно изменить порядок, в котором применяются вращения.
В вашем случае вместо умножения матриц
Z × X × Y
вам просто нужно вычислитьY × X × Z
.Обоснование этому можно найти в Википедии: преобразование между внутренним и внешним вращением .
источник
Z
(пространство объекта), затем на 50 градусов вокругX
(пространство объекта), затем на 45 градусов вокругY
(пространство объекта). Это точно так же, как вращение на 45 градусов вокругY
( мировое пространство ), затем на 50 градусов вокругX
( мировое пространство ), затем на 50 градусов вокругZ
( мировое пространство ).Я предоставлю свое решение в качестве ответа, пока кто-нибудь не сможет объяснить, почему это работает.
При каждом рендеринге я перестраивал свой кватернион, используя углы, сохраненные в векторе вращения, а затем применял кватернион к своему окончательному преобразованию.
Однако, чтобы сохранить его вокруг мировых осей, мне пришлось сохранить кватернион по всем кадрам и вращать объекты только с разницей в углах, т.е.
(Многословно для читабельности)
Я думаю, что dsilva.vinicius пытался добраться до этой точки.
источник
Вам нужно будет хранить порядок поворотов.
Сохраните текущую матрицу вращения и предварительно умножьте каждый поворот по мере их поступления.
источник
В дополнение к ответу @ concept3d вы можете использовать 3 матрицы внешнего вращения для вращения вокруг оси в мировых координатах. Цитата из Википедии :
Так что вам нужно инвертировать порядок поворотов относительно того, что вы будете делать, используя внутренние (или локальные пространства) повороты. @Syntac попросил вращение zxy, поэтому мы должны сделать внешнее вращение yxz для достижения того же результата. Код ниже:
Объяснение значений матрицы здесь .
Этот код является дидактическим, а не оптимальным, поскольку вы можете использовать несколько матриц D3DXMATRIX.
источник