Лучший способ перевести движение перетаскивания мыши в 3d вращение объекта

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

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

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

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

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

Более практичный выбор Quaternions (также), которые представляют собой четыре элементарных вектора. Эти четыре элемента определяют вращение и единую шкалу, и бывает, что если вы войдете и нормализуете вектор на единицу длины, вы получите масштабный коэффициент 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.

Ответ 3

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

trackball.h

trackball.c

Ответ 4

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

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

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