netlib.narod.ru< Назад | Оглавление | Далее >

Матрицы и преобразования

Большая часть преобразований, которыми мы будем пользоваться, может быть описана в виде вещественной матрицы 3 × 3. Однако работа с матрицами 3 × 3 несколько усложняет вычисления, поскольку некоторые преобразования выполняются не так, как другие. Например, перенос реализуется сложением элементов матрицы, а поворот — умножением. Тем не менее, если вставить элементы матрицы 3 × 3 в матрицу 4 × 4 и должным образом заполнить свободные места, все преобразования можно будет выполнять посредством операции матричного умножения, поэтому для описания преобразований мы будем пользоваться матрицами 4 × 4. Если вы незнакомы с однородной системой координат, которая применяется при описании преобразований в трехмерном пространстве (а кто с ней знаком, кроме математиков?), вы наверняка чувствуете себя сбитым с толку. Давайте немедленно решим эту проблему и начнем с небольшого примера того, как пользоваться матрицами для преобразования координат точки в пространстве. Поскольку формулы для трехмерного случая оказываются довольно длинными, мы вместо этого рассмотрим упрощенный пример на плоскости — уверяю вас, в трехмерном пространстве он работает точно так же.

Двумерные координаты точки xy в однородной системе координат представляются вектором следующего вида:

Матрица для переноса точки на плоскости выглядит следующим образом:

где dx — смещение точки по оси X, а dy — смещение по оси Y. Теперь давайте умножим исходный вектор на эту матрицу и посмотрим, что у нас получится. При умножении матрицы на вектор-столбец каждый элемент вектора-результата представляет собой сумму элементов соответствующей строки матрицы, умноженных на элементы исходного вектора:

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

Теперь давайте попробуем применить полученные знания на практике и воспользуемся объектом C3dMatrix, содержащим массив вещественных величин 4 × 4, для переноса вектора. Чтобы вы получше представляли себе класс C3dMatrix, привожу исходный текст его конструктора:

C3dMatrix::C3dMatrix()
{
    m_00 = 1.0; m_01 = 0.0; m_02 = 0.0; m_03 = 0.0;
    m_10 = 0.0; m_11 = 1.0; m_12 = 0.0; m_13 = 0.0;
    m_20 = 0.0; m_21 = 0.0; m_22 = 1.0; m_23 = 0.0;
    m_30 = 0.0; m_31 = 0.0; m_32 = 0.0; m_33 = 1.0;
} 

В исходном состоянии, задаваемом в конструкторе, эта матрица является матрицей идентичного преобразования, или единичной матрицей. Если умножить вектор на такую матрицу, он не изменится. Приведенный ниже фрагмент, использующий объект C3dMatrix, осуществляет перенос вектора x, y, z со смещениями координат dx, dy, dz:

C3dVector v (x, y, z);
C3dMatrix m;
m.Translate(dx, dy, dz);
v = m * v; 

Объект C3dVector инициализируется элементами исходного вектора. Затем, после конструирования объекта C3dMatrix (который в первоначальном состоянии совпадает с матрицей идентичного преобразования), вызывается его функция Translate для занесения в матрицу преобразования переноса. Наконец, вектор умножается на матрицу, и результат присваивается исходному вектору.

Не следует полагать, будто функция C3dMatrix::Translate просто инициализирует матрицу; как нетрудно убедиться по приведенному ниже фрагменту, на самом деле она комбинирует преобразование переноса с любыми преобразованиями, уже занесенными в матрицу:

void C3dMatrix::Translate(double dx, double dy, double dz)
{
    C3dMatrix tx( 1,  0,  0, 0,
                  0,  1,  0, 0,
                  0,  0,  1, 0,
                 dx, dy, dz, 1); 

    *this *= tx;
} 

Временная матрица инициализируется элементами для преобразования переноса. Затем текущая матрица умножается на временную матрицу переноса, а результат снова присваивается текущей матрице.

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

mFinal = m1 * m2 * m3; 

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz