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

Матрицы

В этом разделе мы сосредоточимся на математике матриц. Их использование в трехмерной компьютерной графике будет рассмотрено в следующем разделе.

Матрицей m × n называется прямоугольный массив чисел, состоящий из m строк и n столбцов. Количество строк и столбцов определяет размер матрицы. Отдельный элемент матрицы идентифицируется путем указания его строки и столбца в состоящем из двух элементов спсике индексов; первый индекс определяет строку, а второй — столбец. Ниже в качестве примера приведены матрицы M размером 3 × 3, В размером 2 × 4 и С размером 3 × 2:


формула 13

В большинстве случаев для обозначения матриц мы будем использовать заглавные полужирные буквы. Иногда матрицы состоят из единственной строки или единственного столбца. Чтобы отличать такие матрицы, мы дадим им специальные имена: вектор-строка (row vector) и вектор-столбец (column vector). Вот примеры таких векторов:


формула 14

Для элементов вектора-строки и вектора-столбца необходим только один индекс. Иногда для идентификации элемента строки или столбца в качестве индекса мы будем использовать буквы.

Равенство, умножение матрицы на скаляр и сложение матриц

Для пояснения рассматриваемых терминов в данном разделе будут использованые следующие четыре матрицы:


формула 15

Умножение

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

Чтобы получить произведение матриц AB необходимо чтобы количество столбцов матрицы A было равно количеству строк матрицы B. Если условие выполняется, произведение матриц определено. Рассмотрим представленные ниже матрицы A и B, с размерностью 2 × 3 и 3 × 3 соответственно:


формула 20

Как видите, произведение AB определено поскольку количество столбцов матрицы A равно количеству строк матрицы B. Обратите внимание, что произведение BA, получаемое в результате перестановки множителей, не определено, потому что количество столбцов матрицы B не равно количеству строк матрицы A. Это говорит о том, что в обшем случае операция умножения матриц не коммутативна (то есть AB ≠ BA). Мы говорим «в общем случае не коммутативна» по той причине, что существует ряд частных случаев в которых операция умножения матриц ведет себя как коммутативная.

После того, как мы узнали в каких случаях произведение матриц определено, можно дать определение операции умножения матриц: если A — это матрица m × n, а B — матрица n × p, то их произведением будет матрица C, размером m × p, в которой элемент cij находится как скалярное произведение i-го вектора-строки матрицы A и j-го вектора-столбца матрицы B:


формула 21

В этой формуле ai обозначает i-ый вектор-строку в матрице A, а bj — j-ый вектор-столбец матрицы B.

Давайте для примера вычислим произведение:


формула 22

Произведение определено, поскольку количество столбцов матрицы A равно количеству строк матрицы B. Кроме того, обратите внимание, что размер полученной в результате матрицы — 2 × 2. Согласно формуле (4) получаем:


формула 23

В качестве упражнения проверьте, что в данном случае AB ≠ BA.

И еще один, более общий, пример:


формула 24

Единичная матрица

Существует особая матрица, называемая единичной матрицей (identity matrix). Это квадратная матрица все элементы которой равны нулю, за исключением тех, что расположены на главной диагонали — эти элементы равны единице. Ниже приведены примеры единичных матриц размером 2 × 2, 3 × 3 и 4 × 4:


формула 25

Единичная матрица действует как мультипликативное тождество:


формула 26

Следовательно, операция умножения на единичную матрицу не изменяет исходную матрицу. Более того, умножение на единичную матрицу это один из случаев, когда операция умножения матриц является коммутативной. Вы можете думать о единичной матрице как о числе 1 для матриц.


ПРИМЕР

Проверьте, что в результате умножения матрицы М = формула 27 на единичную матрицу размером 2 × 2 получается матрица М.


формула 28



Инвертирование матриц

В математике матриц нет аналога операции деления, но зато есть мультипликативная операция инвертирования. Приведенный ниже список обобщает важные особенности инвертирования:

Инверсия матриц применяется для нахождения искомой матрицы в уравнениях. Для примера возьмем выражение p' = pR и предположим, что нам известны p' и R, а требуется найти p. Сначала вычислим R-1 (подразумевается, что эта матрица существует). Получив R-1 можно вычислить p по следующему алгоритму:


формула 29

Описание способа вычисления инвертированной матрицы выходит за рамки этой книги, но вы можете его найти в любом учебнике линейной алгебры. В разделе «Базовые преобразования» мы получим инверсию нескольких матриц, с которыми будем работать. В раздеде «Матрицы в библиотеке D3DX» мы познакомимся с функцией библиотеки D3DX, которая может инвертировать матрицу за нас.

Завершая раздел об инвертировании матриц представим вам одно полезное свойство, касающееся инвертирования произведения: (AB)-1 = B-1A-1. Здесь подразумеваеся, что матрицы A и B могут быть инвертированы и что обе они — квадратные матрицы одинакового размера.

Транспонирование матриц

Транспонирование матрицы осуществляется путем перестановки ее строк и столбцов. Следовательно, результатом транспонирования матрицы m × n будет матрица n × m. Результат транспонирования матрицы M мы будем обозначать MT.


ПРИМЕР

Транспонируйте следующие две матрицы:


формула 30

Напомним, что транспонирование матрицы осуществляется путем перестановки ее строк и столбцов. Следовательно:


формула 31



Матрицы в библиотеке D3DX

Программируя приложения Direct3D мы чаще всего будем использовать матрицы 4 × 4 и векторы-строки 1 × 4. Обратите внимание, что использование матриц двух указанных размеров подразумевает, что определены результаты следующих операций умножения матриц:

Для представления вектора-строки 1 × 4 в библиотеке D3DX, мы будем использовать классы векторов D3DXVECTOR3 и D3DXVECTOR4. Конечно, в классе D3DXVECTOR3 только три компоненты, а не четыре. Однако обычно подразумевается что четвертая компонента равна нулю или единице (более подробно это будет обсуждаться в следующем разделе).

Для представления матриц 4 × 4 в библиотеке D3DX, мы используем класс D3DXMATRIX, определение которого выглядит следующим образом:

typedef struct D3DXMATRIX : public D3DMATRIX
{
    public:
        D3DXMATRIX() {};
        D3DXMATRIX(CONST FLOAT*);
        D3DXMATRIX(CONST D3DMATRIX&);
        D3DXMATRIX(FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
                   FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
                   FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
                   FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44);

        // получение элемента
        FLOAT& operator () (UINT Row, UINT Col);
        FLOAT operator () (UINT Row, UINT Col) const;

        // приведение типа
        operator FLOAT* ();
        operator CONST FLOAT* () const;

        // операторы присваивания
        D3DXMATRIX& operator *= (CONST D3DXMATRIX&);
        D3DXMATRIX& operator += (CONST D3DXMATRIX&);
        D3DXMATRIX& operator -= (CONST D3DXMATRIX&);
        D3DXMATRIX& operator *= (FLOAT);
        D3DXMATRIX& operator /= (FLOAT);

        // унарные операторы
        D3DXMATRIX operator + () const;
        D3DXMATRIX operator - () const;

        // бинарные операторы
        D3DXMATRIX operator * (CONST D3DXMATRIX&) const;
        D3DXMATRIX operator + (CONST D3DXMATRIX&) const;
        D3DXMATRIX operator - (CONST D3DXMATRIX&) const;
        D3DXMATRIX operator * (FLOAT) const;
        D3DXMATRIX operator / (FLOAT) const;

        friend D3DXMATRIX operator * (FLOAT, CONST D3DXMATRIX&);

        BOOL operator == (CONST D3DXMATRIX&) const;
        BOOL operator != (CONST D3DXMATRIX&) const;
} D3DXMATRIX, *LPD3DXMATRIX;

Класс D3DXMATRIX наследует элементы данных от простой структуры D3DMATRIX, определенной следующим образом:

typedef struct _D3DMATRIX {
    union {
        struct {
            float _11, _12, _13, _14;
            float _21, _22, _23, _24;
            float _31, _32, _33, _34;
            float _41, _42, _43, _44;
        };
        float m[4][4];
    };
} D3DMATRIX;

Обратите внимание, что в классе D3DXMATRIX есть десятки полезных операторов для проверки равенства, сложения и вычитания матриц, умножения матрицы на скаляр, преобразования типов и — самое главное — перемножения двух объектов типа D3DXMATRIX. Поскольку умножение матриц так важно, приведем пример кода, использующего этот оператор:

D3DXMATRIX A(Е);      // инициализация A
D3DXMATRIX B(Е);      // инициализация B
D3DXMATRIX C = A * B; // C = AB

Другим важным оператором класса D3DXMATRIX являются скобки, позволяющие легко получить доступ к отдельным элементам матрицы. Обратите внимание, что при использовании скобок нумерация элементов матрицы начинается с нуля, подобно нумерации элементов массива в языке С. Например, чтобы обратиться к верхнему левому элементу матрицы, следует написать:

D3DXMATRIX M;
M(0, 0) = 5.0f; // Присвоить первому элементу матрицы значение 5.0f.

Кроме того, библиотека D3DX предоставляет набор полезных функций, позволяющих инициализировать единичную матрицу D3DXMATRIX, транспонировать матрицу D3DXMATRIX и инвертировать матрицу D3DXMATRIX:

D3DXMATRIX *D3DXMatrixIdentity(
    D3DXMATRIX *pout        // Матрица, инициализируемая как единичная
  );

D3DXMATRIX M;
D3DXMatrixIdentity(&M);     // M = единичная матрица

D3DXMATRIX *D3DXMatrixTranspose(
    D3DXMATRIX *pOut,       // Результат транспонирования матрицы
    CONST D3DXMATRIX *pM    // Транспонируемая матрица
  );

D3DXMATRIX A(...);          // инициализация A
D3DXMATRIX B;
D3DXMatrixTranspose(&B, &A); // B = транспонированная(A)

D3DXMATRIX *D3DXMatrixInverse(
    D3DXMATRIX *pOut,      // возвращает результат инвертирования pM
    FLOAT *pDeterminant,   // детерминант, если необходим, иначе 0
    CONST D3DXMATRIX *pM   // инвертируемая матрица
  );

Функция инвертирования возвращает NULL, если переданная ей матрица не может быть инвертирована. Кроме того, в этой книге мы игнорируем второй параметр и всегда передаем в нем 0.

D3DXMATRIX A(...);        // инициализация A
D3DXMATRIX B;
D3DXMatrixInverse(&B, 0, &A); // B = инвертированная(A)


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

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