diff --git a/clutter/clutter/clutter-base-types.c b/clutter/clutter/clutter-base-types.c index fcbcd2ec7..1d447ed22 100644 --- a/clutter/clutter/clutter-base-types.c +++ b/clutter/clutter/clutter-base-types.c @@ -126,65 +126,15 @@ clutter_matrix_progress (const GValue *a, { const ClutterMatrix *matrix1 = g_value_get_boxed (a); const ClutterMatrix *matrix2 = g_value_get_boxed (b); - graphene_point3d_t scale1 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f); - float shear1[3] = { 0.f, 0.f, 0.f }; - graphene_point3d_t rotate1 = GRAPHENE_POINT3D_INIT_ZERO; - graphene_point3d_t translate1 = GRAPHENE_POINT3D_INIT_ZERO; - ClutterVertex4 perspective1 = { 0.f, 0.f, 0.f, 0.f }; - graphene_point3d_t scale2 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f); - float shear2[3] = { 0.f, 0.f, 0.f }; - graphene_point3d_t rotate2 = GRAPHENE_POINT3D_INIT_ZERO; - graphene_point3d_t translate2 = GRAPHENE_POINT3D_INIT_ZERO; - ClutterVertex4 perspective2 = { 0.f, 0.f, 0.f, 0.f }; - graphene_point3d_t scale_res = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f); - float shear_res = 0.f; - graphene_point3d_t rotate_res = GRAPHENE_POINT3D_INIT_ZERO; - graphene_point3d_t translate_res = GRAPHENE_POINT3D_INIT_ZERO; - ClutterVertex4 perspective_res = { 0.f, 0.f, 0.f, 0.f }; + graphene_matrix_t m1, m2, m; ClutterMatrix res; - clutter_matrix_init_identity (&res); + cogl_matrix_to_graphene_matrix (matrix1, &m1); + cogl_matrix_to_graphene_matrix (matrix2, &m2); - _clutter_util_matrix_decompose (matrix1, - &scale1, shear1, &rotate1, &translate1, - &perspective1); - _clutter_util_matrix_decompose (matrix2, - &scale2, shear2, &rotate2, &translate2, - &perspective2); + graphene_matrix_interpolate (&m1, &m2, progress, &m); - /* perspective */ - _clutter_util_vertex4_interpolate (&perspective1, &perspective2, progress, &perspective_res); - res.wx = perspective_res.x; - res.wy = perspective_res.y; - res.wz = perspective_res.z; - res.ww = perspective_res.w; - - /* translation */ - graphene_point3d_interpolate (&translate1, &translate2, progress, &translate_res); - cogl_matrix_translate (&res, translate_res.x, translate_res.y, translate_res.z); - - /* rotation */ - graphene_point3d_interpolate (&rotate1, &rotate2, progress, &rotate_res); - cogl_matrix_rotate (&res, rotate_res.x, 1.0f, 0.0f, 0.0f); - cogl_matrix_rotate (&res, rotate_res.y, 0.0f, 1.0f, 0.0f); - cogl_matrix_rotate (&res, rotate_res.z, 0.0f, 0.0f, 1.0f); - - /* skew */ - shear_res = shear1[2] + (shear2[2] - shear1[2]) * progress; /* YZ */ - if (shear_res != 0.f) - _clutter_util_matrix_skew_yz (&res, shear_res); - - shear_res = shear1[1] + (shear2[1] - shear1[1]) * progress; /* XZ */ - if (shear_res != 0.f) - _clutter_util_matrix_skew_xz (&res, shear_res); - - shear_res = shear1[0] + (shear2[0] - shear1[0]) * progress; /* XY */ - if (shear_res != 0.f) - _clutter_util_matrix_skew_xy (&res, shear_res); - - /* scale */ - graphene_point3d_interpolate (&scale1, &scale2, progress, &scale_res); - cogl_matrix_scale (&res, scale_res.x, scale_res.y, scale_res.z); + graphene_matrix_to_cogl_matrix (&m, &res); g_value_set_boxed (retval, &res); diff --git a/clutter/clutter/clutter-private.h b/clutter/clutter/clutter-private.h index 2465508cf..b5ff077c9 100644 --- a/clutter/clutter/clutter-private.h +++ b/clutter/clutter/clutter-private.h @@ -274,12 +274,6 @@ struct _ClutterVertex4 float w; }; -void -_clutter_util_vertex4_interpolate (const ClutterVertex4 *a, - const ClutterVertex4 *b, - double progress, - ClutterVertex4 *res); - #define CLUTTER_MATRIX_INIT_IDENTITY { \ 1.0f, 0.0f, 0.0f, 0.0f, \ 0.0f, 1.0f, 0.0f, 0.0f, \ @@ -287,22 +281,6 @@ _clutter_util_vertex4_interpolate (const ClutterVertex4 *a, 0.0f, 0.0f, 0.0f, 1.0f, \ } -float _clutter_util_matrix_determinant (const ClutterMatrix *matrix); - -void _clutter_util_matrix_skew_xy (ClutterMatrix *matrix, - float factor); -void _clutter_util_matrix_skew_xz (ClutterMatrix *matrix, - float factor); -void _clutter_util_matrix_skew_yz (ClutterMatrix *matrix, - float factor); - -gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src, - graphene_point3d_t *scale_p, - float shear_p[3], - graphene_point3d_t *rotate_p, - graphene_point3d_t *translate_p, - ClutterVertex4 *perspective_p); - typedef struct _ClutterPlane { graphene_vec3_t v0; diff --git a/clutter/clutter/clutter-util.c b/clutter/clutter/clutter-util.c index 85e7d75f4..daf87b5d6 100644 --- a/clutter/clutter/clutter-util.c +++ b/clutter/clutter/clutter-util.c @@ -210,310 +210,6 @@ _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1, } } -float -_clutter_util_matrix_determinant (const ClutterMatrix *matrix) -{ - return matrix->xw * matrix->yz * matrix->zy * matrix->wz - - matrix->xz * matrix->yw * matrix->zy * matrix->wz - - matrix->xw * matrix->yy * matrix->zz * matrix->wz - + matrix->xy * matrix->yw * matrix->zz * matrix->wz - + matrix->xz * matrix->yy * matrix->zw * matrix->wz - - matrix->xy * matrix->yz * matrix->zw * matrix->wz - - matrix->xw * matrix->yz * matrix->zx * matrix->wy - + matrix->xz * matrix->yw * matrix->zx * matrix->wy - + matrix->xw * matrix->yx * matrix->zz * matrix->wy - - matrix->xx * matrix->yw * matrix->zz * matrix->wy - - matrix->xz * matrix->yx * matrix->zw * matrix->wy - + matrix->xx * matrix->yz * matrix->zw * matrix->wy - + matrix->xw * matrix->yy * matrix->zx * matrix->wz - - matrix->xy * matrix->yw * matrix->zx * matrix->wz - - matrix->xw * matrix->yx * matrix->zy * matrix->wz - + matrix->xx * matrix->yw * matrix->zy * matrix->wz - + matrix->xy * matrix->yx * matrix->zw * matrix->wz - - matrix->xx * matrix->yy * matrix->zw * matrix->wz - - matrix->xz * matrix->yy * matrix->zx * matrix->ww - + matrix->xy * matrix->yz * matrix->zx * matrix->ww - + matrix->xz * matrix->yx * matrix->zy * matrix->ww - - matrix->xx * matrix->yz * matrix->zy * matrix->ww - - matrix->xy * matrix->yx * matrix->zz * matrix->ww - + matrix->xx * matrix->yy * matrix->zz * matrix->ww; -} - -static void -_clutter_util_matrix_transpose_vector4_transform (const ClutterMatrix *matrix, - const ClutterVertex4 *point, - ClutterVertex4 *res) -{ - res->x = matrix->xx * point->x - + matrix->xy * point->y - + matrix->xz * point->z - + matrix->xw * point->w; - - res->y = matrix->yx * point->x - + matrix->yy * point->y - + matrix->yz * point->z - + matrix->yw * point->w; - - res->z = matrix->zx * point->x - + matrix->zy * point->y - + matrix->zz * point->z - + matrix->zw * point->w; - - res->w = matrix->wz * point->x - + matrix->wy * point->w - + matrix->wz * point->z - + matrix->ww * point->w; -} - -void -_clutter_util_matrix_skew_xy (ClutterMatrix *matrix, - float factor) -{ - matrix->yx += matrix->xx * factor; - matrix->yy += matrix->xy * factor; - matrix->yz += matrix->xz * factor; - matrix->yw += matrix->xw * factor; -} - -void -_clutter_util_matrix_skew_xz (ClutterMatrix *matrix, - float factor) -{ - matrix->zx += matrix->xx * factor; - matrix->zy += matrix->xy * factor; - matrix->zz += matrix->xz * factor; - matrix->zw += matrix->xw * factor; -} - -void -_clutter_util_matrix_skew_yz (ClutterMatrix *matrix, - float factor) -{ - matrix->zx += matrix->yx * factor; - matrix->zy += matrix->yy * factor; - matrix->zz += matrix->yz * factor; - matrix->zw += matrix->yw * factor; -} - -static void -_clutter_util_vertex_combine (const graphene_point3d_t *a, - const graphene_point3d_t *b, - double ascl, - double bscl, - graphene_point3d_t *res) -{ - res->x = (ascl * a->x) + (bscl * b->x); - res->y = (ascl * a->y) + (bscl * b->y); - res->z = (ascl * a->z) + (bscl * b->z); -} - -void -_clutter_util_vertex4_interpolate (const ClutterVertex4 *a, - const ClutterVertex4 *b, - double progress, - ClutterVertex4 *res) -{ - res->x = a->x + (b->x - a->x) * progress; - res->y = a->y + (b->y - a->y) * progress; - res->z = a->z + (b->z - a->z) * progress; - res->w = a->w + (b->w - a->w) * progress; -} - -/*< private > - * clutter_util_matrix_decompose: - * @src: the matrix to decompose - * @scale_p: (out caller-allocates): return location for a vertex containing - * the scaling factors - * @shear_p: (out) (array length=3): return location for an array of 3 - * elements containing the skew factors (XY, XZ, and YZ respectively) - * @rotate_p: (out caller-allocates): return location for a vertex containing - * the Euler angles - * @translate_p: (out caller-allocates): return location for a vertex - * containing the translation vector - * @perspective_p: (out caller-allocates: return location for a 4D vertex - * containing the perspective - * - * Decomposes a #ClutterMatrix into the transformations that compose it. - * - * This code is based on the matrix decomposition algorithm as published in - * the CSS Transforms specification by the W3C CSS working group, available - * at http://www.w3.org/TR/css3-transforms/. - * - * The algorithm, in turn, is based on the "unmatrix" method published in - * "Graphics Gems II, edited by Jim Arvo", which is available at: - * http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c - * - * Return value: %TRUE if the decomposition was successful, and %FALSE - * if the matrix is singular - */ -gboolean -_clutter_util_matrix_decompose (const ClutterMatrix *src, - graphene_point3d_t *scale_p, - float shear_p[3], - graphene_point3d_t *rotate_p, - graphene_point3d_t *translate_p, - ClutterVertex4 *perspective_p) -{ - CoglMatrix matrix = *src; - CoglMatrix perspective; - ClutterVertex4 vertex_tmp; - graphene_point3d_t row[3], pdum; - int i, j; - -#define XY_SHEAR 0 -#define XZ_SHEAR 1 -#define YZ_SHEAR 2 -#define MAT(m,r,c) ((float *)(m))[(c) * 4 + (r)] - - /* normalize the matrix */ - if (matrix.ww == 0.f) - return FALSE; - - for (i = 0; i < 4; i++) - { - for (j = 0; j < 4; j++) - { - MAT (&matrix, j, i) /= MAT (&matrix, 3, 3); - } - } - - /* perspective is used to solve for perspective, but it also provides - * an easy way to test for singularity of the upper 3x3 component - */ - perspective = matrix; - - /* transpose */ - MAT (&perspective, 3, 0) = 0.f; - MAT (&perspective, 3, 1) = 0.f; - MAT (&perspective, 3, 2) = 0.f; - MAT (&perspective, 3, 3) = 1.f; - - if (_clutter_util_matrix_determinant (&perspective) == 0.f) - return FALSE; - - if (MAT (&matrix, 3, 0) != 0.f || - MAT (&matrix, 3, 1) != 0.f || - MAT (&matrix, 3, 2) != 0.f) - { - CoglMatrix perspective_inv; - ClutterVertex4 p; - - vertex_tmp.x = MAT (&matrix, 3, 0); - vertex_tmp.y = MAT (&matrix, 3, 1); - vertex_tmp.z = MAT (&matrix, 3, 2); - vertex_tmp.w = MAT (&matrix, 3, 3); - - /* solve the equation by inverting perspective... */ - cogl_matrix_get_inverse (&perspective, &perspective_inv); - - /* ... and multiplying vertex_tmp by the inverse */ - _clutter_util_matrix_transpose_vector4_transform (&perspective_inv, - &vertex_tmp, - &p); - - *perspective_p = p; - - /* clear the perspective part */ - MAT (&matrix, 3, 0) = 0.0f; - MAT (&matrix, 3, 1) = 0.0f; - MAT (&matrix, 3, 2) = 0.0f; - MAT (&matrix, 3, 3) = 1.0f; - } - else - { - /* no perspective */ - perspective_p->x = 0.0f; - perspective_p->y = 0.0f; - perspective_p->z = 0.0f; - perspective_p->w = 1.0f; - } - - /* translation */ - translate_p->x = MAT (&matrix, 0, 3); - MAT (&matrix, 0, 3) = 0.f; - translate_p->y = MAT (&matrix, 1, 3); - MAT (&matrix, 1, 3) = 0.f; - translate_p->z = MAT (&matrix, 2, 3); - MAT (&matrix, 2, 3) = 0.f; - - /* scale and shear; we split the upper 3x3 matrix into rows */ - for (i = 0; i < 3; i++) - { - row[i].x = MAT (&matrix, i, 0); - row[i].y = MAT (&matrix, i, 1); - row[i].z = MAT (&matrix, i, 2); - } - - /* compute scale.x and normalize the first row */ - scale_p->x = graphene_point3d_length (&row[0]); - graphene_point3d_normalize (&row[0], &row[0]); - - /* compute XY shear and make the second row orthogonal to the first */ - shear_p[XY_SHEAR] = graphene_point3d_dot (&row[0], &row[1]); - _clutter_util_vertex_combine (&row[1], &row[0], - 1.0, -shear_p[XY_SHEAR], - &row[1]); - - /* compute the Y scale and normalize the second row */ - scale_p->y = graphene_point3d_length (&row[1]); - graphene_point3d_normalize (&row[1], &row[1]); - shear_p[XY_SHEAR] /= scale_p->y; - - /* compute XZ and YZ shears, orthogonalize the third row */ - shear_p[XZ_SHEAR] = graphene_point3d_dot (&row[0], &row[2]); - _clutter_util_vertex_combine (&row[2], &row[0], - 1.0, -shear_p[XZ_SHEAR], - &row[2]); - - shear_p[YZ_SHEAR] = graphene_point3d_dot (&row[1], &row[2]); - _clutter_util_vertex_combine (&row[2], &row[1], - 1.0, -shear_p[YZ_SHEAR], - &row[2]); - - /* get the Z scale and normalize the third row*/ - scale_p->z = graphene_point3d_length (&row[2]); - graphene_point3d_normalize (&row[2], &row[2]); - shear_p[XZ_SHEAR] /= scale_p->z; - shear_p[YZ_SHEAR] /= scale_p->z; - - /* at this point, the matrix (inside row[]) is orthonormal. - * check for a coordinate system flip; if the determinant - * is -1, then negate the matrix and scaling factors - */ - graphene_point3d_cross (&row[1], &row[2], &pdum); - if (graphene_point3d_dot (&row[0], &pdum) < 0.f) - { - scale_p->x *= -1.f; - - for (i = 0; i < 3; i++) - { - row[i].x *= -1.f; - row[i].y *= -1.f; - row[i].z *= -1.f; - } - } - - /* now get the rotations out */ - rotate_p->y = asinf (-row[0].z); - if (cosf (rotate_p->y) != 0.f) - { - rotate_p->x = atan2f (row[1].z, row[2].z); - rotate_p->z = atan2f (row[0].y, row[0].x); - } - else - { - rotate_p->x = atan2f (-row[2].x, row[1].y); - rotate_p->z = 0.f; - } - -#undef XY_SHEAR -#undef XZ_SHEAR -#undef YZ_SHEAR -#undef MAT - - return TRUE; -} - typedef struct { GType value_type;