Как GLKit's GLKMatrix "Колонка Майор"? - PullRequest
15 голосов
/ 13 марта 2012

Предпосылка A

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


A 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 гласит:

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

Помещение B

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

Ответы [ 3 ]

11 голосов
/ 13 марта 2012

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

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

10 голосов
/ 17 сентября 2012

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

column major

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

  • m00 относится к столбец = 0, строка = 0 ,
  • m01 относится к столбец = 0, строка = 1 ,
  • m02 относится к столбец = 0, строка = 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 голосов
/ 13 марта 2012

Проблема в Исходное положение 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.

...