Вопрос по выводу gluLookAt функции в OpenGL?

Всем доброго вечера,


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


Изучая работу gluLookAt я заметил, что вектор up обычно указывает по одной оси (y или -z), не смотря на то, куда обращён взгляд «камеры» (да, я знаю, что надо смещать мир, дабы сэмулировать понятие движения в OpenGL). Теоретически, вектор up должен быть ортогонален направлению камеры (или разницы между точками — center и eye, то есть опять же вектор с концом «куда смотреть» и началом «откуда»). Интернет пишет, что это неважно и часто up вектор просто смотрит «вверх», неважно куда направлена камера.


Можете ли объяснить мне, почему так? Потому что, когда я попытался сэмулировать наклон камеры, то у меня встала задача вращать вектор up относительно вектора направления камеры, и для меня это составило трудность.


И второй вопрос, он относится к заголовку, помогите мне пожалуйста с объяснением, как выводится сама функция gluLookAt. В интернете, я отыскал небольшой сайт (сорри, что на немецком), где описывается как реализовать эту функцию, и у меня это получилось (с операциями над векторами и матрицами, я немного владею).


Если возможно, не смогли бы вы мне объяснить, почему в та матрица преобразований, которую мыс троим в конце — именно то, что нам нужно (понятно, что она даёт нам правильный результат).


Вот смотрите:

Когда мы получаем нормализованный вектор направления камеры и нормализованный вектор up, то мы их векторно умножаем друг на друга:

s' = f x UP'


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


Хорошо, допустим, мы нормализуем наш вектор и снова умножаем его на вектор направления камеры, с последующей нормализацией:

u = s x f


Отлично, новый вектор, перпендикулярный обеим векторам, получен. Но я не могу понять, (простите за глупость) — зачем, и как мы переходим вот к такой матрице:

|  s[0]  s[1]  s[2]  0 |
M = |  u[0]  u[1]  u[2]  0 |
    | -f[0] -f[1] -f[2]  0 |
    |   0     0     0    1 |



Это возможно, матрица поворота, но здесь я не вижу последовательного умножения матриц поворота относительно отдельных осей X, Y, Z (таких как в Википедии). Тем более, что у нас нет никаких косинусов и углов, которые мы могли вычислить из имеющихся двух векторов.


Спасибо вам больше заранее.
  • Вопрос задан
  • 6638 просмотров
Решения вопроса 1
SHVV
@SHVV
Как вы написали, матрица преобразования — это матрица перехода от одного базиса к другому. Она может содержать как поворот, так и масштабирование и прочие линейные искажения.

Одно из свойств матрицы преобразования — это то, что её строки являются векторами базиса новой системы координат. То есть, когда вы умножаете матрицу на вектор, вы последовательно умножаете скалярно исходный вектор и строки (вектора базиса), получая исходный вектор в новых координатах. Так как каждое скалярное произведение покажет, сколько того или иного базисного вектора есть в исходном векторе. Чтобы матрица преобразования была ортонормированной (содержать исключительно вращения), она должна состоять из взаимно перпендикулярных и нормализованных векторов.

Итак, строки матрицы у нас — вектора нового базиса в координатах исходного базиса. Надо их найти.
Один из векторов у нас известен — это направление взгляда, нормализуем его и записываем сразу в матрицу (для OpenGL ось взгляда — ось Z, потому записываем наш вектор в третью строку матрицы). Второй вектор ортогонален первому и некоторой примерной линии, направленной вверх. получаем его векторным произведением вектора взгляда и этого вспомогательного вектора. Получаем вектор, направленный вправо (или влево, в зависимости от порядка умножения). После нормализации записываем его в первую строку матрицы (в OpenGL ось X совпадает с осью X экрана и направлена вправо). Оставшийся вектор получаем векторным произведением уже полученных векторов и записываем во вторую строку матрицы (в OpenGL ось Y направлена вверх). Он должен получаться уже нормализованным.

Но есть нюанс. Если вектор взгляда совпадает с вспомогательным вектором вверх, то их векторное произведение будет равно нулю и матрицу посчитать не получится.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
AterCattus
@AterCattus
Люблю быстрый backend
Раз никто не предложил ничего конкретного…

Вот в этой книжке (легко ищется и качается) с 554 страницы (но можно и раньше начать читать) описывается работа с UVN камерой. На основе вашего примера матрицы M такую камеру можно назвать транспонированной «SU-F».
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы