From 733de46f3b1498db2d88f260376524a37da47df2 Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 31 May 2007 09:29:12 +0000 Subject: [PATCH] Fixed ellipse behaviour for negative angles; fixed double to int conversion for negative numbers; fixed CLUTTER_ANGLE_FROM_DEGX; added ClutterVertices and clutter_actor_get_transformed_vertices() --- ChangeLog | 23 +- clutter/clutter-actor.c | 378 +++++++++++++++++++++++++++- clutter/clutter-actor.h | 34 +++ clutter/clutter-behaviour-ellipse.c | 8 +- clutter/clutter-fixed.c | 4 +- clutter/clutter-fixed.h | 4 +- doc/reference/ChangeLog | 5 + doc/reference/clutter.types | 1 + 8 files changed, 446 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 537f1ec78..acdaaee14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ -2007-05-31 Matthew Allum +2007-05-31 Tomas Frydrych + * clutter/clutter-fixed.h: + * clutter/clutter-fixed.c: + (_clutter_double_to_int): + Fixed return value to gint; added missing cast that broke negative + number conversions. + + (CLUTTER_ANGLE_FROM_DEGX): + Swapped division and multiplication around to avoid overflows. + + * clutter/clutter-behaviour-ellipse.c: + Fixed incorrectly set lower bounds for angle properties. + + * clutter/clutter-actor.h: + * clutter/clutter-actor.c: + Added ClutterVertices type. + (clutter_actor_get_transformed_vertices): + New function. + +2007-05-31 Matthew Allum * TODO: Sync up for whats left for 0.4 release (and 0.6 ideas) @@ -21,7 +40,7 @@ * doc/manual/manual.xsl: * doc/manual/style.css: Add various bits for application developers manual. - + 2007-05-30 Tomas Frydrych * clutter/clutter-alpha.h: diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 364d1f156..01ce77c05 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -299,6 +299,348 @@ clutter_actor_pick (ClutterActor *self, } } +/* + * Utility functions for manipulating transformation matrix + * + * Matrix: 4x4 of ClutterFixed + */ +#define M(m,row,col) (m)[col*4+row] + +/* Make indentity matrix */ +static void +mtx_identity (ClutterFixed * m) +{ + memset (m, 0, sizeof (ClutterFixed) * 16); + M (m,0,0) = CFX_ONE; + M (m,1,1) = CFX_ONE; + M (m,2,2) = CFX_ONE; + M (m,3,3) = CFX_ONE; +} + +/* Add translation by (x,y,z) to matrix */ +static void +mtx_translate (ClutterFixed * m, + ClutterFixed x, ClutterFixed y, ClutterFixed z) +{ + M (m,0,3) += CFX_MUL (M (m,0,0), x) + CFX_MUL (M (m,0,1), y) + + CFX_MUL (M (m,0,2), z); + + M (m,1,3) += CFX_MUL (M (m,1,0), x) + CFX_MUL (M (m,1,1), y) + + CFX_MUL (M (m,1,2), z); + + M (m,2,3) += CFX_MUL (M (m,2,0), x) + CFX_MUL (M (m,2,1), y) + + CFX_MUL (M (m,2,2), z); + + M (m,3,3) += CFX_MUL (M (m,3,0), x) + CFX_MUL (M (m,3,1), y) + + CFX_MUL (M (m,3,2), z); +} + +/* Add rotation around Z axis by ang to matrix */ +static void +mtx_rotate_z (ClutterFixed *m, ClutterFixed ang) +{ + ClutterFixed m0, m1; + ClutterAngle a = CLUTTER_ANGLE_FROM_DEGX (ang); + ClutterFixed c = clutter_cosi (a); + ClutterFixed s = clutter_sini (a); + + m0 = CFX_MUL (M (m,0,0), c) + CFX_MUL (M (m,0,1), s); + m1 = CFX_MUL (M (m,0,0), -s) + CFX_MUL (M (m,0,1), c); + M (m,0,0) = m0; + M (m,0,1) = m1; + + m0 = CFX_MUL (M (m,1,0), c) + CFX_MUL (M (m,1,1), s); + m1 = CFX_MUL (M (m,1,0), -s) + CFX_MUL (M (m,1,1), c); + M (m,1,0) = m0; + M (m,1,1) = m1; + + m0 = CFX_MUL (M (m,2,0), c) + CFX_MUL (M (m,2,1), s); + m1 = CFX_MUL (M (m,2,0), -s) + CFX_MUL (M (m,2,1), c); + M (m,2,0) = m0; + M (m,2,1) = m1; + + m0 = CFX_MUL (M (m,3,0), c) + CFX_MUL (M (m,3,1), s); + m1 = CFX_MUL (M (m,3,0), -s) + CFX_MUL (M (m,3,1), c); + M (m,3,0) = m0; + M (m,3,1) = m1; +} + +/* Add rotation around X axis by ang to matrix */ +static void +mtx_rotate_x (ClutterFixed *m, ClutterFixed ang) +{ + ClutterFixed m1, m2; + ClutterAngle a = CLUTTER_ANGLE_FROM_DEGX (ang); + ClutterFixed c = clutter_cosi (a); + ClutterFixed s = clutter_sini (a); + + m1 = CFX_MUL (M (m,0,1), c) + CFX_MUL (M (m,0,2), s); + m2 = CFX_MUL (M (m,0,1), -s) + CFX_MUL (M (m,0,2), c); + M (m,0,1) = m1; + M (m,0,2) = m2; + + m1 = CFX_MUL (M (m,1,1), c) + CFX_MUL (M (m,1,2), s); + m2 = CFX_MUL (M (m,1,1), -s) + CFX_MUL (M (m,1,2), c); + M (m,1,1) = m1; + M (m,1,2) = m2; + + m1 = CFX_MUL (M (m,2,1), c) + CFX_MUL (M (m,2,2), s); + m2 = CFX_MUL (M (m,2,1), -s) + CFX_MUL (M (m,2,2), c); + M (m,2,1) = m1; + M (m,2,2) = m2; + + m1 = CFX_MUL (M (m,3,1), c) + CFX_MUL (M (m,3,2), s); + m2 = CFX_MUL (M (m,3,1), -s) + CFX_MUL (M (m,3,2), c); + M (m,3,1) = m1; + M (m,3,2) = m2; +} + +/* Add rotation around Y axis by ang to matrix */ +static void +mtx_rotate_y (ClutterFixed *m, ClutterFixed ang) +{ + ClutterFixed m0, m2; + ClutterAngle a = CLUTTER_ANGLE_FROM_DEGX (ang); + ClutterFixed c = clutter_cosi (a); + ClutterFixed s = clutter_sini (a); + + m0 = CFX_MUL (M (m,0,0), c) + CFX_MUL (M (m,0,2), -s); + m2 = CFX_MUL (M (m,0,0), s) + CFX_MUL (M (m,0,2), c); + M (m,0,0) = m0; + M (m,0,2) = m2; + + m0 = CFX_MUL (M (m,1,0), c) + CFX_MUL (M (m,1,2), -s); + m2 = CFX_MUL (M (m,1,0), s) + CFX_MUL (M (m,1,2), c); + M (m,1,0) = m0; + M (m,1,2) = m2; + + m0 = CFX_MUL (M (m,2,0), c) + CFX_MUL (M (m,2,2), -s); + m2 = CFX_MUL (M (m,2,0), s) + CFX_MUL (M (m,2,2), c); + M (m,2,0) = m0; + M (m,2,2) = m2; + + m0 = CFX_MUL (M (m,3,0), c) + CFX_MUL (M (m,3,2), -s); + m2 = CFX_MUL (M (m,3,0), s) + CFX_MUL (M (m,3,2), c); + M (m,3,0) = m0; + M (m,3,2) = m2; +} + +/* Apply scale by factors x, y to matrix */ +static void +mtx_scale (ClutterFixed *m, ClutterFixed x, ClutterFixed y) +{ + M (m,0,0) = CFX_MUL (M (m,0,0), x); + M (m,1,1) = CFX_MUL (M (m,1,1), y); +} + +/* Transform point (x,y,z) by matrix */ +static void +mtx_transform (ClutterFixed *m, + ClutterFixed *x, ClutterFixed *y, ClutterFixed *z) +{ + ClutterFixed _x, _y, _z; + _x = *x; + _y = *y; + _z = *z; + + *x = CFX_MUL (M (m,0,0), _x) + CFX_MUL (M (m,0,1), _y) + + CFX_MUL (M (m,0,2), _z) + M (m,0,3); + + *y = CFX_MUL (M (m,1,0), _x) + CFX_MUL (M (m,1,1), _y) + + CFX_MUL (M (m,1,2), _z) + M (m,1,3); + + *z = CFX_MUL (M (m,2,0), _x) + CFX_MUL (M (m,2,1), _y) + + CFX_MUL (M (m,2,2), _z) + M (m,2,3); +} + +/** + * clutter_actor_get_transformed_vertices: + * @self: A #ClutterActor + * @verts: Pointer to a location of #ClutterVertices where to store the result. + * Calculates the vertices of the translated, rotated and scaled actor in 3D + * space. + * + * Since: 0.4 + **/ +void +clutter_actor_get_transformed_vertices (ClutterActor * self, + ClutterVertices * verts) +{ + ClutterActorPrivate * priv; + ClutterFixed mtx[16]; + ClutterFixed x, y, z; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + priv = self->priv; + + mtx_identity (&mtx[0]); + + /* + * All the rotation ops are relative to the actor, not the overall + * coordiante system; so first of all, we carry out a translation from + * 0,0 to where our actor is. + */ + mtx_translate (&mtx[0], + CLUTTER_UNITS_TO_FIXED (priv->coords.x1), + CLUTTER_UNITS_TO_FIXED (priv->coords.y1), + CLUTTER_INT_TO_FIXED (priv->z)); + + if (self->priv->rzang) + { + mtx_translate (&mtx[0], + CLUTTER_INT_TO_FIXED (priv->rzx), + CLUTTER_INT_TO_FIXED (priv->rzy), + 0); + + mtx_rotate_z (&mtx[0], priv->rzang); + + mtx_translate (&mtx[0], + CLUTTER_INT_TO_FIXED (-priv->rzx), + CLUTTER_INT_TO_FIXED (-priv->rzy), + 0); + } + + if (self->priv->ryang) + { + mtx_translate (&mtx[0], + CLUTTER_INT_TO_FIXED (priv->ryx), + 0, + CLUTTER_INT_TO_FIXED (priv->z + priv->ryz)); + + mtx_rotate_y (&mtx[0], priv->ryang); + + mtx_translate (&mtx[0], + CLUTTER_INT_TO_FIXED (-priv->ryx), + 0, + CLUTTER_INT_TO_FIXED (-(priv->z + priv->ryz))); + } + + if (self->priv->rxang) + { + mtx_translate (&mtx[0], + 0, + CLUTTER_INT_TO_FIXED (priv->rxy), + CLUTTER_INT_TO_FIXED (priv->z + priv->rxz)); + + mtx_rotate_x (&mtx[0], priv->rxang); + + mtx_translate (&mtx[0], + 0, + CLUTTER_INT_TO_FIXED (-priv->rxy), + CLUTTER_INT_TO_FIXED (-(priv->z - priv->rxz))); + } + + if (self->priv->z) + mtx_translate (&mtx[0], 0, 0, CLUTTER_INT_TO_FIXED (priv->z)); + + if (self->priv->scale_x != CFX_ONE || self->priv->scale_y != CFX_ONE) + { + mtx_scale (&mtx[0], priv->scale_x, priv->scale_y); + } + +#if 0 + g_debug ("Matrix\n" + " %f, %f, %f, %f\n" + " %f, %f, %f, %f\n" + " %f, %f, %f, %f\n" + " %f, %f, %f, %f", + CLUTTER_FIXED_TO_FLOAT (M(mtx,0,0)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,0,1)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,0,2)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,0,3)), + + CLUTTER_FIXED_TO_FLOAT (M(mtx,1,0)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,1,1)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,1,2)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,1,3)), + + CLUTTER_FIXED_TO_FLOAT (M(mtx,2,0)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,2,1)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,2,2)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,2,3)), + + CLUTTER_FIXED_TO_FLOAT (M(mtx,3,0)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,3,1)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,3,2)), + CLUTTER_FIXED_TO_FLOAT (M(mtx,3,3))); +#endif + + x = 0; + y = 0; + z = 0; + + mtx_transform (&mtx[0], &x, &y, &z); + + verts->topleft.x = CLUTTER_UNITS_FROM_FIXED (x); + verts->topleft.y = CLUTTER_UNITS_FROM_FIXED (y); + verts->topleft.z = CLUTTER_UNITS_FROM_FIXED (z); + + x = CLUTTER_UNITS_TO_FIXED (priv->coords.x2 - priv->coords.x1); + y = CLUTTER_UNITS_TO_FIXED (priv->coords.y2 - priv->coords.y1); + z = CLUTTER_INT_TO_FIXED (priv->z); + + mtx_transform (&mtx[0], &x, &y, &z); + + verts->bottomright.x = CLUTTER_UNITS_FROM_FIXED (x); + verts->bottomright.y = CLUTTER_UNITS_FROM_FIXED (y); + verts->bottomright.z = CLUTTER_UNITS_FROM_FIXED (z); + + x = 0; + y = CLUTTER_UNITS_TO_FIXED (priv->coords.y2 - priv->coords.y1); + z = CLUTTER_INT_TO_FIXED (priv->z); + + mtx_transform (&mtx[0], &x, &y, &z); + + verts->bottomleft.x = CLUTTER_UNITS_FROM_FIXED (x); + verts->bottomleft.y = CLUTTER_UNITS_FROM_FIXED (y); + verts->bottomleft.z = CLUTTER_UNITS_FROM_FIXED (z); + + x = CLUTTER_UNITS_TO_FIXED (priv->coords.x2 - priv->coords.x1); + y = 0; + z = CLUTTER_INT_TO_FIXED (priv->z); + + mtx_transform (&mtx[0], &x, &y, &z); + + verts->topright.x = CLUTTER_UNITS_FROM_FIXED (x); + verts->topright.y = CLUTTER_UNITS_FROM_FIXED (y); + verts->topright.z = CLUTTER_UNITS_FROM_FIXED (z); + +#if 0 + if (priv->coords.x1 != verts->topleft.x || + priv->coords.y1 != verts->topleft.y || + priv->coords.x2 != verts->bottomright.x || + priv->coords.y2 != verts->bottomright.y) + g_debug ("Box [%f,%f],[%f,%f], \n" + " rxy %d, rxz %d, rxa %f\n" + " ryx %d, ryz %d, rya %f\n" + " rzx %d, rzy %d, rza %f\n" + "Vertices: \n" + " tl [%f,%f,%f], tr [%f,%f,%f] \n" + " bl [%f,%f,%f], br [%f,%f,%f] \n", + CLUTTER_FIXED_TO_FLOAT (priv->coords.x1), + CLUTTER_FIXED_TO_FLOAT (priv->coords.y1), + CLUTTER_FIXED_TO_FLOAT (priv->coords.x2), + CLUTTER_FIXED_TO_FLOAT (priv->coords.y2), + priv->rxy, priv->rxz, CLUTTER_FIXED_TO_FLOAT (priv->rxang), + priv->ryx, priv->ryz, CLUTTER_FIXED_TO_FLOAT (priv->ryang), + priv->rzx, priv->rzy, CLUTTER_FIXED_TO_FLOAT (priv->rzang), + CLUTTER_FIXED_TO_FLOAT (verts->topleft.x), + CLUTTER_FIXED_TO_FLOAT (verts->topleft.y), + CLUTTER_FIXED_TO_FLOAT (verts->topleft.z), + CLUTTER_FIXED_TO_FLOAT (verts->topright.x), + CLUTTER_FIXED_TO_FLOAT (verts->topright.y), + CLUTTER_FIXED_TO_FLOAT (verts->topright.z), + CLUTTER_FIXED_TO_FLOAT (verts->bottomleft.x), + CLUTTER_FIXED_TO_FLOAT (verts->bottomleft.y), + CLUTTER_FIXED_TO_FLOAT (verts->bottomleft.z), + CLUTTER_FIXED_TO_FLOAT (verts->bottomright.x), + CLUTTER_FIXED_TO_FLOAT (verts->bottomright.y), + CLUTTER_FIXED_TO_FLOAT (verts->bottomright.z)); +#endif +} + +#undef M + /** * clutter_actor_paint: * @self: A #ClutterActor @@ -314,7 +656,9 @@ clutter_actor_paint (ClutterActor *self) ClutterActorPrivate *priv; ClutterActorClass *klass; ClutterMainContext *context; - +#if 1 + ClutterVertices verts; +#endif g_return_if_fail (CLUTTER_IS_ACTOR (self)); priv = self->priv; @@ -330,6 +674,10 @@ clutter_actor_paint (ClutterActor *self) } } +#if 1 + clutter_actor_get_transformed_vertices (self, &verts); +#endif + context = clutter_context_get_default (); klass = CLUTTER_ACTOR_GET_CLASS (self); @@ -2139,6 +2487,34 @@ clutter_geometry_get_type (void) return our_type; } +/* + * ClutterVertices + */ + +static ClutterVertices* +clutter_vertices_copy (const ClutterVertices *vertices) +{ + ClutterVertices *result = g_new (ClutterVertices, 1); + + *result = *vertices; + + return result; +} + +GType +clutter_vertices_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ( + g_intern_static_string ("ClutterVertices"), + (GBoxedCopyFunc) clutter_vertices_copy, + (GBoxedFreeFunc) g_free); + + return our_type; +} + /* * ClutterActorBox */ diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index 37440ccf3..709266f27 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -77,6 +77,7 @@ typedef struct _ClutterActorClass ClutterActorClass; typedef struct _ClutterActorBox ClutterActorBox; typedef struct _ClutterActorPrivate ClutterActorPrivate; typedef struct _ClutterGeometry ClutterGeometry; +typedef struct _ClutterVertices ClutterVertices; typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data); #define CLUTTER_CALLBACK(f) ((ClutterCallback) (f)) @@ -107,6 +108,39 @@ struct _ClutterActorBox { ClutterUnit x1, y1, x2, y2; }; GType clutter_actor_box_get_type (void) G_GNUC_CONST; +struct _ClutterVertices +{ + struct + { + ClutterUnit x; + ClutterUnit y; + ClutterUnit z; + }topleft; + + struct + { + ClutterUnit x; + ClutterUnit y; + ClutterUnit z; + }topright; + + struct + { + ClutterUnit x; + ClutterUnit y; + ClutterUnit z; + }bottomleft; + + struct + { + ClutterUnit x; + ClutterUnit y; + ClutterUnit z; + }bottomright; +}; + +GType clutter_vertices_get_type (void) G_GNUC_CONST; + struct _ClutterActor { /*< public >*/ diff --git a/clutter/clutter-behaviour-ellipse.c b/clutter/clutter-behaviour-ellipse.c index a2b95bdeb..44da61027 100644 --- a/clutter/clutter-behaviour-ellipse.c +++ b/clutter/clutter-behaviour-ellipse.c @@ -160,7 +160,7 @@ clutter_behaviour_ellipse_alpha_notify (ClutterBehaviour * behave, angle = self->priv->angle_begin - (angle * alpha) / CLUTTER_ALPHA_MAX_ALPHA; } - + clutter_behaviour_ellipse_advance (self, angle, &knot); knot.x += self->priv->center.x; @@ -273,7 +273,7 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) g_param_spec_int ("angle-begin", "Angle Begin", "Initial angle", - 0, G_MAXINT, 0, + G_MININT, G_MAXINT, 0, CLUTTER_PARAM_READWRITE)); /** * ClutterBehaviourEllipse:angle-end: @@ -287,7 +287,7 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) g_param_spec_int ("angle-end", "Angle End", "Final angle", - 0, G_MAXINT, 1024, + G_MININT, G_MAXINT, 1024, CLUTTER_PARAM_READWRITE)); /** @@ -302,7 +302,7 @@ clutter_behaviour_ellipse_class_init (ClutterBehaviourEllipseClass *klass) g_param_spec_int ("angle-tilt", "Angle Tilt", "Tilt of the ellipse", - 0, G_MAXINT, 1024, + G_MININT, G_MAXINT, 1024, CLUTTER_PARAM_READWRITE)); /** diff --git a/clutter/clutter-fixed.c b/clutter/clutter-fixed.c index e3d2b3e03..622545458 100644 --- a/clutter/clutter-fixed.c +++ b/clutter/clutter-fixed.c @@ -844,7 +844,7 @@ _clutter_double_to_fixed (double val) * * Since: 0.2 */ -ClutterFixed +gint _clutter_double_to_int (double val) { union @@ -855,7 +855,7 @@ _clutter_double_to_int (double val) dbl.d = val; dbl.d = dbl.d + _magic; - return dbl.i[0] >> 16; + return ((int)dbl.i[0]) >> 16; } #undef _CFX_MAN diff --git a/clutter/clutter-fixed.h b/clutter/clutter-fixed.h index d252bd3e9..c7104103d 100644 --- a/clutter/clutter-fixed.h +++ b/clutter/clutter-fixed.h @@ -51,7 +51,7 @@ typedef gint32 ClutterAngle; /* angle such that 1024 == 2*PI */ #define CLUTTER_ANGLE_FROM_DEGF(x) CLUTTER_FLOAT_TO_INT(((float)x*1024.0f)/360.0f) #define CLUTTER_ANGLE_TO_DEGF(x) (((float)x * 360.0)/ 1024.0) -#define CLUTTER_ANGLE_FROM_DEGX(x) CFX_INT(((x*1024)/360) + CFX_HALF) +#define CLUTTER_ANGLE_FROM_DEGX(x) CFX_INT(((x/360)*1024) + CFX_HALF) #define CFX_Q 16 /* Decimal part size in bits */ #define CFX_ONE (1 << CFX_Q) /* 1 */ @@ -202,7 +202,7 @@ extern inline ClutterFixed _clutter_double_to_fixed (double value); extern inline -ClutterFixed _clutter_double_to_int (double value); +gint _clutter_double_to_int (double value); G_END_DECLS diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index dfa49737b..7b3f9f01f 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,8 @@ +2007-05-31 Tomas Frydrych + + * clutter.types: + Added clutter_vertices_get_type. + 2007-05-30 Tomas Frydrych * clutter.types: diff --git a/doc/reference/clutter.types b/doc/reference/clutter.types index 1d23a0f43..d8383919a 100644 --- a/doc/reference/clutter.types +++ b/doc/reference/clutter.types @@ -18,3 +18,4 @@ clutter_behaviour_path_get_type clutter_behaviour_rotate_get_type clutter_behaviour_scale_get_type clutter_backend_get_type +clutter_vertices_get_type