Лучший способ перевести движение перетаскивания мышью в 3d вращение объекта - PullRequest
15 голосов
/ 20 сентября 2008

У меня есть 3d-объект, который я хочу вращать в 3d. Самый простой способ состоит в том, чтобы напрямую перевести движение мыши X и Y во вращение вокруг осей Y и X, но если есть некоторое вращение вдоль обеих осей, то способ, которым поворачивается модель, становится крайне нелогичным (то есть, если вы перевернете объект на 180 градусов относительно одного ось, ваше движение вдоль другой оси меняется на противоположное).

Я мог бы просто сделать описанный выше метод, но вместо того, чтобы хранить величину вращения для вращения вокруг двух осей, я мог сохранить полную матрицу вращения и просто еще больше вращать ее по тем же осям для каждого перетаскивания мыши, но я обеспокоен что это быстро приведет к проблемам с точностью.

Ответы [ 4 ]

7 голосов
/ 20 сентября 2008

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

Существует относительно простой способ преобразования угла и трехмерный вектор, представляющий вращаемую ось в матрицу вращения.

Вы правы в том, что обновление необработанной матрицы вращения посредством инкрементных вращений приведет к тому, что матрица больше не будет чистой матрицей вращения. Это связано с тем, что матрица вращения 3x3 содержит в три раза больше данных, чем необходимо для представления вращения.

Более компактный способ представления поворотов - Углы Эйлера , имеющие минимальный вектор 3 значений. Вы можете взять текущее вращение в качестве вектора угла Эйлера, преобразовать его в матрицу, применить вращение (в инкрементном или ином виде) и преобразовать матрицу обратно в вектор угла Эйлера. Этот последний шаг естественным образом исключит любой невращающийся компонент в вашей матрице, так что вы снова получите чистую вращательную матрицу для следующего состояния.

Углы Эйлера концептуально хороши, однако для преобразования туда и обратно требуется много работы.

Более практичный выбор - Кватернионы ( также ), которые представляют собой четырехэлементные векторы. Четыре элемента определяют вращение и равномерный масштаб, и бывает, что если вы войдете и нормализуете вектор до длины единицы, вы получите масштабный коэффициент 1,0. Оказывается, что значение оси угла также можно очень легко преобразовать в значение кватерниона с помощью

q.x = sin(0.5*angle) * axis.x;
q.y = sin(0.5*angle) * axis.y;
q.z = sin(0.5*angle) * axis.z;
q.w = cos(0.5*angle);

Затем вы можете взять произведение кватернионов (которое использует только простое умножение и сложение) текущего кватерниона вращения и кватерниона инкрементного вращения, чтобы получить новый кватернион, представляющий выполнение обоих вращений. В этот момент вы можете нормализовать длину, чтобы обеспечить чистое вращение, но в противном случае продолжить итеративное объединение вращений.

Преобразование кватерниона в матрицу вращения очень просто (используется только умножение и сложение), когда вы хотите отобразить модель в повернутом состоянии с использованием традиционных графических API.

5 голосов
/ 20 сентября 2008

В моем курсе компьютерной графики нам дали следующий код, который позволил нам не изобретать велосипед.

trackball.h

trackball.c

4 голосов
/ 20 сентября 2008

Создайте матрицу аккумулятора и инициализируйте ее идентификатором.

Каждый кадр, примените это к вашему виду модели / состоянию матрицы мира перед рисованием объекта.

При движении мыши создайте матрицу вращения вокруг оси X с некоторой чувствительностью_константой * delta_x. Построить еще одну матрицу вращения вокруг оси Y для другого компонента. Умножьте одно, затем другое на аккумулятор.

Аккумулятор будет меняться при перемещении мыши. При рисовании он будет ориентировать объект так, как вы ожидаете.

Кроме того, человек, говорящий о кватернионах, прав; это будет хорошо выглядеть только для небольших дополнительных изменений. Если вы быстро перетащите его по диагонали, он не будет вращаться так, как вы ожидаете.

3 голосов
/ 20 сентября 2008

Вы можете справиться с потерей точности, перенормировав матрицу вращения, чтобы каждая из 3 строк снова была перпендикулярна. Или вы можете восстановить матрицу вращения, которую вы собираетесь изменить, основываясь на существующей информации об объекте, и это устраняет необходимость перенормировки.

В качестве альтернативы вы можете использовать кватернионов , который является альтернативой углам Эйлера для работы с вращениями.

Я узнал многое из этого в ранние годы от этого часто задаваемого вопроса , который занимается этой проблемой (хотя и для другого приложения) в Эйлера - это зло .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...