Каков правильный порядок преобразований при расчете матриц в OpenGL? - PullRequest
0 голосов
/ 15 октября 2019

Я следую учебным пособиям на LearnOpenGL.com, и меня смущает порядок матриц.

В главе Преобразования говорится:

Умножение матриц не является коммутативным, что означает, что их порядок важен. При умножении матриц крайняя правая матрица сначала умножается на вектор, поэтому вы должны читать умножения справа налево. Рекомендуется сначала выполнять операции масштабирования, а затем вращения и, наконец, преобразования при объединении матриц, иначе они могут (отрицательно) влиять друг на друга. Например, если вы сначала выполните перевод, а затем масштабируете, вектор перевода также масштабируется!

Так что, если я не ошибаюсь, порядок будет Translate * Rotate * Scale * vector_to_transform.

Но сразу в следующей главе при расчете матрицы LookAt порядок умножения переворачивается. Вот фрагмент кода с веб-сайта:

// Custom implementation of the LookAt function
glm::mat4 calculate_lookAt_matrix(glm::vec3 position, glm::vec3 target, glm::vec3 worldUp)
{
    // 1. Position = known
    // 2. Calculate cameraDirection
    glm::vec3 zaxis = glm::normalize(position - target);
    // 3. Get positive right axis vector
    glm::vec3 xaxis = glm::normalize(glm::cross(glm::normalize(worldUp), zaxis));
    // 4. Calculate camera up vector
    glm::vec3 yaxis = glm::cross(zaxis, xaxis);

    // Create translation and rotation matrix
    // In glm we access elements as mat[col][row] due to column-major layout
    glm::mat4 translation = glm::mat4(1.0f); // Identity matrix by default
    translation[3][0] = -position.x; // Third column, first row
    translation[3][1] = -position.y;
    translation[3][2] = -position.z;
    glm::mat4 rotation = glm::mat4(1.0f);
    rotation[0][0] = xaxis.x; // First column, first row
    rotation[1][0] = xaxis.y;
    rotation[2][0] = xaxis.z;
    rotation[0][1] = yaxis.x; // First column, second row
    rotation[1][1] = yaxis.y;
    rotation[2][1] = yaxis.z;
    rotation[0][2] = zaxis.x; // First column, third row
    rotation[1][2] = zaxis.y;
    rotation[2][2] = zaxis.z; 

    // Return lookAt matrix as combination of translation and rotation matrix
    return rotation * translation; // Remember to read from right to left (first translation then rotation)
}

В конце фрагмента кода матрица рассчитывается как rotation * translation, хотя матрица будет умножена на

gl_position = projection * lookAt * model * vec4(vertexPosition, 1.0);

как матрицы столбцов должны быть предварительно умножены на вектор.

Пожалуйста, помогите мне понять это.

1 Ответ

0 голосов
/ 15 октября 2019

Хорошо! Прочитав всю главу снова, я упустил важную деталь. Матрица просмотра обычно не масштабирует объекты. Это просто матрица, чтобы вращать и переводить матрицу модели таким образом, чтобы имитировать глаз в мир. Эта глава на LearnOpenGL.com содержит блок, объясняющий объединение матриц, и показывает, как объединить преобразование и поворот матрицы, и как реализована функция lookAt.

...