1

так под GL_PROJECTION яв opengl Почему мы должны делать gluPerspective перед gluLookAt?

glu.gluPerspective(90,aspect,1,10); 
    glu.gluLookAt(0,0,3,0,0,0,0,1,0); 

это работает нормально, но когда я переключаю заказ я не получить какой-либо объект на моем экране, я повернута мою камеру и Нет ничего.

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

+2

Кроме того: 'GL_PROJECTION' должен иметь только проекционные преобразования, как преобразования модели, так и представления должны идти в' GL_MODELVIEW'. Хотя это сработает, это правильная вещь, это соглашение, которое следует соблюдать. – legends2k

+3

Что сказал @ legendends2k. Также включение преобразований просмотра в GL_PROJECTION вызовет проблемы, как только освещение вступит в сцену. – datenwolf

+0

[«Помогите вычеркнуть злоупотребление GL_PROJECTION.»] (Http://www.sjbaker.org/steve/omniv/projection_abuse.html) – genpfault

ответ

3

Чтобы увидеть объект на экране, вам нужно, чтобы он попадал в канонический объем представления, который для 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); хорошо за пределами видимого региона. Это потому, что геометрически последняя матрица сначала переводит, а затем масштабируется, а не масштабируется, а затем переводится. Переведенная шкала ведет к тому, что она полностью отключена.

+0

Благодарим вас за ваше мнение, я понимаю, что изменение порядка изменяет порядок умножения матрицы. Можно ли немного подробнее рассказать о том, почему он не попадает в каноническую точку зрения? (Я знаю, что P * V * M - правильный порядок, и изменение порядка дает неправильную матрицу, но что это за неправильная матрица, подразумевающая?) Спасибо – demalegabi

+0

Пожалуйста, проверьте обновленный ответ, который теперь содержит пример, чтобы сделать его понятным. – legends2k

3

В

glu.gluPerspective(90,aspect,1,10); 
glu.gluLookAt(0,0,3,0,0,0,0,1,0); 

случая, первая модель/мировые координатах (в R^3) преобразуется в координаты вида (также R^3). Затем проекция отображает координаты вида в перспективное пространство (P^4), которое затем уменьшается с точки зрения перспективы до координат NDC. В общем, как это должно работать.

Теперь посмотрим на:

glu.gluLookAt(0,0,3,0,0,0,0,1,0); 
glu.gluPerspective(90,aspect,1,10); 

Здесь мировые координаты проецируются непосредственно в проективном пространстве (P^4). Так как матрица lookAt является отображением из R^3 -> R^3, и мы уже находимся в P^4, это не сработает. Даже если бы можно было повернуть P^4, параметры gluLookAt должны были бы адаптироваться к диапазонам проективного пространства.

Примечание: В общем случае никогда не следует добавлять gluLookAt в стек GL_PROJECTION. Поскольку он описывает матрицу вида, он лучше подходит для стека GL_MODELVIEW. Для справки смотрите here.

Смежные вопросы