void graphene_matrix_untransform_bounds (const graphene_matrix_t *m, const graphene_rect_t *r, const graphene_rect_t *bounds, graphene_rect_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; graphene_rect_t rect; g_return_if_fail (m != NULL && r != NULL); g_return_if_fail (bounds != NULL); g_return_if_fail (res != NULL); if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_bounds (&inverse, r, res); return; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_intersection (r, &bounds_t, &rect)) { graphene_rect_init (res, 0.f, 0.f, 0.f, 0.f); return; } graphene_matrix_inverse (m, &inverse); graphene_matrix_project_rect_bounds (&inverse, &rect, res); }
gboolean graphene_matrix_untransform_point (const graphene_matrix_t *m, const graphene_point_t *p, const graphene_rect_t *bounds, graphene_point_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; g_return_val_if_fail (m != NULL, FALSE); g_return_val_if_fail (p != NULL, FALSE); g_return_val_if_fail (bounds != NULL, FALSE); g_return_val_if_fail (res != NULL, FALSE); if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_point (&inverse, p, res); return TRUE; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_contains_point (&bounds_t, p)) return FALSE; graphene_matrix_inverse (m, &inverse); graphene_matrix_project_point (&inverse, p, res); return TRUE; }
/** * graphene_matrix_untransform_point: * @m: a #graphene_matrix_t * @p: a #graphene_point_t * @bounds: the bounds of the transformation * @res: (out caller-allocates): return location for the * untransformed point * * Undoes the transformation of a #graphene_point_t using the * given matrix, within the given rectangular @bounds. * * Returns: %true if the point was successfully untransformed * * Since: 1.0 */ bool graphene_matrix_untransform_point (const graphene_matrix_t *m, const graphene_point_t *p, const graphene_rect_t *bounds, graphene_point_t *res) { graphene_matrix_t inverse; graphene_rect_t bounds_t; if (graphene_matrix_is_2d (m)) { graphene_matrix_inverse (m, &inverse); graphene_matrix_transform_point (&inverse, p, res); return true; } graphene_matrix_transform_bounds (m, bounds, &bounds_t); if (!graphene_rect_contains_point (&bounds_t, p)) return false; graphene_matrix_inverse (m, &inverse); graphene_matrix_project_point (&inverse, p, res); return true; }
/** * graphene_matrix_interpolate: * @a: ... * @b: ... * @factor: ... * @res: (out caller-allocates): ... * * ... * * Since: 1.0 */ void graphene_matrix_interpolate (const graphene_matrix_t *a, const graphene_matrix_t *b, double factor, graphene_matrix_t *res) { graphene_point3d_t scale_a = { 1.f, 1.f, 1.f }, translate_a; graphene_vec4_t perspective_a; graphene_quaternion_t rotate_a; float shear_a[3] = { 0.f, 0.f, 0.f }; graphene_point3d_t scale_b = { 1.f, 1.f, 1.f }, translate_b; graphene_vec4_t perspective_b; graphene_quaternion_t rotate_b; float shear_b[3] = { 0.f, 0.f, 0.f }; graphene_point3d_t scale_r = { 1.f, 1.f, 1.f }, translate_r; graphene_quaternion_t rotate_r; graphene_matrix_t tmp; float shear; g_return_if_fail (a != NULL && b != NULL); g_return_if_fail (res != NULL); if (graphene_matrix_is_2d (a) && graphene_matrix_is_2d (b)) { graphene_vec4_init (&perspective_a, 0.f, 0.f, 0.f, 1.f); graphene_vec4_init (&perspective_b, 0.f, 0.f, 0.f, 1.f); matrix_decompose_2d (a, &scale_a, shear_a, &rotate_a, &translate_a); matrix_decompose_2d (b, &scale_b, shear_b, &rotate_b, &translate_b); } else { matrix_decompose_3d (a, &scale_a, shear_a, &rotate_a, &translate_a, &perspective_a); matrix_decompose_3d (b, &scale_b, shear_b, &rotate_b, &translate_b, &perspective_b); } res->value.w = graphene_simd4f_interpolate (perspective_a.value, perspective_b.value, factor); graphene_point3d_interpolate (&translate_a, &translate_b, factor, &translate_r); graphene_matrix_translate (res, &translate_r); graphene_quaternion_slerp (&rotate_a, &rotate_b, factor, &rotate_r); graphene_quaternion_to_matrix (&rotate_r, &tmp); if (!graphene_matrix_is_identity (&tmp)) graphene_matrix_multiply (&tmp, res, res); shear = shear_a[YZ_SHEAR] + (shear_b[YZ_SHEAR] - shear_a[YZ_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_yz (res, shear); shear = shear_a[XZ_SHEAR] + (shear_b[XZ_SHEAR] - shear_a[XZ_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_xz (res, shear); shear = shear_a[XY_SHEAR] + (shear_b[XY_SHEAR] - shear_a[XY_SHEAR]) * factor; if (shear != 0.f) graphene_matrix_skew_xy (res, shear); graphene_point3d_interpolate (&scale_a, &scale_b, factor, &scale_r); if (scale_r.x != 1.f && scale_r.y != 1.f && scale_r.z != 0.f) graphene_matrix_scale (res, scale_r.x, scale_r.y, scale_r.z); }