После стольких чтений о преобразованиях пришло время реализовать трекбол для моего приложения. Я понимаю, что должен создать вектор из источника, в который была нажата мышь, а затем другой из источника, из которого отпущена мышь.
Мой вопрос заключается в том, нужно ли преобразовывать (x, y) пиксельные координаты в мировые координаты или я должен просто делать все в пространстве изображения (учитывая, что пространство изображения - это 2D-проекция сцены, измеренная в пикселях)?
РЕДАКТИРОВАТЬ
Ответ Ричи Сэмса очень хороший. Тем не менее, я думаю, что я придерживаюсь немного другого подхода, пожалуйста, поправьте меня, если я ошибаюсь или неправильно что-то понимаю.
В моем приложении у меня есть SimplePerspectiveCamera
класс , который получает position
от камеры, position of the target
мы смотрим, в up
векторе fovy
, aspectRatio
, near
и far
расстояние.
Из них я строю свои матрицы просмотра и проекции. Теперь, если я хочу увеличить / уменьшить масштаб, я обновляю поле зрения и обновляю матрицу проекции. Если я хочу панорамировать, я перемещаю положение камеры и наблюдаю за дельтой, которую производит мышь.
Наконец, для поворотов я могу использовать либо преобразование оси угла, либо кватернионы. Для этого я сохраняю координаты пикселей, где была нажата мышь, а затем, когда мышь перемещается, я также сохраняю координаты пикселей.
Для каждой пары координат можно вычислить Z-значение дается формулой для шара, т.е. SQRT (1-х ^ 2-у ^ 2), а затем вычислить для векторов , которые идут от target
до PointMousePressed
и от target
до PointMouseMoved
, делает поперечный продукт чтобы получить ось вращения и использовать любой метод для расчета новой позиции камеры.
Однако мое самое большое сомнение заключается в том, что значения (x, y, z) приведены в пиксельных координатах, а при вычислении используемых мной векторов target
это точка в мировых координатах. Разве это смешивание системы координат не влияет на результат вращения, который я пытаюсь сделать?
z
значение сферы радиусаr
, однако я не уверен, живет ли эта сфера в мировом пространстве или пространстве изображений и каковы значения. Возможно, я обдумываю проблему.Ответы:
Предполагая, что вы имеете в виду камеру, которая вращается в зависимости от движения мыши:
Одним из способов его реализации является отслеживание положения камеры и ее вращения в пространстве. Сферические координаты удобны для этого, так как вы можете представлять углы напрямую.
Камера расположена в P, который определяется m_theta, m_phi и m_radius. Мы можем свободно вращаться и двигаться в любом месте, изменяя эти три значения. Однако мы всегда смотрим и вращаем m_target. m_target является локальным источником сферы. Однако мы можем свободно перемещать это происхождение в любое место в мировом пространстве.
Есть три основные функции камеры:
В простейших формах Rotate () и Zoom () тривиальны. Просто измените m_theta, m_phi и m_radius соответственно:
Панорамирование немного сложнее. Панорамирование камеры определяется как перемещение камеры влево / вправо и / или вверх / вниз относительно текущего вида камеры. Самый простой способ сделать это - преобразовать текущий вид камеры из сферических координат в декартовы. Это даст нам вверх и правильные векторы.
Итак, во-первых, мы конвертируем нашу сферическую систему координат в декартову, чтобы получить вектор взгляда . Далее, мы делаем векторное произведение с вектором вверх , чтобы получить правильный вектор. Это вектор, который указывает прямо справа от вида камеры. Наконец, мы делаем еще одно векторное перекрестное произведение, чтобы поднять вектор камеры .
Чтобы закончить кастрюлю, мы перемещаем m_target вдоль вверх и правых векторов.
Один вопрос, который вы можете задать: зачем все время конвертировать между декартовым и сферическим (вам также придется конвертировать, чтобы создать матрицу представления).
Хороший вопрос. У меня тоже был этот вопрос и я пытался использовать исключительно декартово. У вас возникают проблемы с вращением. Поскольку операции с плавающей запятой не совсем точны, многократные вращения приводят к накоплению ошибок, которые медленно соответствуют камере и непреднамеренно вращаются.
Итак, в итоге я застрял со сферическими координатами. Чтобы противостоять дополнительным вычислениям, я закончил кэшировать матрицу вида и вычислять ее только при движении камеры.
Последний шаг - использовать этот класс Camera. Просто вызовите соответствующую функцию-член внутри функций MouseDown / Up / Scroll вашего приложения:
Переменные m_camera * Factor - это просто масштабные коэффициенты, которые изменяют скорость вращения / панорамирования / прокрутки камеры.
Приведенный выше код представляет собой упрощенную версию системы камер с псевдокодом, которую я сделал для стороннего проекта: camera.h и camera.cpp . Камера пытается имитировать систему камер Майя. Код бесплатный и с открытым исходным кодом, поэтому не стесняйтесь использовать его в своем собственном проекте.
источник
В случае, если вы хотите взглянуть на готовое решение. У меня есть порт THREE.JS контроллеров TrackBall в C ++ и C #
источник