diff --git a/cogl/cogl/cogl-matrix.c b/cogl/cogl/cogl-matrix.c index d191bed9e..25858c7d0 100644 --- a/cogl/cogl/cogl-matrix.c +++ b/cogl/cogl/cogl-matrix.c @@ -1155,201 +1155,6 @@ cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse) } } -/* - * Generate a 4x4 transformation matrix from glRotate parameters, and - * post-multiply the input matrix by it. - * - * \author - * This function was contributed by Erich Boleyn (erich@uruk.org). - * Optimizations contributed by Rudolf Opalla (rudi@khm.de). - */ -static void -_cogl_matrix_rotate (CoglMatrix *matrix, - float angle, - float x, - float y, - float z) -{ - float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; - float m[16]; - gboolean optimized; - - s = sinf (angle * DEG2RAD); - c = cosf (angle * DEG2RAD); - - memcpy (m, identity, 16 * sizeof (float)); - optimized = FALSE; - -#define M(row,col) m[col*4+row] - - if (x == 0.0f) - { - if (y == 0.0f) - { - if (z != 0.0f) - { - optimized = TRUE; - /* rotate only around z-axis */ - M (0,0) = c; - M (1,1) = c; - if (z < 0.0f) - { - M (0,1) = s; - M (1,0) = -s; - } - else - { - M (0,1) = -s; - M (1,0) = s; - } - } - } - else if (z == 0.0f) - { - optimized = TRUE; - /* rotate only around y-axis */ - M (0,0) = c; - M (2,2) = c; - if (y < 0.0f) - { - M (0,2) = -s; - M (2,0) = s; - } - else - { - M (0,2) = s; - M (2,0) = -s; - } - } - } - else if (y == 0.0f) - { - if (z == 0.0f) - { - optimized = TRUE; - /* rotate only around x-axis */ - M (1,1) = c; - M (2,2) = c; - if (x < 0.0f) - { - M (1,2) = s; - M (2,1) = -s; - } - else - { - M (1,2) = -s; - M (2,1) = s; - } - } - } - - if (!optimized) - { - const float mag = sqrtf (x * x + y * y + z * z); - - if (mag <= 1.0e-4) - { - /* no rotation, leave mat as-is */ - return; - } - - x /= mag; - y /= mag; - z /= mag; - - - /* - * Arbitrary axis rotation matrix. - * - * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied - * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation - * (which is about the X-axis), and the two composite transforms - * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary - * from the arbitrary axis to the X-axis then back. They are - * all elementary rotations. - * - * Rz' is a rotation about the Z-axis, to bring the axis vector - * into the x-z plane. Then Ry' is applied, rotating about the - * Y-axis to bring the axis vector parallel with the X-axis. The - * rotation about the X-axis is then performed. Ry and Rz are - * simply the respective inverse transforms to bring the arbitrary - * axis back to it's original orientation. The first transforms - * Rz' and Ry' are considered inverses, since the data from the - * arbitrary axis gives you info on how to get to it, not how - * to get away from it, and an inverse must be applied. - * - * The basic calculation used is to recognize that the arbitrary - * axis vector (x, y, z), since it is of unit length, actually - * represents the sines and cosines of the angles to rotate the - * X-axis to the same orientation, with theta being the angle about - * Z and phi the angle about Y (in the order described above) - * as follows: - * - * cos ( theta ) = x / sqrt ( 1 - z^2 ) - * sin ( theta ) = y / sqrt ( 1 - z^2 ) - * - * cos ( phi ) = sqrt ( 1 - z^2 ) - * sin ( phi ) = z - * - * Note that cos ( phi ) can further be inserted to the above - * formulas: - * - * cos ( theta ) = x / cos ( phi ) - * sin ( theta ) = y / sin ( phi ) - * - * ...etc. Because of those relations and the standard trigonometric - * relations, it is pssible to reduce the transforms down to what - * is used below. It may be that any primary axis chosen will give the - * same results (modulo a sign convention) using this method. - * - * Particularly nice is to notice that all divisions that might - * have caused trouble when parallel to certain planes or - * axis go away with care paid to reducing the expressions. - * After checking, it does perform correctly under all cases, since - * in all the cases of division where the denominator would have - * been zero, the numerator would have been zero as well, giving - * the expected result. - */ - - xx = x * x; - yy = y * y; - zz = z * z; - xy = x * y; - yz = y * z; - zx = z * x; - xs = x * s; - ys = y * s; - zs = z * s; - one_c = 1.0f - c; - - /* We already hold the identity-matrix so we can skip some statements */ - M (0,0) = (one_c * xx) + c; - M (0,1) = (one_c * xy) - zs; - M (0,2) = (one_c * zx) + ys; - /* M (0,3) = 0.0f; */ - - M (1,0) = (one_c * xy) + zs; - M (1,1) = (one_c * yy) + c; - M (1,2) = (one_c * yz) - xs; - /* M (1,3) = 0.0f; */ - - M (2,0) = (one_c * zx) - ys; - M (2,1) = (one_c * yz) + xs; - M (2,2) = (one_c * zz) + c; - /* M (2,3) = 0.0f; */ - - /* - M (3,0) = 0.0f; - M (3,1) = 0.0f; - M (3,2) = 0.0f; - M (3,3) = 1.0f; - */ - } -#undef M - - matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_ROTATION); -} - void cogl_matrix_rotate (CoglMatrix *matrix, float angle, @@ -1357,7 +1162,22 @@ cogl_matrix_rotate (CoglMatrix *matrix, float y, float z) { - _cogl_matrix_rotate (matrix, angle, x, y, z); + graphene_matrix_t rotation; + graphene_matrix_t m; + graphene_vec3_t axis; + unsigned long flags; + + flags = matrix->flags; + + cogl_matrix_to_graphene_matrix (matrix, &m); + graphene_vec3_init (&axis, x, y, z); + graphene_matrix_init_rotate (&rotation, angle, &axis); + graphene_matrix_multiply (&rotation, &m, &m); + graphene_matrix_to_cogl_matrix (&m, matrix); + + flags |= MAT_FLAG_ROTATION | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE; + matrix->flags = flags; + _COGL_MATRIX_DEBUG_PRINT (matrix); }