Эта статья является отступлением от различных статей, которые говорят о матрицах, в частности статьи, которая вводит матрицы, но также статьи, которая вводит 3D, статьи о перспективной проекции, и статьи о камерах.
В программировании в общем строка идет слева направо, столбец идет вверх и вниз.
стол·бец
/ˈkäləm/
существительное
вертикальная колонна, обычно цилиндрическая и сделанная из камня или бетона, поддерживающая антаблемент, арку или другую структуру или стоящая отдельно как памятник.
синонимы: колонна, столб, шест, вертикаль, …
вертикальное деление страницы или текста.
строка
/rō/
существительное
- горизонтальная линия записей в таблице.
Мы можем видеть примеры в нашем программном обеспечении. Например, мои текстовые редакторы показывают Строки и столбцы, строки являются другим словом для строки в этом случае, поскольку столбец уже занят
Обратите внимание в нижней левой области строка состояния показывает строку и столбец.
В программном обеспечении для работы с электронными таблицами мы видим, что строки идут поперек
А столбцы идут вниз.
Итак, когда мы создаем матрицу 3x3 или 4x4 в JavaScript для WebGL, мы делаем их так
const m3x3 = [
0, 1, 2, // строка 0
3, 4, 5, // строка 1
6, 7, 8, // строка 2
];
const m4x4 = [
0, 1, 2, 3, // строка 0
4, 5, 6, 7, // строка 1
8, 9, 10, 11, // строка 2
12, 13, 14, 15, // строка 3
];
Ясно следуя соглашениям выше, первая строка m3x3
- это 0, 1, 2
, а последняя строка m4x4
- это 12, 13, 14, 15
Как мы видим в первой статье о матрицах, чтобы сделать довольно стандартную WebGL 3x3 2D матрицу перевода, значения перевода tx
и ty
идут в позиции 6 и 7
const some3x3TranslationMatrix = [
1, 0, 0,
0, 1, 0,
tx, ty, 1,
];
или для матрицы 4x4, которая вводится в первой статье о 3D, перевод идет в позиции 12, 13, 14, как в
const some4x4TranslationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, tz, 1,
];
Но есть проблема. Математические соглашения для матричной математики обычно делают вещи в столбцах. Математик написал бы матрицу перевода 3x3 так
и матрицу перевода 4x4 так
Это оставляет нас с проблемой. Если мы хотим, чтобы наши матрицы выглядели как математические матрицы, мы можем решить написать матрицу 4x4 так
const some4x4TranslationMatrix = [
1, 0, 0, tx,
0, 1, 0, ty,
0, 0, 1, tx,
0, 0, 0, 1,
];
К сожалению, делать это так имеет проблемы. Как упоминалось в статье о камерах, каждый из столбцов матрицы 4x4 часто имеет значение.
Первый, второй и третий столбцы часто считаются осями x, y и z соответственно, а последний столбец - это позиция или перевод.
Одна проблема в том, что в коде было бы не весело пытаться получить эти части отдельно. Хотите ось Z? Вам пришлось бы делать это
const zAxis = [
some4x4Matrix[2],
some4x4Matrix[6],
some4x4Matrix[10],
];
Ух!
Итак, способ, которым WebGL, и OpenGL ES, на котором основан WebGL, обходит это, заключается в том, что он называет строки “столбцами”.
const some4x4TranslationMatrix = [
1, 0, 0, 0, // это столбец 0
0, 1, 0, 0, // это столбец 1
0, 0, 1, 0, // это столбец 2
tx, ty, tz, 1, // это столбец 3
];
Теперь это соответствует математическому определению. Сравнивая с примером выше, если мы хотим ось Z, все, что нам нужно сделать, это
const zAxis = some4x4Matrix.slice(8, 11);
Для тех, кто знаком с C++, сам OpenGL требует, чтобы 16 значений матрицы 4x4 были последовательными в памяти, поэтому в C++ мы могли бы создать структуру или класс Vec4
// C++
struct Vec4 {
float x;
float y;
float z;
float w;
};
и мы могли бы создать матрицу 4x4 из 4 из них
// C++
struct Mat4x4 {
Vec4 x_axis;
Vec4 y_axis;
Vec4 z_axis;
Vec4 translation;
}
или просто
// C++
struct Mat4x4 {
Vec4 column[4];
}
И это просто казалось бы работающим.
К сожалению, это выглядит совсем не как математическая версия, когда вы фактически объявляете одну статически в коде.
// C++
Mat4x4 someTranslationMatrix = {
{ 1, 0, 0, 0, },
{ 0, 1, 0, 0, },
{ 0, 0, 1, 0, },
{ tx, ty, tz, 1, },
};
Или обратно к JavaScript, где у нас обычно нет чего-то вроде C++ структур.
const someTranslationMatrix = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
tx, ty, tz, 1,
];
Итак, с этим соглашением называть строки “столбцами” некоторые вещи проще, но другие могут быть более запутанными, если вы математик.
Я поднимаю все это, потому что эти статьи написаны с точки зрения программиста, а не математика. Это означает, что как и каждый другой одномерный массив, который обрабатывается как двумерный массив, строки идут поперек.
const someTranslationMatrix = [
1, 0, 0, 0, // строка 0
0, 1, 0, 0, // строка 1
0, 0, 1, 0, // строка 2
tx, ty, tz, 1, // строка 3
];
точно так же, как
// изображение смайлика
const dataFor7x8OneChannelImage = [
0, 255, 255, 255, 255, 255, 0, // строка 0
255, 0, 0, 0, 0, 0, 255, // строка 1
255, 0, 255, 0, 255, 0, 255, // строка 2
255, 0, 0, 0, 0, 0, 255, // строка 3
255, 0, 255, 0, 255, 0, 255, // строка 4
255, 0, 255, 255, 255, 0, 255, // строка 5
255, 0, 0, 0, 0, 0, 255, // строка 6
0, 255, 255, 255, 255, 255, 0, // строка 7
]
и поэтому эти статьи будут ссылаться на них как на строки.
Если вы математик, вы можете найти это запутанным. Мне жаль, что у меня нет решения. Я мог бы назвать то, что явно является строкой 3, столбцом, но это также было бы запутанно, поскольку это не соответствует никакому другому программированию.
В любом случае, надеюсь, это помогает прояснить, почему ни одно из объяснений не выглядит как что-то из математической книги. Вместо этого они выглядят как код и используют соглашения кода. Я надеюсь, что это помогает объяснить, что происходит, и это не слишком запутанно для тех, кто привык к математическим соглашениям.