Расчет матрицы LookAt

Я пишу 3D-движок и наткнулся на алгоритм LookAt, описанный в документации DirectX:

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1

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

Вопрос в том, зачем это нужно делать? Что это дает?


person Daemin    schedule 08.12.2008    source источник
comment
Прочтите материалы на msdn.microsoft.com/ en-au / library / bb206269 (VS.85) .aspx   -  person Daemin    schedule 09.12.2008
comment
Обратите внимание, что это основная строка, левосторонний взгляд на матрицу   -  person bobobobo    schedule 23.07.2011
comment
буква L (l) в правом нижнем углу должна быть единицей (1)   -  person vidstige    schedule 20.12.2017
comment
@bobobobo Это основная матрица столбца, потому что перевод находится внизу, а не справа. основной столбец является стандартом в GLSL.   -  person Crouching Kitten    schedule 21.06.2020
comment
@CrouchingKitten в матрице основного преобразования столбца компоненты перевода находятся с правой стороны - см. Сводка на странице scratchapixel.com/lessons/   -  person bobobobo    schedule 22.06.2020
comment
@bobobobo На этой странице предполагается, что основные столбцы / строки являются математическими понятиями, но это не так. Вместо этого они рассказывают, как одномерный массив интерпретируется как матрица. OpenGL всегда интерпретирует массив по столбцам. Код из OP был скопирован со страницы Microsoft, и он не отображает матрицу. Он показывает массив, разбитый на несколько строк. Столбец major переворачивает его (так что перевод будет справа в интерпретации OpenGL), в то время как row-major сохраняет его в том виде, в каком он написан в коде, внизу.   -  person Crouching Kitten    schedule 22.06.2020


Ответы (8)


Я строю обзорную матрицу, создавая матрицу вращения 3x3, как вы сделали здесь, а затем расширяю ее до 4x4 с нулями и единственной единицей в правом нижнем углу. Затем я строю матрицу трансляции 4x4, используя отрицательные координаты точки взгляда (без скалярных произведений), и умножаю две матрицы вместе. Я предполагаю, что это умножение дает эквивалент скалярных произведений в нижней строке вашего примера, но мне нужно будет проработать это на бумаге, чтобы убедиться.

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

person Judge Maygarden    schedule 09.12.2008
comment
Разве вы не должны создавать матрицу обзора, вычисляя матрицу обратного мира ориентации камеры? - person xcrypt; 25.01.2012
comment
@xcrypt Вы имеете в виду матрицу обратной трансформации камеры? - person A---B; 18.06.2016
comment
Поправьте меня, если я ошибаюсь, но ваше описание похоже на преобразование просмотра (т.е. матрицу view), тогда как OP, похоже, показывает матрица просмотра. В какой-то момент я подумал, что матрицы view и look-at - это одно и то же, но получил (дорогостоящий) ожог, и теперь я думаю о них как о двух разных матрицах. Это неправильно? Матрица просмотра в точности такая же, как матрица просмотра, но построена по-другому? - person code_dredd; 08.02.2017
comment
@code_dredd Функция LookAt () иногда дает мировую матрицу, которая является обратной матрицей представления. Но поскольку инверсия очень затратна, лучше, если LookAt уже возвращает матрицу вида. - person Crouching Kitten; 19.06.2020

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

Итак, операция такова: сначала перевести в начало координат (переместиться на - eye), затем повернуть так, чтобы вектор от eye до At выровнялся. с + z:

По сути, вы получите тот же результат, если предварительно умножите матрицу вращения на перевод - eye:

[      1       0       0   0 ]   [ xaxis.x  yaxis.x  zaxis.x 0 ]
[      0       1       0   0 ] * [ xaxis.y  yaxis.y  zaxis.y 0 ]
[      0       0       1   0 ]   [ xaxis.z  yaxis.z  zaxis.z 0 ]
[ -eye.x  -eye.y  -eye.z   1 ]   [       0        0        0 1 ]

  [         xaxis.x          yaxis.x          zaxis.x  0 ]
= [         xaxis.y          yaxis.y          zaxis.y  0 ]
  [         xaxis.z          yaxis.z          zaxis.z  0 ]
  [ dot(xaxis,-eye)  dot(yaxis,-eye)  dot(zaxis,-eye)  1 ]

Дополнительные замечания:

Обратите внимание, что преобразование просмотра (намеренно) инвертировано: вы умножаете каждую вершину на эту матрицу, чтобы «переместить мир» так, чтобы часть, которую вы хотите увидеть, попала в объем канонического просмотра.

Также обратите внимание, что компонент матрицы вращения (назовем его R) матрицы LookAt - это матрица инвертированного изменения базиса, где строки R новые базисные векторы в терминах старых базисных векторов (отсюда имена переменных xaxis.x, .. xaxis - это новая ось x после изменения базиса). Однако из-за инверсии строки и столбцы меняются местами.

person bobobobo    schedule 23.07.2011
comment
Умножение матриц не коммутативно. - person 林奕忠; 08.10.2015
comment
Это лучший ответ, гораздо более убедительный, чем принятый в настоящее время ответ. - person prideout; 29.02.2016
comment
Это означало бы, что матрица LookAt является ортонормированной базой, иначе транспонирование не было бы равно обратному, верно? - person John Leidegren; 12.12.2016
comment
@JohnLeidegren да, часть вращения ортонормирована по конструкции именно по этой причине. - person eric; 31.12.2018

Немного общей информации:

Матрица просмотра - это матрица, которая позиционирует / поворачивает что-то, чтобы указать (посмотреть) на точку в пространстве из другой точки в пространстве.

Метод берет желаемый «центр» обзора камеры, вектор «вверх», который представляет направление «вверх» для камеры (вверх почти всегда (0,1,0), но это не обязательно ), и вектор "глаза", который является местоположением камеры.

Это используется в основном для камеры, но также может использоваться для других техник, таких как тени, прожекторы и т. Д.

Честно говоря, я не совсем уверен, почему компонент перевода устанавливается именно так, как в этом методе. В gluLookAt (из OpenGL) компонент перевода установлен на 0,0,0, поскольку камера всегда рассматривается как находящаяся на 0,0,0.

person TM.    schedule 09.12.2008

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

Идея не столько в том, что матрица регулирует положение камеры. Скорее, он пытается упростить математику: когда вы хотите визуализировать изображение всего, что вы можете видеть из своего положения «глаза», проще всего представить, что ваш глаз является центром вселенной.

Итак, краткий ответ заключается в том, что это значительно упрощает математику.

Отвечая на вопрос в комментарии: причина, по которой вы не просто вычитаете позицию «глаза» из всего, связана с порядком операций. Подумайте об этом так: как только вы окажетесь в новой системе отсчета (то есть в положении головы, представленном xaxis, yaxis и zaxis), вы теперь хотите выразить расстояния в терминах этой новой (повернутой) системы отсчета. Вот почему вы используете скалярное произведение новых осей с положением глаза: оно представляет то же расстояние, на которое вещи должны переместиться, но использует новую систему координат.

person Bob Cross    schedule 08.12.2008
comment
Итак, насколько я понимаю, матрица настраивается с правильным переводом, хорошо, но почему скалярные произведения в этом вычислении? Разве это не могло быть просто -eye.x, -eye.y, -eye.z? - person Daemin; 09.12.2008

Точечный продукт просто проецирует точку на ось, чтобы получить x-, y- или z-компоненты глаза. Вы перемещаете камеру назад, поэтому взгляд на (0, 0, 0) из (10, 0, 0) и из (100000, 0, 0) будет иметь разный эффект.

person Eugene Yokota    schedule 08.12.2008

Матрица просмотра выполняет эти два шага:

  1. Переведите вашу модель в начало координат,
  2. Поверните его в соответствии с ориентацией, заданной вектором вверх и направлением взгляда.

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

person Kalle    schedule 09.12.2008

Матрица преобразования 4x4 содержит два-три компонента: 1. матрицу вращения 2. добавляемое перемещение. 3. Масштаб (многие движки не используют это прямо в матрице).

Их комбинация преобразует точку из пространства A в пространство B, следовательно, это матрица преобразования M_ab

Теперь положение камеры находится в пространстве A, поэтому это недопустимое преобразование для пространства B, поэтому вам нужно умножить это местоположение на преобразование поворота.

Остается только один открытый вопрос: почему именно точки? Что ж, если вы напишете 3 точки на бумаге, вы обнаружите, что 3 точки с X, Y и Z в точности похожи на умножение с матрицей вращения.

Примером для этой четвертой строки / столбца будет взятие нулевой точки - (0,0,0) в мировом пространстве. Это не нулевая точка в пространстве камеры, поэтому вам нужно знать, каково представление в пространстве камеры, поскольку вращение и масштаб оставляют его равным нулю!

ваше здоровье

person Adi    schedule 15.02.2009

Точку взгляда необходимо размещать в пространстве вашей оси, а не в мировом пространстве. Когда вы ставите точку на векторе с базисным вектором единицы координат, одним из x, y, z, он дает вам координаты глаза в этом пространстве. Вы трансформируете местоположение, применяя три перевода в последнем месте, в данном случае в последней строке. Затем перемещение глаза назад при отрицательном результате эквивалентно перемещению всего остального пространства вперед. Точно так же, как подъем в лифте заставляет вас чувствовать, что весь остальной мир выпадает из-под вас.

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

person DragonLord    schedule 24.04.2014
comment
Что такое осевое пространство? Я никогда раньше не слышал этот термин. Вы имели в виду объектное пространство? вертикальное пространство? пространство камеры? - person Bjorn; 14.11.2016