Как работает масштабирование, панорамирование и вращение?

Используя OpenGL, я пытаюсь нарисовать примитивную карту своего кампуса.

Может ли кто-нибудь объяснить мне, как обычно реализованы панорамирование, масштабирование и поворот?

Например, при панорамировании и масштабировании я просто настраиваю окно просмотра? Итак, я рисую и рисую все свои линии, составляющие мою карту, а затем, когда пользователь щелкает и перетаскивает, он настраивает мое окно просмотра?

При панорамировании сдвигает ли он значения x / y моего окна просмотра, а при масштабировании увеличивает / уменьшает мое окно просмотра на некоторую величину? А как насчет ротации?

Должен ли я выполнять аффинные преобразования для каждой полилинии, представляющей карту моего кампуса, для вращения? Разве это не будет дорого делать "на лету" на карте приличного размера?

Или область просмотра оставлена ​​прежней, а панорамирование / масштабирование / вращение выполняется каким-то другим способом?


Например, если вы перейдете по этой ссылке, вы увидите, что он описывает панорамирование и масштабирование точно так же, как я описал выше, путем изменения области просмотра.

Это не так?

Ответов (3)

Решение

Они достигаются путем применения серии команд glTranslate, glRotate (которые представляют положение и ориентацию камеры) перед рисованием сцены. (технически вы вращаете всю сцену!)

Существуют служебные функции, такие как gluLookAt, которые как бы абстрагируют некоторые подробности об этом.

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

gluLookAt принимает положение, пункт назначения и вектор вверх.

Если вы реализуете векторный класс, он destinaion = position + direction должен дать вам точку назначения.

Опять же, чтобы упростить задачу, вы можете предположить, что вектор вверх всегда равен (0,1,0)

Затем перед рендерингом чего-либо в вашей сцене загрузите единичную матрицу и вызовите gluLookAt

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt( source.x, source.y, source.z, destination.x, destination.y, destination.z, 0, 1, 0 );

Затем начните рисовать свои объекты

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

Одна проблема в том, что если у вас есть только вектор направления «вперед», как вы его перемещаете? где правое и левое?

Мой подход в этом случае - просто взять перекрестное произведение «направления» и (0,1,0).

Теперь вы можете перемещать камеру влево и вправо, используя что-то вроде:

position = position + right * amount; //amount < 0 moves to the left

Вы можете двигаться вперед, используя «вектор направления», но ИМО лучше ограничить движение горизонтальной плоскостью, поэтому получите вектор вперед так же, как мы получили правильный вектор:

forward = cross( up, right )

Если честно, это несколько хакерский подход.

Правильный подход - использовать более «сложную» структуру данных для представления «ориентации» камеры, а не только прямого направления. Однако, поскольку вы только начинаете, хорошо делать все по шагам.

Все эти «действия» могут быть выполнены с помощью функций преобразования матрицы представления модели. Вы должны прочитать о glTranslatef (панорамирование), glScalef (масштабирование), glRotatef (вращение). Вам также следует прочитать базовое руководство по OpenGL, эта ссылка может оказаться вам полезной.

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

Учитывая локальную точку

  • Местное -> Преобразование мира
  • Мир -> Преобразование камеры
  • Камера -> Преобразование экрана (обычно проекция. Зависит от того, используете ли вы перспективу или ортогональную)

Каждое из этих преобразований берет вашу трехмерную точку и умножается на матрицу.

Когда вы поворачиваете камеру, она обычно меняет мир -> преобразование камеры путем умножения матрицы преобразования на ваше аффинное преобразование поворота / панорамирования / масштабирования. Поскольку все ваши точки повторно визуализируются в каждом кадре, новая матрица применяется к вашим точкам, и это дает вид вращения.