Как 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, но кажется странным определять "строку" как вертикальную, а "столбец" - горизонтальную. Может кто-нибудь объяснить это?
Ответы
Ответ 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
.