Подтвердить что ты не робот

Как GLKit GLKMatrix "Column Major"?

Помещение А

Говоря о матрицах "Major Column" в линейной памяти, столбцы указываются один за другим, так что первые 4 записи в памяти соответствуют первому столбцу в матрице. С другой стороны, под "матрицами мажорных строк" понимаются строки, которые задаются одна за другой, так что первые 4 записи в памяти указывают первую строку матрицы.


GLKMatrix4 выглядит так:

union _GLKMatrix4
{
    struct
    {
        float m00, m01, m02, m03;
        float m10, m11, m12, m13;
        float m20, m21, m22, m23;
        float m30, m31, m32, m33;
    };
    float m[16];
}
typedef union _GLKMatrix4 GLKMatrix4;

В документации на m член сказано:

Одномерный массив элементов матриц в основном порядке столбцов.

Помещение Б

"Строка" в GLKMatrix4 - это набор из 4 поплавков, объявленных горизонтально ([m00, m01, m02, m03] будет первой "строкой"). Таким образом, эти записи могут быть интерпретированы как mRowCol (m12 будет запись в строке 1, столбце 2).


Если мы посмотрим, как эти элементы структуры GLKMatrix расположены в соответствии с порядком объявлений, мы увидим:

[m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23,...]

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

Заключение

m самом деле не является основной колонной, и документы не правы.


Теперь я должен отметить, что на самом деле я не верю заключению, но две предпосылки кажутся довольно разумными. Действительно, я больше всего не доверяю предпосылке B, но кажется странным определять "строку" как вертикальную, а "столбец" - горизонтальную. Может кто-нибудь объяснить это?

4b9b3361

Ответ 1

Объявление немного запутанно, но матрица находится в главном порядке столбца. Четыре строки в структуре представляют столбцы в матрице, а m0 * - столбец 0 и m3 * - столбец 3. Это легко проверить, просто создайте матрицу перевода и проверьте значения m30, m31 и m32 для компонентов перевода.

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

Ответ 2

Это происходит из спецификации OpenGL -

column major

Точка путаницы в точности такова: как отмечали другие, мы индексируем основную матрицу столбца с первым индексом, указывающим столбец, а не строку:

  • m00 относится к столбцу = 0, row = 0,
  • m01 относится к столбцу = 0, row = 1,
  • m02 относится к столбцу = 0, row = 2,

MATLAB, вероятно, многое сделал для косвенного содействия этой путанице, в то время как MATLAB действительно использует столбцы для внутреннего представления данных, он все еще использует соглашение о стандартном индексировании строки x(row,col). Я не уверен, почему они это сделали.

Также обратите внимание, что OpenGL по умолчанию использует векторы столбцов - т.е. вы ожидаете, что после этого умножите матрицу вектором, который он преобразует, как (MATRIX*VECTOR) в шейдере. Контраст с (VECTOR*MATRIX), который вы хотите для матрицы строк.

Это может помочь взглянуть на мою статью о главных матрицах строк и столбцов в C.

Значок столбца встречно интуитивно понятен при выкладке матриц в код

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

float a[4] = { 1, 2,
               3, 4 };

Итак, очень естественно выглядит, что вы указываете по строке, матрица

1 2
3 4

Но если вы используете основную спецификацию столбца, то вы на самом деле указали матрицу

1 3
2 4

Что действительно противоречит интуиции. Если бы мы имели вертикальный (или "основной" язык , то проще было бы определить основные матрицы столбцов в коде.

Является ли все это еще одним аргументом для Direct3D? Я не знаю, ты говоришь мне.

Действительно, почему OpenGL использует основные матрицы столбцов?

Копая глубже, кажется, что причина, по которой это было сделано , заключалась в том, чтобы иметь возможность "перемножать" матрицы по векторам как (MATRIX*VECTOR) - т.е. иметь возможность использовать столбцы (основные) векторы типа:

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

┌ 2 8 1 1 ┐ ┌ 2 ┐
│ 2 1 7 2 │ │ 2 │
│ 2 6 5 1 │ │ 2 │
└ 1 9 0 0 ┘ └ 1 ┘

Сравните это с необходимостью использования векторов строк:

Массовое умножение матрицы на ряд

[ 2 2 2 1 ]  ┌ 2 8 1 1 ┐ 
             │ 2 1 7 2 │
             │ 2 6 5 1 │
             └ 1 9 0 0 ┘

Сделка: , если матрицы заданы как основные строки, тогда вы должны "использовать векторы строк и матрицы с пре-умножением вектором, который они преобразуют.

Причиной того, что вы "должны" использовать векторы строк при использовании основных матриц строк, является согласованное представление данных: ведь вектор строки - это всего лишь 1 строка, 4 столбца.

Ответ 3

Проблема в Помещении B заключается в том, что вы предполагаете, что "строка" в GLKMatrix4 представляет собой набор из 4 поплавков, объявленных горизонтально ([m00, m01, m02, m03] будет первым "строка" ).

Мы можем проверить, что просто проверив значение column в следующем коде:

GLKMatrix3 matrix = {1, 2, 3, 4, 5, 6, 7, 8, 9};
GLKVector3 column = GLKMatrix3GetColumn(m, 0);

Примечание. Я использовал GLKMatrix3 для простоты, но то же самое относится к GLKMatrix4.