То, что вы просите, называется ротацией Arcball. Кватернионы - это простое решение, только если вы понимаете, как они работают. Однако вы можете достичь того же самого без кватернионов.
Предпосылки
Вы знаете, как вращать объекты в целом? Допустим, у вас есть объект в начале координат. Знаете ли вы, как вы поворачиваете его (подсказка: умножьте на некоторую матрицу вращения)? Если да, то я предполагаю, что вы знаете, что произойдет, если вы сначала переведите объект, а затем поверните его?
Вы должны знать, как рассчитать матрицу вращения по оси угла (просто, как круговая диаграмма, посмотрите на множество онлайн-уравнений, многие из них также дают вам код)
Решение
- Получить камеры вверх и вправо векторов. Обратите внимание, что они должны быть нормализованы.
- Получить вектор от точки фокусировки на камеру (camPosition - Focus). Это вектор, который вы собираетесь вращать. Давайте назовем это camFocusVector .
- Решите, сколько вы хотите повернуть в рысканье / тангаже по отношению к камере
- Создайте две матрицы вращения. Матрица первого поворота будет использовать вверх камеры как оси и поворот вокруг вертикальной оси под углом , что вы решили. Матрица второго поворота будет использовать право камеры в качестве оси и тангажа угла , который вы решили.
- Теперь поверните camFocusVector с новыми матрицами вращения. Теперь это ваша новая позиция камеры относительно начала координат. Мы, конечно, хотим, чтобы это было относительно точки фокуса ...
- Добавьте положение точки фокусировки в camFocusVector . Теперь это новая позиция вашей камеры. Переведите свою камеру соответственно.
- Наконец, попросите камеру сфокусироваться на точке фокусировки, вызвав функцию lookAt ()
Предостережения
Вам придется следить за определенными случаями или особенностями, при которых ваша камера перестанет работать. Глядя прямо вниз / вверх, например. Я дам вам понять, как с этим справиться.
EDIT1: Как пересчитать ортонормированные векторы камеры
Вы уже знаете направление камеры ((cameraPos - focusPoint) .normalize ()). Теперь предположим, что у вашей камеры вверх + Y (или если текущая верхняя ось вашего мира ... это зависит от вас). Теперь просто пересечь направление с вверх , чтобы получить право . Выполнено? Нет! Ваш верхний вектор больше не является ортогональным к двум другим. Чтобы исправить это, перекрестное право с руководством , и вы получите ваш новый вверх .
Обратите внимание, что Грам-Шмидт действительно то, что следует использовать для ортонормирования векторов.
Опять же, обратите внимание на предостережения, так как в некоторых случаях это не сработает (например, направление параллельно вверх ).