Вращение 3D камеры

9

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

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

Итак, вот набор соглашений, которые я сформировал на основе того, что кажется наиболее распространенным и логичным:

  1. Правило правой руки для оси.
  2. Положительный Y вверх, положительный Z направлен на зрителя, положительный X направо.
  3. Row Major матрицы, транспонированные при отправке в шейдеры.
    • Шаг: вращение вокруг оси X
    • Yaw: вращение вокруг оси Y
    • Roll: вращение вокруг оси z
  4. Порядок вращения: Roll, Pitch, Yaw (это правильно? Может кто-нибудь проверить меня?)
  5. Положительные значения вращения, если смотреть вниз от положительного конца оси, приводят к вращению по часовой стрелке.
  6. Направление по умолчанию для поворота 0 по всей оси - это вектор, направленный вниз к отрицательному Y.

.. учитывая эти условности (во что бы то ни стало исправьте меня, если они ошибаются!), как это сделать:

  • Написать функцию LookAt? (lookAt (векторное положение, векторный фокус, вектор вверх))
  • Рассчитать матрицу вращения. (вращение (x, y, z))

Я попытался ответить на эти два вопроса сам, по крайней мере, за последние 3 недели, я переписал свою функцию LookAt & Rotation Matrix по крайней мере 30 раз, я протестировал десятки методов и прочитал материал, который видел на сотни веб-сайтов и читали многие ответы на вопросы, копировали чужой код, и ничего из того, что я сделал до сих пор, не сработало, все дало неправильный результат. Некоторые из которых производили некоторые забавно причудливые результаты, даже не близкие к правильному вращению.

Я работал над этим каждую ночь, за исключением прошлой ночи, потому что я был настолько расстроен повторяющимся провалом, что мне пришлось остановиться и сделать перерыв.

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

Я пишу на Java, но я возьму код, написанный на любом языке, большая часть моего кода 3D-рендеринга на самом деле работает блестяще, это просто математика, которую я не могу понять.

ОБНОВЛЕНИЕ: решено

Спасибо за помощь! Теперь у меня есть работающая функция LookAt, которую я на самом деле понимаю, и я не могу быть счастливее (если кто-то захочет увидеть ее, обязательно спросите).

Я попытался еще раз создать матрицу вращения, основанную на переменных pitch / yaw / roll, и она снова, похоже, потерпела неудачу, но я решил отказаться от попыток использовать углы Эйлера для камеры freelook, так как она кажется неподходящей для Вместо того, чтобы использовать роль, вместо этого я собираюсь создать класс кватернионов, возможно, будет более удачным идти по этому пути, в противном случае я прибегну к использованию шага / рыскания в качестве сферических координат и буду полагаться на новую рабочую функцию LookAt для вращения.

Если кто-то еще сталкивается с подобной проблемой и хочет задать мне вопросы, не стесняйтесь.

По крайней мере, я больше не застреваю, спасибо за помощь!

Грейди
источник

Ответы:

15

То, что вы ищете, можно найти в этом очень хорошем объяснении: http://www.songho.ca/opengl/gl_transform.html

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

На данный момент вам нужно рассмотреть 5 систем координат и как они связаны друг с другом. Это координаты окна, нормализованные координаты устройства, координаты глаза, мировые координаты и координаты объекта.

Координаты окна можно увидеть как «физические» пиксели на вашем экране. Это координаты, на которые ссылается оконная система, и если вы работаете с собственным разрешением мониторов, это фактически отдельные пиксели. Система координат окна является двумерным целым числом и относится к вашему окну. Здесь x + слева, а y + вниз с началом координат в верхнем левом углу. Вы сталкиваетесь с этим, когда вы, например, звоните glViewport.

Второй набор - нормализованные координаты устройства. Они относятся к настройке пространства активным портом просмотра. Видимая область порта просмотра имеет значение от -1 до +1 и, следовательно, имеет начало координат в центре. Х + слева, а у + вверх. У вас также есть z + "вне" сцены. Это то, что вы описываете в 1.

Вы не контролируете, как вы доберетесь от нормализованных координат устройства до координат окна, это делается для вас неявно. Единственный контроль, который у вас есть, - через glViewportили похожий.

При работе с openGL ваш конечный результат всегда будет в нормализованных координатах устройства. В результате вам нужно беспокоиться о том, как визуализировать вашу сцену в них. Если вы установите матрицу проекции и вида модели в единичную матрицу, вы можете непосредственно нарисовать эти координаты. Это делается, например, при применении полноэкранных эффектов.

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

Чтобы добраться от координат глаза до координат устройства, вы строите матрицу проекции. Простейшей является ортографическая проекция, которая просто масштабирует значения соответствующим образом. Перспективная проекция является более сложной и включает в себя симуляцию перспективы.

Наконец, у вас есть мировая система координат. Это система координат, в которой определяется ваш мир, а ваша камера является частью этого мира. Здесь важно отметить, что ориентации осей такие же, как вы их определяете . Если вы предпочитаете z + как вверх, это нормально.

Чтобы перейти от мировых координат к координатам глаза, вы определяете матрицу вида. Это может быть сделано с чем-то вроде lookAt. Эта матрица «перемещает» мир так, что камера находится в начале координат и смотрит вниз по оси z.

Чтобы вычислить матрицу вида на удивление просто, вам нужно преобразовать камеру. Вам в основном нужно сформулировать следующую матрицу:

Mзнак равноИкс[1]Y[1]Z[1]-п[1]Икс[2]Y[2]Z[2]-п[2]Икс[3]Y[3]Z[3]-п[3]0001

Векторы x, y и z могут быть напрямую взяты с камеры. В случае, если смотреть на вас, вы получите их из значений цели, глаза (в центре) и вверх. Вот так:

Zзнак равноNормaLяZе(еYе-TaргеT)Иксзнак равноNормaLяZе(Uп×Z)Yзнак равноZИкс

Но если у вас просто лежат эти ценности, вы можете принять их такими, какие они есть.

Получение р немного сложнее. Это не позиция в мировых координатах, а позиция в координатах камеры. Простой обходной путь - инициализировать две матрицы, одну с только x, y и z, а другую с -eye и умножить их вместе. Результатом является матрица представления.

Как это может выглядеть в коде:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

полный код

И, наконец, ради полноты, у вас также есть система координат объекта. Это система координат, в которой хранятся сетки. С помощью матрицы модели координаты сетки преобразуются в мировую систему координат. На практике матрицы модели и вида объединяются в так называемую матрицу вида модели.

rioki
источник
1
Если бы я мог проголосовать за этот ответ сто раз, я бы так и сделал. Спасибо за исчерпывающий и полный ответ на все вопросы, которые меня смутили, а также за предоставление кода и ссылки! Я провел весь день, читая книги по математике по этому предмету и с вашим ответом, примером кода и связанной страницей, если мне этого недостаточно, чтобы понять это, я должен сейчас уйти. Если бы я мог попросить только одно пояснение в последнем примере кода, был бы я прав, сказав, что эти матрицы расположены в главном порядке столбцов, а приведенная выше - в основном?
Грэди
Это немного сбивает с толку, матрицы являются основными столбца, но столбец в строке. Таким образом, чтобы сопоставить фактическую математику с кодом, вам нужно транспонировать матрицу. См. Github.com/rioki/glm/blob/master/src/matrix.h#l72 Это отображается точно на openGL и как это будет при использовании float[16].
rioki
Ах, я так и думал, но просто хотел быть уверен, еще раз спасибо! Вы мне очень помогли, я очень ценю это.
Грэди