From 1aac180e8dc20d9d7ef92bfda754f24024ce7aeb Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 27 Feb 2019 20:42:02 -0300 Subject: [PATCH] cogl/matrix: Rotate using graphene --- cogl/cogl/cogl-matrix.c | 221 ++-------------------------------------- 1 file changed, 11 insertions(+), 210 deletions(-) diff --git a/cogl/cogl/cogl-matrix.c b/cogl/cogl/cogl-matrix.c index 97034ee7a..f61e33b1f 100644 --- a/cogl/cogl/cogl-matrix.c +++ b/cogl/cogl/cogl-matrix.c @@ -98,20 +98,6 @@ static float identity[16] = { 0.0, 0.0, 0.0, 1.0 }; -static void -matrix_multiply_array_with_flags (CoglMatrix *result, - const float *array) -{ - graphene_matrix_t m1, m2, res; - - cogl_matrix_to_graphene_matrix (result, &m1); - graphene_matrix_init_from_float (&m2, array); - - graphene_matrix_multiply (&m2, &m1, &res); - graphene_matrix_to_cogl_matrix (&res, result); -} - - void cogl_matrix_multiply (CoglMatrix *result, const CoglMatrix *a, @@ -166,201 +152,6 @@ cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse) return success; } -/* - * 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 thie 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); -} - void cogl_matrix_rotate (CoglMatrix *matrix, float angle, @@ -368,7 +159,17 @@ cogl_matrix_rotate (CoglMatrix *matrix, float y, float z) { - _cogl_matrix_rotate (matrix, angle, x, y, z); + graphene_matrix_t rotation, m; + graphene_vec3_t r; + + cogl_matrix_to_graphene_matrix (matrix, &m); + graphene_matrix_transpose (&m, &m); + + graphene_matrix_init_rotate (&rotation, angle, graphene_vec3_init (&r, x, y, z)); + graphene_matrix_multiply (&rotation, &m, &m); + + graphene_matrix_to_cogl_matrix (&m, matrix); + _COGL_MATRIX_DEBUG_PRINT (matrix); }