Последовательность преобразований можно реализовать путем свертки отдельных матриц справа налево или слева направо в зависимости от порядка, в котором заданы матричные представления. Разумеется, крайний справа член произведения матриц всегда является первым преобразованием, применяемым к объекту, а крайний слева - последним. Данный порядок нужно использовать, поскольку координаты точек представляются как четырехэлементные векторы-столбцы, на которые слева действует сложная матрица преобразования 4 на 4.
В приведенной ниже программе приводятся примеры процедур построения матрицы трехмерного сложного преобразования. Чтобы получить одну сложную матрицу (инициализируется как единичная), в заданном порядке объединяются три базовых геометрических преобразования. В данном примере вначале выполняется поворот, затем масштабирование, потом трансляция. Сложная матрица вычисляется слева направо, так что преобразования вызываются в порядке их применения. Следовательно, новая построенная матрица присоединяется слева к предыдущей, и в результате обновляется матрица произведения.
class wcPt3D {
public :
GLfloat x, y, z;
} ;
typedef GLfloat Matrix4x4 [4][4]; Matrix4x4 matComposite;
/* Строится единичная матрица 4 на 4. */
void matrix4x4SetIdentity (Matrix4x4 matldent4x4)
{
GLint row, col;
for (row = 0; row < 4; row++)
for (col = 0; col < 4 ; col++)
matldent4x4 [row][col] = (row == col);
}
/* Матрица ml умножается слева на матрицу m2, результат
* записывается в m2.
*/
void matrix4x4PreMultiply (Matrix4x4 ml, Matrix4x4 m2)
{
GLint row, col;
Matrix4x4 matTemp;
for (row = 0; row < 4; row++)
for (col = 0; col < 4 ; col++)
matTemp [row][col] = ml [row][0] * m2 [0][col] +
ml [row][l] * m2 [l][col] + ml [row][2] * m2 [2][col] + ml [row][3] * m2 [3][col];
for (row = 0; row < 4; row++) for (col = 0; col < 4; col++)
m2 [row][col] = matTemp [row][col];
}
/* Процедура генерации матрицы трехмерной трансляции. */ void translate3D (GLfloat tx, GLfloat ty, GLfloat tz)
{
Matrix4x4 matTransl3D;
/* Матрица трансляции инициализируется как единичная. */ matrix4x4SetIdentity (matTransl3D);
matTransl3D [0][3] = tx;
matTransl3D [1][3] = ty;
matTransl3D [2][3] = tz;
/* Выполняется свертка матрицы matTransl3D со сложной
* матрицей.
*/
matrix4x4PreMultiply (matTransl3D, matComposite);
/* Процедура генерации матрицы поворота вокруг кватерниона. */ void rotate3D (wcPt3D pi, wcPt3D p2, GLfloat radianAngle)
{
Matrix4x4 matQuatRot;
float axisVectLength = sqrt ((p2.x - pl.x) * (p2.x - pl.x) +
(p2.y - pl.y) * (p2.y - pl.y) +
(p2.z - pl.z) * (p2.z - pl.z));
float cosA = cosf (radianAngle); float oneC = 1 - cosA; float sinA = sinf (radianAngle);
float ux = (p2.x - pl.x) / axisVectLength;