3 x 3 матрицы могут кодировать преобразования, такие как вращение и отражение, но не перевод. Для этого вам нужно добавить четвертый элемент и представить свои векторы в виде однородных координат . Можно использовать неквадратные матрицы для определенных целей, но если вы хотите иметь возможность составлять их в любом порядке, они должны быть квадратными (поскольку вы можете умножить только две матрицы, если число столбцов в первой равно количество строк во втором).
Итак, для ваших целей вы должны использовать матрицы 4x4 и 4-элементные однородные векторы, добавляя четвертую w координату со значением 1.
Применение преобразования к группе векторов - это просто умножение.
Традиционно векторы представляются в виде столбцов , а матрица идет слева. Вы представляете их выше как строки и умножаете справа. Оба действительны, но матрицу преобразования необходимо транспонировать между двумя случаями. Матрица, которую вы показываете, имеет значения перевода внизу, что соответствует вашему порядку умножения.
После того, как векторы были преобразованы, вам нужно разделить на w координату, чтобы масштабировать x, y и z обратно в обычное трехмерное пространство. .
В псевдокоде C-ish с использованием соглашения о векторе-строке:
Vector transform (Vector v, Matrix m)
{
Vector result;
for ( int i = 0; i < 4; ++i )
result[i] = v[0] * m[0][i] + v[1] * m[1][i] + v[2] + m[2][i] + v[3] * m[3][i];
result[0] = result[0]/result[3];
result[1] = result[1]/result[3];
result[2] = result[2]/result[3];
return result;
}
Последовательность преобразований может быть составлена путем умножения матриц для каждого из них по очереди. Обратите внимание, что матричное умножение не коммутативно , поэтому важен порядок, в котором вы умножаетесь. В свою очередь, это означает, что важно, умножаете ли вы векторы строк слева или столбцы справа. Если умножить A x B x C , то на векторы столбцов, которые аналогичны выполнению преобразования C сначала, затем B , затем наконец A . Для векторов строк это сначала A , затем B , а затем C . Поэтому важно сохранять все единообразно при конструировании, составлении и применении ваших преобразований.
Опять же, в псевдокоде, который должен соответствовать transform
выше:
Matrix compose (Matrix first, Matrix second)
{
Matrix result;
for ( int i = 0; i < 4; ++i )
for ( int j = 0; j < 4; ++j )
result[i][j] = first[i][0] * second[0][j]
+ first[i][1] * second[1][j]
+ first[i][2] * second[2][j]
+ first[i][3] * second[3][j];
return result;
}