Чтобы увидеть объект на экране, вам нужно, чтобы он попадал в канонический объем представления, который для OpenGL, [-1, 1] во всех трех измерениях. Для преобразования объекта, вы грубо сделать
P»= Проекция × View × Model × P
где P'
является конечной точкой, которая должна быть в каноническом объеме, и P является начальным точка в пространстве модели. P преобразуется матрицей модели, за которой следует представление, а затем проекция.
Порядок, за которым я следил, - это вектор-столбец, где каждое последующее преобразование предварительно/слева-умножается. Другой способ прочитать ту же формулу - прочитать ее слева направо, где вместо преобразования точки система координат преобразуется, а интерпретация P
в преобразованной системе пространственно представляет собой P'
в исходной системе. Это еще один способ увидеть это, результат одинаковый в обоих случаях; так и пространственно.
Почему мы должны выполнять gluPerspective перед gluLookAt?
Старший, фиксированная функция трубопровод OpenGL разместить/правосторонним умножает и, таким образом, нуждается для того, чтобы быть отменено, чтобы получить тот же эффект. Поэтому, когда нам нужно LookAt и Перспектива далее, мы делаем обратное, чтобы получить ожидаемый результат.
Отдавая два в правильном порядке приводит к
P»= View × Проекция × Model × P
поскольку умножение матриц анти-коммутативной, вы не получите право P'
который попадает в объем канонического представления и, следовательно, черный экран.
См. Chapter 3, Red Book в разделе Команды преобразования общего назначения, в котором объясняется порядок, за которым следует OpenGL. Выдержка:
Примечание: Все умножение матриц с OpenGL происходит следующим образом: Предположим, что текущая матрица С и матрица указана с glMultMatrix *() или любого преобразования команд является М , После умножения конечная матрица всегда равна CM. Так как матричное умножение вообще не является коммутативным, порядок имеет значение.
Я хочу знать, почему первый случай работает, но второй не делает.
Чтобы узнать, что на самом деле происходит с матрицей, сформированной из неправильного порядка, позволяет сделать небольшую тренировку в 2D. Скажем, канонический вид региона [-100, 100] как в X, так и в Y; что-либо вне этого вырезано. Происхождение этого воображаемого квадратного экрана находится в центре, X идет вправо, Y идет вверх. Когда преобразование не применяется, вызов DrawImage
рисует изображение в начале координат. У вас есть изображение размером 1 × 1; его модельная матрица масштабируется на 200
, так что она становится изображением 200 × 200
; который заполняет весь экран. Поскольку начало координат находится в центре экрана, чтобы нарисовать изображение так, чтобы оно заполняло экран, нам нужна матрица вида, которая преобразует (перемещает) изображение (-100, -100). Формулируя этот
P»= View × Model = Перевести -100, -100 × Scale 200, 200
[ 200, 0, −100 ]
[ 0, 200, −100 ]
[ 0, 0, 1 ]
Однако, результат
Модель × Вид = S 200, 200 × T -100, -100
[ 200, 0, −20000 ]
[ 0, 200, −20000 ]
[ 0, 0, 1 ]
Умножив прежнюю матрицу с точками (0, 0) и (1, 1) привело бы к (-100, -100) и (100, 100), как и ожидалось. Угол изображения будет выровнен по углам экрана. Однако умножение последней матрицы на них приведет к (-20000, -20000) и (-19800, -19800); хорошо за пределами видимого региона. Это потому, что геометрически последняя матрица сначала переводит, а затем масштабируется, а не масштабируется, а затем переводится. Переведенная шкала ведет к тому, что она полностью отключена.
Кроме того: 'GL_PROJECTION' должен иметь только проекционные преобразования, как преобразования модели, так и представления должны идти в' GL_MODELVIEW'. Хотя это сработает, это правильная вещь, это соглашение, которое следует соблюдать. – legends2k
Что сказал @ legendends2k. Также включение преобразований просмотра в GL_PROJECTION вызовет проблемы, как только освещение вступит в сцену. – datenwolf
[«Помогите вычеркнуть злоупотребление GL_PROJECTION.»] (Http://www.sjbaker.org/steve/omniv/projection_abuse.html) – genpfault