Способ преобразования трехмерных векторов с помощью матрицы - PullRequest
4 голосов
/ 31 мая 2010

Я немного читал о преобразовании Vector3 с помощью матриц, и сейчас я копаюсь глубже в математику и сам кодирую ее, а не использую существующий код. По какой-то причине моя школьная программа никогда не включала в себя матрицы, поэтому я заполняю пробел в своих знаниях. К счастью, мне нужно всего несколько простых вещей, я думаю.

Ситуация в том, что я программирую робота для RoboCup 3D-лиги . Я пишу код на C #, но он должен работать на Mono. В идеале я бы не использовал для этого существующие графические библиотеки (WinForms / WPF / XNA), поскольку все, что мне действительно нужно, это аккуратное подмножество матричных преобразований.

В частности, мне нужен перевод и вращения x / y / z, а также способ объединения нескольких преобразований в одну матрицу. Затем это будет применено к моему собственному типу Vector3 для создания преобразованного Vector3.

Я читал разные советы по этому поводу. Например, некоторые моделируют преобразование с матрицей 4x3, другие с матрицей 4x4.

Кроме того, некоторые примеры показывают, что вам нужно четвертое значение для матрицы вектора 1. Что происходит с этим значением, когда оно включается в вывод?

            [1 0 0 0]
[x y z 1] * [0 1 0 0] = [a b c d]
            [0 0 1 0]
            [2 4 6 1]

Части, по которым я скучаю:

  • Каких размеров должны быть мои матрицы
  • Композиция преобразований путем умножения матриц преобразования вместе
  • Преобразование трехмерных векторов с результирующей матрицей

Поскольку я в основном просто хочу запустить его, любой псевдо-код был бы великолепен. Информация о том, какие значения матрицы выполняют, какие преобразования достаточно четко определены на многих страницах, поэтому обсуждать их здесь не нужно, если вы не очень заинтересованы:)

1 Ответ

7 голосов
/ 31 мая 2010

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...