+static void d3drm_matrix_multiply_affine(struct d3drm_matrix *dst,
+ const struct d3drm_matrix *src1, const struct d3drm_matrix *src2)
+{
+ struct d3drm_matrix tmp;
+
+ tmp._11 = src1->_11 * src2->_11 + src1->_12 * src2->_21 + src1->_13 * src2->_31;
+ tmp._12 = src1->_11 * src2->_12 + src1->_12 * src2->_22 + src1->_13 * src2->_32;
+ tmp._13 = src1->_11 * src2->_13 + src1->_12 * src2->_23 + src1->_13 * src2->_33;
+ tmp._14 = 0.0f;
+
+ tmp._21 = src1->_21 * src2->_11 + src1->_22 * src2->_21 + src1->_23 * src2->_31;
+ tmp._22 = src1->_21 * src2->_12 + src1->_22 * src2->_22 + src1->_23 * src2->_32;
+ tmp._23 = src1->_21 * src2->_13 + src1->_22 * src2->_23 + src1->_23 * src2->_33;
+ tmp._24 = 0.0f;
+
+ tmp._31 = src1->_31 * src2->_11 + src1->_32 * src2->_21 + src1->_33 * src2->_31;
+ tmp._32 = src1->_31 * src2->_12 + src1->_32 * src2->_22 + src1->_33 * src2->_32;
+ tmp._33 = src1->_31 * src2->_13 + src1->_32 * src2->_23 + src1->_33 * src2->_33;
+ tmp._34 = 0.0f;
+
+ tmp._41 = src1->_41 * src2->_11 + src1->_42 * src2->_21 + src1->_43 * src2->_31 + src2->_41;
+ tmp._42 = src1->_41 * src2->_12 + src1->_42 * src2->_22 + src1->_43 * src2->_32 + src2->_42;
+ tmp._43 = src1->_41 * src2->_13 + src1->_42 * src2->_23 + src1->_43 * src2->_33 + src2->_43;
+ tmp._44 = 1.0f;
+
+ *dst = tmp;
+}
+
+static void d3drm_matrix_set_rotation(struct d3drm_matrix *matrix, D3DVECTOR *axis, float theta)
+{
+ float sin_theta, cos_theta, vers_theta;
+
+ D3DRMVectorNormalize(axis);
+ sin_theta = sinf(theta);
+ cos_theta = cosf(theta);
+ vers_theta = 1.0f - cos_theta;
+
+ matrix->_11 = vers_theta * axis->u1.x * axis->u1.x + cos_theta;
+ matrix->_21 = vers_theta * axis->u1.x * axis->u2.y - sin_theta * axis->u3.z;
+ matrix->_31 = vers_theta * axis->u1.x * axis->u3.z + sin_theta * axis->u2.y;
+ matrix->_41 = 0.0f;
+
+ matrix->_12 = vers_theta * axis->u2.y * axis->u1.x + sin_theta * axis->u3.z;
+ matrix->_22 = vers_theta * axis->u2.y * axis->u2.y + cos_theta;
+ matrix->_32 = vers_theta * axis->u2.y * axis->u3.z - sin_theta * axis->u1.x;
+ matrix->_42 = 0.0f;
+
+ matrix->_13 = vers_theta * axis->u3.z * axis->u1.x - sin_theta * axis->u2.y;
+ matrix->_23 = vers_theta * axis->u3.z * axis->u2.y + sin_theta * axis->u1.x;
+ matrix->_33 = vers_theta * axis->u3.z * axis->u3.z + cos_theta;
+ matrix->_43 = 0.0f;
+
+ matrix->_14 = 0.0f;
+ matrix->_24 = 0.0f;
+ matrix->_34 = 0.0f;
+ matrix->_44 = 1.0f;
+}
+
+static void d3drm_vector_transform_affine(D3DVECTOR *dst, const D3DVECTOR *v, const struct d3drm_matrix *m)
+{
+ D3DVECTOR tmp;
+
+ tmp.u1.x = v->u1.x * m->_11 + v->u2.y * m->_21 + v->u3.z * m->_31 + m->_41;
+ tmp.u2.y = v->u1.x * m->_12 + v->u2.y * m->_22 + v->u3.z * m->_32 + m->_42;
+ tmp.u3.z = v->u1.x * m->_13 + v->u2.y * m->_23 + v->u3.z * m->_33 + m->_43;
+
+ *dst = tmp;
+}
+