Compare commits
2 Commits
clutter-1.
...
wip/interp
Author | SHA1 | Date |
---|---|---|
Emmanuele Bassi | b0c2d81014 | |
Emmanuele Bassi | afc797e196 |
|
@ -1054,6 +1054,9 @@ static inline void clutter_actor_set_margin_internal (ClutterActor *self,
|
|||
gfloat margin,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static void clutter_actor_set_child_transform_internal (ClutterActor *self,
|
||||
const ClutterMatrix *transform);
|
||||
|
||||
/* Helper macro which translates by the anchor coord, applies the
|
||||
given transformation and then translates back */
|
||||
#define TRANSFORM_ABOUT_ANCHOR_COORD(a,m,c,_transform) G_STMT_START { \
|
||||
|
@ -4224,6 +4227,7 @@ _clutter_actor_get_transform_info (ClutterActor *self)
|
|||
info = g_slice_new (ClutterTransformInfo);
|
||||
|
||||
*info = default_transform_info;
|
||||
clutter_matrix_init_identity (&info->child_transform);
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (self), quark_actor_transform_info,
|
||||
info,
|
||||
|
@ -7196,7 +7200,8 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||
P_("Children transformation matrix"),
|
||||
CLUTTER_TYPE_MATRIX,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
CLUTTER_PARAM_ANIMATABLE);
|
||||
|
||||
/**
|
||||
* ClutterActor:child-transform-set:
|
||||
|
@ -14628,6 +14633,10 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
|
|||
pspec);
|
||||
break;
|
||||
|
||||
case PROP_CHILD_TRANSFORM:
|
||||
clutter_actor_set_child_transform_internal (actor, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
g_object_set_property (obj, pspec->name, value);
|
||||
break;
|
||||
|
@ -18624,6 +18633,9 @@ _clutter_actor_create_transition (ClutterActor *actor,
|
|||
*/
|
||||
if (info->cur_state->easing_duration == 0)
|
||||
{
|
||||
CLUTTER_NOTE (ANIMATION, "Easing duration=0, immediate set for '%s::%s'",
|
||||
_clutter_actor_get_debug_name (actor),
|
||||
pspec->name);
|
||||
clutter_actor_set_animatable_property (actor,
|
||||
pspec->param_id,
|
||||
&final,
|
||||
|
@ -19930,6 +19942,35 @@ done:
|
|||
g_ptr_array_free (event_tree, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_set_child_transform_internal (ClutterActor *self,
|
||||
const ClutterMatrix *transform)
|
||||
{
|
||||
ClutterTransformInfo *info = _clutter_actor_get_transform_info (self);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
GObject *obj;
|
||||
gboolean was_set = info->child_transform_set;
|
||||
|
||||
clutter_matrix_init_from_matrix (&info->child_transform, transform);
|
||||
|
||||
/* if it's the identity matrix, we need to toggle the boolean flag */
|
||||
info->child_transform_set = !cogl_matrix_is_identity (transform);
|
||||
|
||||
/* we need to reset the transform_valid flag on each child */
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
child->priv->transform_valid = FALSE;
|
||||
|
||||
clutter_actor_queue_redraw (self);
|
||||
|
||||
obj = G_OBJECT (self);
|
||||
g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM]);
|
||||
|
||||
if (was_set != info->child_transform_set)
|
||||
g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM_SET]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_set_child_transform:
|
||||
* @self: a #ClutterActor
|
||||
|
@ -19947,32 +19988,21 @@ void
|
|||
clutter_actor_set_child_transform (ClutterActor *self,
|
||||
const ClutterMatrix *transform)
|
||||
{
|
||||
ClutterTransformInfo *info;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
GObject *obj;
|
||||
const ClutterTransformInfo *info;
|
||||
ClutterMatrix new_transform;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
info = _clutter_actor_get_transform_info (self);
|
||||
info = _clutter_actor_get_transform_info_or_defaults (self);
|
||||
|
||||
if (transform != NULL)
|
||||
clutter_matrix_init_from_matrix (&info->child_transform, transform);
|
||||
clutter_matrix_init_from_matrix (&new_transform, transform);
|
||||
else
|
||||
clutter_matrix_init_identity (&info->child_transform);
|
||||
clutter_matrix_init_identity (&new_transform);
|
||||
|
||||
info->child_transform_set = transform != NULL;
|
||||
|
||||
/* we need to reset the transform_valid flag on each child */
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
child->priv->transform_valid = FALSE;
|
||||
|
||||
clutter_actor_queue_redraw (self);
|
||||
|
||||
obj = G_OBJECT (self);
|
||||
g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM]);
|
||||
g_object_notify_by_pspec (obj, obj_props[PROP_CHILD_TRANSFORM_SET]);
|
||||
_clutter_actor_create_transition (self, obj_props[PROP_CHILD_TRANSFORM],
|
||||
&info->child_transform,
|
||||
&new_transform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -284,6 +284,53 @@ clutter_vertex_equal (const ClutterVertex *vertex_a,
|
|||
fabsf (vertex_a->z - vertex_b->z) < FLOAT_EPSILON;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_vertex_length (const ClutterVertex *vertex)
|
||||
{
|
||||
return sqrtf (vertex->x * vertex->x + vertex->y * vertex->y + vertex->z * vertex->z);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_vertex_normalize (ClutterVertex *vertex)
|
||||
{
|
||||
float factor = clutter_vertex_length (vertex);
|
||||
|
||||
if (factor == 0.f)
|
||||
return;
|
||||
|
||||
vertex->x /= factor;
|
||||
vertex->y /= factor;
|
||||
vertex->z /= factor;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_vertex_dot (const ClutterVertex *v1,
|
||||
const ClutterVertex *v2)
|
||||
{
|
||||
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_vertex_cross (const ClutterVertex *v1,
|
||||
const ClutterVertex *v2,
|
||||
ClutterVertex *res)
|
||||
{
|
||||
res->x = v1->y * v2->z - v2->y * v1->z;
|
||||
res->y = v1->z * v2->x - v2->z * v1->x;
|
||||
res->z = v1->x * v2->y - v2->x * v1->y;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_vertex_interpolate (const ClutterVertex *a,
|
||||
const ClutterVertex *b,
|
||||
double progress,
|
||||
ClutterVertex *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;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_vertex_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
|
@ -294,9 +341,7 @@ clutter_vertex_progress (const GValue *a,
|
|||
const ClutterVertex *bv = g_value_get_boxed (b);
|
||||
ClutterVertex res;
|
||||
|
||||
res.x = av->x + (bv->x - av->x) * progress;
|
||||
res.y = av->y + (bv->y - av->y) * progress;
|
||||
res.z = av->z + (bv->z - av->z) * progress;
|
||||
clutter_vertex_interpolate (av, bv, progress, &res);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
|
@ -1280,12 +1325,75 @@ clutter_rect_progress (const GValue *a,
|
|||
static gpointer
|
||||
clutter_matrix_copy (gpointer data)
|
||||
{
|
||||
return g_memdup (data, sizeof (ClutterMatrix));
|
||||
return cogl_matrix_copy (data);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterMatrix, clutter_matrix,
|
||||
clutter_matrix_copy,
|
||||
clutter_matrix_free)
|
||||
static gboolean
|
||||
clutter_matrix_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const ClutterMatrix *matrix1 = g_value_get_boxed (a);
|
||||
const ClutterMatrix *matrix2 = g_value_get_boxed (b);
|
||||
ClutterVertex scale1 = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f);
|
||||
float shear1[3] = { 0.f, 0.f, 0.f };
|
||||
ClutterVertex rotate1 = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex translate1 = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex4 perspective1 = { 0.f, 0.f, 0.f, 0.f };
|
||||
ClutterVertex scale2 = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f);
|
||||
float shear2[3] = { 0.f, 0.f, 0.f };
|
||||
ClutterVertex rotate2 = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex translate2 = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex4 perspective2 = { 0.f, 0.f, 0.f, 0.f };
|
||||
ClutterVertex scale_res = CLUTTER_VERTEX_INIT (1.f, 1.f, 1.f);
|
||||
float shear_res[3] = { 0.f, 0.f, 0.f };
|
||||
ClutterVertex rotate_res = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex translate_res = CLUTTER_VERTEX_INIT_ZERO;
|
||||
ClutterVertex4 perspective_res = { 0.f, 0.f, 0.f, 0.f };
|
||||
ClutterMatrix res;
|
||||
|
||||
clutter_matrix_init_identity (&res);
|
||||
|
||||
_clutter_util_matrix_decompose (matrix1,
|
||||
&scale1, shear1, &rotate1, &translate1,
|
||||
&perspective1);
|
||||
_clutter_util_matrix_decompose (matrix2,
|
||||
&scale2, shear2, &rotate2, &translate2,
|
||||
&perspective2);
|
||||
|
||||
/* 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 */
|
||||
clutter_vertex_interpolate (&translate1, &translate2, progress, &translate_res);
|
||||
cogl_matrix_translate (&res, translate_res.x, translate_res.y, translate_res.z);
|
||||
|
||||
/* rotation */
|
||||
clutter_vertex_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 */
|
||||
|
||||
/* scale */
|
||||
clutter_vertex_interpolate (&scale1, &scale2, progress, &scale_res);
|
||||
cogl_matrix_scale (&res, scale_res.x, scale_res.y, scale_res.z);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterMatrix, clutter_matrix,
|
||||
clutter_matrix_copy,
|
||||
clutter_matrix_free,
|
||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_matrix_progress))
|
||||
|
||||
/**
|
||||
* clutter_matrix_alloc:
|
||||
|
@ -1313,7 +1421,7 @@ clutter_matrix_alloc (void)
|
|||
void
|
||||
clutter_matrix_free (ClutterMatrix *matrix)
|
||||
{
|
||||
g_free (matrix);
|
||||
cogl_matrix_free (matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1381,3 +1489,60 @@ clutter_matrix_init_from_matrix (ClutterMatrix *a,
|
|||
{
|
||||
return memcpy (a, b, sizeof (ClutterMatrix));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_determinant:
|
||||
* @matrix: a #ClutterMatrix
|
||||
*
|
||||
* Calculates the determinant of the @matrix.
|
||||
*
|
||||
* Return value: the determinant of the #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
float
|
||||
clutter_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;
|
||||
}
|
||||
|
||||
ClutterMatrix *
|
||||
clutter_matrix_normalize (ClutterMatrix *matrix)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
#define MAT(m,r,c) ((float *)(m))[(c)*4+(r)]
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
for (j = 0; j < 4; j++)
|
||||
MAT (matrix, i, j) /= MAT (matrix, 3, 3);
|
||||
}
|
||||
|
||||
#undef MAT
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterMainContext ClutterMainContext;
|
||||
typedef struct _ClutterVertex4 ClutterVertex4;
|
||||
|
||||
#define CLUTTER_REGISTER_VALUE_TRANSFORM_TO(TYPE_TO,func) { \
|
||||
g_value_register_transform_func (g_define_type_id, TYPE_TO, func); \
|
||||
|
@ -265,6 +266,29 @@ void _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
|
|||
const cairo_rectangle_int_t *src2,
|
||||
cairo_rectangle_int_t *dest);
|
||||
|
||||
|
||||
struct _ClutterVertex4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
void
|
||||
_clutter_util_vertex4_interpolate (const ClutterVertex4 *a,
|
||||
const ClutterVertex4 *b,
|
||||
double progress,
|
||||
ClutterVertex4 *res);
|
||||
|
||||
gboolean
|
||||
_clutter_util_matrix_decompose (const ClutterMatrix *src,
|
||||
ClutterVertex *scale_p,
|
||||
float shear_p[3],
|
||||
ClutterVertex *rotate_p,
|
||||
ClutterVertex *translate_p,
|
||||
ClutterVertex4 *perspective_p);
|
||||
|
||||
typedef struct _ClutterPlane
|
||||
{
|
||||
float v0[3];
|
||||
|
|
|
@ -422,6 +422,17 @@ ClutterVertex *clutter_vertex_copy (const ClutterVertex *vertex);
|
|||
void clutter_vertex_free (ClutterVertex *vertex);
|
||||
gboolean clutter_vertex_equal (const ClutterVertex *vertex_a,
|
||||
const ClutterVertex *vertex_b);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_vertex_length (const ClutterVertex *vertex);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_vertex_normalize (ClutterVertex *vertex);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_vertex_dot (const ClutterVertex *v1,
|
||||
const ClutterVertex *v2);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_vertex_cross (const ClutterVertex *v1,
|
||||
const ClutterVertex *v2,
|
||||
ClutterVertex *res);
|
||||
|
||||
/**
|
||||
* ClutterActorBox:
|
||||
|
@ -694,15 +705,25 @@ typedef gboolean (* ClutterProgressFunc) (const GValue *a,
|
|||
void clutter_interval_register_progress_func (GType value_type,
|
||||
ClutterProgressFunc func);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
GType clutter_matrix_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterMatrix * clutter_matrix_alloc (void);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterMatrix * clutter_matrix_init_identity (ClutterMatrix *matrix);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterMatrix * clutter_matrix_init_from_array (ClutterMatrix *matrix,
|
||||
const float values[16]);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterMatrix * clutter_matrix_init_from_matrix (ClutterMatrix *a,
|
||||
const ClutterMatrix *b);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_matrix_free (ClutterMatrix *matrix);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
float clutter_matrix_determinant (const ClutterMatrix *matrix);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterMatrix * clutter_matrix_normalize (ClutterMatrix *matrix);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include "clutter-main.h"
|
||||
|
@ -84,14 +86,6 @@ _clutter_gettext (const gchar *str)
|
|||
#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2))
|
||||
#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2)))
|
||||
|
||||
typedef struct _ClutterVertex4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
} ClutterVertex4;
|
||||
|
||||
void
|
||||
_clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
|
@ -182,6 +176,251 @@ _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
|
|||
dest->y = dest_y;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_util_vertex_combine (const ClutterVertex *a,
|
||||
const ClutterVertex *b,
|
||||
double ascl,
|
||||
double bscl,
|
||||
ClutterVertex *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,
|
||||
ClutterVertex *scale_p,
|
||||
float shear_p[3],
|
||||
ClutterVertex *rotate_p,
|
||||
ClutterVertex *translate_p,
|
||||
ClutterVertex4 *perspective_p)
|
||||
{
|
||||
CoglMatrix matrix = *src;
|
||||
CoglMatrix perspective;
|
||||
ClutterVertex4 vertex_tmp;
|
||||
ClutterVertex 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, i, j) /= 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, 0, 3) = 0.f;
|
||||
MAT (&perspective, 1, 3) = 0.f;
|
||||
MAT (&perspective, 2, 3) = 0.f;
|
||||
MAT (&perspective, 3, 3) = 1.f;
|
||||
|
||||
if (clutter_matrix_determinant (&perspective) == 0.f)
|
||||
return FALSE;
|
||||
|
||||
if (MAT (&matrix, 0, 3) != 0.f ||
|
||||
MAT (&matrix, 1, 3) != 0.f ||
|
||||
MAT (&matrix, 2, 3) != 0.f)
|
||||
{
|
||||
CoglMatrix perspective_inv;
|
||||
ClutterVertex4 p;
|
||||
|
||||
vertex_tmp.x = MAT (&matrix, 0, 3);
|
||||
vertex_tmp.y = MAT (&matrix, 1, 3);
|
||||
vertex_tmp.z = MAT (&matrix, 2, 3);
|
||||
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, 0, 3) = 0.0f;
|
||||
MAT (&matrix, 1, 3) = 0.0f;
|
||||
MAT (&matrix, 2, 3) = 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, 3, 0);
|
||||
MAT (&matrix, 3, 0) = 0.f;
|
||||
translate_p->y = MAT (&matrix, 3, 1);
|
||||
MAT (&matrix, 3, 1) = 0.f;
|
||||
translate_p->z = MAT (&matrix, 3, 2);
|
||||
MAT (&matrix, 3, 2) = 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 = clutter_vertex_length (&row[0]);
|
||||
clutter_vertex_normalize (&row[0]);
|
||||
|
||||
/* compute XY shear and make the second row orthogonal to the first */
|
||||
shear_p[XY_SHEAR] = clutter_vertex_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 = clutter_vertex_length (&row[1]);
|
||||
clutter_vertex_normalize (&row[1]);
|
||||
shear_p[XY_SHEAR] /= scale_p->y;
|
||||
|
||||
/* compute XZ and YZ shears, orthogonalize the third row */
|
||||
shear_p[XZ_SHEAR] = clutter_vertex_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] = clutter_vertex_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 = clutter_vertex_dot (&row[0], &row[2]);
|
||||
clutter_vertex_normalize (&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
|
||||
*/
|
||||
clutter_vertex_cross (&row[1], &row[2], &pdum);
|
||||
if (clutter_vertex_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;
|
||||
|
|
|
@ -908,11 +908,13 @@ clutter_margin_free
|
|||
clutter_margin_get_type
|
||||
clutter_margin_new
|
||||
clutter_matrix_alloc
|
||||
clutter_matrix_determinant
|
||||
clutter_matrix_free
|
||||
clutter_matrix_get_type
|
||||
clutter_matrix_init_identity
|
||||
clutter_matrix_init_from_array
|
||||
clutter_matrix_init_from_matrix
|
||||
clutter_matrix_normalize
|
||||
clutter_media_get_audio_volume
|
||||
clutter_media_get_buffer_fill
|
||||
clutter_media_get_can_seek
|
||||
|
|
|
@ -3326,6 +3326,7 @@ clutter_matrix_free
|
|||
clutter_matrix_init_from_array
|
||||
clutter_matrix_init_from_matrix
|
||||
clutter_matrix_init_identity
|
||||
clutter_matrix_determinant
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_knot_copy
|
||||
|
|
|
@ -91,7 +91,12 @@ on_key_press (ClutterActor *stage,
|
|||
key_symbol = clutter_event_get_key_symbol (event);
|
||||
|
||||
if (key_symbol == CLUTTER_KEY_space)
|
||||
clutter_actor_set_child_transform (scroll, NULL);
|
||||
{
|
||||
clutter_actor_save_easing_state (scroll);
|
||||
clutter_actor_set_easing_duration (scroll, 1000);
|
||||
clutter_actor_set_child_transform (scroll, NULL);
|
||||
clutter_actor_restore_easing_state (scroll);
|
||||
}
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue