Программируя приложения Direct3D мы чаще всего будем использовать матрицы 4 × 4 и векторы-строки 1 × 4. Обратите внимание, что использование матриц двух указанных размеров подразумевает, что определены результаты следующих операций умножения матриц:
Умножение вектора-строки на матрицу. То есть, если v — это вектор-строка 1 × 4, а T — это матрица 4 × 4, произведение vT определено и представляет собой вектор-строку 1 × 4.
Умножение матрицы на матрицу. То есть, если T — это матрица 4 × 4 и R — это матрица 4 × 4, произведения TR и RT определены и оба являются матрицами 4 × 4. Обратите внимание, что произведение TR не обязательно равно RT, поскольку операция умножения матриц не коммутативна.
Для представления вектора-строки 1 × 4 в библиотеке D3DX, мы будем использовать классы векторов D3DXVECTOR3 и D3DXVECTOR4. Конечно, в классе D3DXVECTOR3 только три компоненты, а не четыре. Однако обычно подразумевается что четвертая компонента равна нулю или единице (более подробно это будет обсуждаться в следующем разделе).
Для представления матриц 4 × 4 в библиотеке D3DX, мы используем класс D3DXMATRIX, определение которого выглядит следующим образом:
Обратите внимание, что в классе 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 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)