Опорный порядок матричных преобразований

Скажем, у меня есть синий 3D-бокс (где верхняя сторона красного цвета).

  • Теперь я вызываю glScalef (1, 10, 1).
  • Затем я вызываю glRotatef (90, 0, 1, 0).
  • Затем я выношу куб.

Я ожидал увидеть красную сторону, обращенную и вытянутую к экрану (вдоль оси Y модели).

Но что я вижу: Красная сторона обращена к экрану (как и ожидалось). Но растяжение происходит на оси Y пространства вида (а не на модели).

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

Что мне не хватает?

Ответы

Ответ 1

OpenGL считывает свои матрицы в так называемом column major порядке. В результате каждая последующая операция представляет собой предварительное умножение всех операций перед ним, а не пост-умножение. Таким образом, каждый последующий вызов операции OpenGL (glScale, glTranslate, glRotate) - это первая вещь, которая влияет на объект, и она идет в обратном порядке от того, как вы ее пишете.

Итак, вам нужно изменить порядок умножения:

glRotatef(90, 0, 1, 0); // Notice how this is the first operation ...
// ... but will be applied after
glScalef(1, 10, 1); // This will be applied first, but is the last operation
// Zany, right?

По правде говоря, он чувствует себя менее интуитивным, когда вы пишете программы и используете компьютер, чтобы указать вещи в обратном порядке. Но графические боги, которые будут решаться так, как они хотят, чтобы стек матрицы OpenGL вел себя (вместе с HLSL, GLSL и другими системами: см. Ссылку выше о порядке упорядочения столбцов).

Ответ 2

Если у вас есть массив, который представляет собой матрицу 4x4 следующим образом:

float mat[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

и вы загружаете это в матрицу OpenGL, OpenGL увидит первые 4 поплавков в качестве первого столбца матрицы, а второй 4 - как второй столбец, а третий 4 - как третий столбец матрицы и т. и др.

Итак, каждые 4 поплавка, OpenGL видит в качестве другого столбца. Это известно как порядок столбцов. Он хранит данные в столбцах. Если вам пришлось перенести матрицу с столбцом, она закончилась бы как матрица строк и наоборот.

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

Чтобы доказать это самому себе, возьмите простую матрицу 2x2 с вектором столбца 2x1, умножьте на M * v. Пусть K = транспонирование (M) и r = вектор строки (1x2).

Тогда   M * v= r * K

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