OpenGL: понимание преобразования

Я пытался понять урок 9 из учебника NEHE, который о растровых изображениях, перемещаемых в трехмерном пространстве.

Самое интересное здесь — это перемещать 2d-текстуру растрового изображения на простом квадре через 3d-пространство и постоянно держать ее лицом к экрану (зрителю). Таким образом, растровое изображение выглядит трехмерным, но все время обращено к зрителю в двухмерном, независимо от того, где оно находится в трехмерном пространстве.

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

код для этого выглядит следующим образом: (следующий код вызывается для каждой звезды в цикле)

glLoadIdentity();
glTranslatef(0.0f,0.0f,zoom);
glRotatef(tilt,1.0f,0.0f,0.0f);
glRotatef(star[loop].angle,0.0f,1.0f,0.0f);
glTranslatef(star[loop].dist,0.0f,0.0f);
glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);
glRotatef(-tilt,1.0f,0.0f,0.0f);

После строк выше начинается рисование звезды. Если вы проверите последние две строки, вы увидите, что преобразования из строк 3 и 4 просто отменены (например, отмена). Эти две строчки в конце дают нам возможность все время показывать звезду лицом к зрителю. Но я не знаю, почему это работает.

И я думаю, что это происходит из-за моего непонимания того, как OpenGL действительно выполняет преобразования. Для меня последние две строки — это просто отмена того, что было сделано раньше, что для меня не имеет смысла. Но это работает.

Поэтому, когда я вызываю glTranslatef, я знаю, что текущая матрица представления умножается на значения перевода, предоставленные с помощью glTranslatef. Другими словами, "glTranslatef(0.0f,0.0f,zoom);" переместит место, где я собираюсь нарисовать свои звезды, если масштаб будет отрицательным. В ПОРЯДКЕ.

а ЧТО именно здесь перенесено? Зритель перемещается «от себя» или есть какая-то система координат объекта, которая перемещается в сцену с помощью glTranslatef? Что тут происходит?

Тогда glRotatef, что здесь повернуто? Опять система координат, сам зритель?

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

Мне не нужно добавлять остальную часть кода, потому что он довольно стандартный. Простая инициализация GL для 3D-рисунков, вращающихся вещей, а затем простое рисование QUADS со звездной текстурой с использованием смешивания. Вот и все.

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


person NovumCoder    schedule 04.03.2011    source источник
comment
В OpenGL принято вращать объект в начале координат, а затем переводить его туда, куда ему нужно. По сути, это имитирует вращение по «локальным координатам». Помните, что все это происходит в стеке, поэтому порядок имеет значение! Этот код сделает два поворота вокруг локальной оси объекта, затем переведет его, затем сделает еще два поворота и перевод (эффективно преобразуя мировые координаты).   -  person fjlksahfob    schedule 05.03.2011


Ответы (3)


Еще один способ представить стек gl-матрицы — пройтись по нему в обратном направлении от вызова отрисовки. В вашем случае, поскольку ваша ничья является последней строкой, давайте активируем код:

1) Сначала звезда вращается на -наклон вокруг оси X относительно начала координат.

2) Звезда поворачивается на -star[loop].angle вокруг оси Y относительно начала координат.

3) Звезда перемещается на star[loop].dist по оси X.

4) Звезда поворачивается на угол star[loop].angle вокруг оси Y относительно начала координат. Поскольку звезда больше не находится в начале координат из-за шага 3, это вращение одновременно перемещает центр звезды и вращает его локально.

5) Звезда вращается за счет наклона вокруг оси X относительно начала координат. (То же примечание, что и 4)

6) Звезда перемещается по оси Z на единицы масштабирования.

Хитрость здесь заключается в том, что сложно напечатать текст, но попробуйте изобразить последовательность ходов. Хотя шаги 2 и 4 могут показаться инвертирующими друг друга, перемещение между ними меняет характер вращения. Ключевой фразой является то, что вращения определяются вокруг начала координат. Перемещение звезды изменяет эффект вращения.

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

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

Второй вопрос, который вы задали, относится к тому, как ведет себя матрица камеры в типичной настройке OpenGL. Во-первых, разберитесь с концепцией координат экранного пространства (аналогично координатам устройства). Это пространство, которое на самом деле отображается. X и Y — векторы вашего экрана, а Z — глубина. Пространство обычно находится в диапазоне от -1 до 1. Перемещение объекта вниз по Z эффективно перемещает объект.

Камера (или матрица перспективы) обычно отвечает за преобразование «мирового» пространства в это экранное пространство. Эта матрица определяет «зрителя», но, в конце концов, это просто еще одна матрица. Матрица всегда применяется «последней», поэтому, если вы читаете преобразования вверх, как я описал ранее, камера обычно находится в самом верху, как вы и видите. В этом случае вы могли бы думать об этом последнем преобразовании (перевести на масштабирование) как на очень простую матрицу камеры, которая перемещает камеру назад на единицы масштабирования.

Удачи. :)

person Nick Gebbie    schedule 04.03.2011
comment
Отличный ответ. Спасибо, Ник. Пункт 4 в вашем комментарии интересен. Поскольку я перемещаю звезду в точке 3, поведение вращения меняется и звезда вращается локально. Просто визуализировал шаги, теперь это имеет смысл. Дааа. :-D - person NovumCoder; 05.03.2011
comment
Несколько лет я преподавал вводную графику. :) Добро пожаловать. - person Nick Gebbie; 05.03.2011

На glTranslatef в середине влияет вращение: он перемещает звезду вдоль оси x' на расстояние dist, а ось x' в это время поворачивается на ( наклон + угол ) по сравнению с исходным x ось.

В opengl у вас есть координаты объекта, которые умножаются на (стек) проекционную матрицу. Итак, вы перемещаете объекты. Если вы хотите «переместить камеру», вам нужно умножить на обратную матрицу положения и оси камеры:

ProjectedCoords = CameraMatrix^-1 . ОбъектМатрица. ОбъектКоорд

person fa.    schedule 04.03.2011

Я также нашел это очень запутанным, но я просто поиграл с частью кода NeHe, чтобы лучше понять glTranslatef() и glRotatef().

Мое текущее понимание состоит в том, что glRotatef() фактически вращает систему координат, так что glRotatef(90.0f, 0.0f, 0.0f, 1.0f) приведет к тому, что ось x будет там, где раньше была ось y. После этого поворота glTranslatef(1.0f, 0.0f, 0.0f) переместит объект на экране вверх.

Таким образом, glTranslatef() перемещает объекты в соответствии с текущим поворотом системы координат. Поэтому порядок glTranslatef и glRotatef важен в уроке 9.

С технической точки зрения мое описание может быть не идеальным, но оно работает для меня.

person Linus    schedule 22.03.2011