From cdb78ec4d2bdea875fb1b4514cf4ec0618e31a8e Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 19 Dec 2008 12:53:57 +0000 Subject: [PATCH 1/3] [units] Do not use fixed point and units interchangeably Clutter units are, at the moment, implemented as a value in fixed point notation using the same format as CoglFixed. This is, though, an implementation detail. For this reason, units should not be treated as CoglFixed values and should be converted to and from fixed point using the provided macros. This commit updates the usage of units and fixed point values in ClutterActor and rationalises some of the transformation code that heavily relied on the equivalency between them. --- clutter/clutter-actor.c | 557 +++++++++++++++++++++------------------- 1 file changed, 292 insertions(+), 265 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 719524c91..655e2bb74 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -772,6 +772,24 @@ clutter_actor_real_allocate (ClutterActor *self, g_object_thaw_notify (G_OBJECT (self)); } +/* like ClutterVertex, but using CoglFixed and with a w component */ +typedef struct { + CoglFixed x; + CoglFixed y; + CoglFixed z; + CoglFixed w; +} fixed_vertex_t; + +/* copies a fixed vertex into a ClutterVertex */ +static inline void +fixed_vertex_to_units (const fixed_vertex_t *f, + ClutterVertex *u) +{ + u->x = CLUTTER_UNITS_FROM_FIXED (f->x); + u->y = CLUTTER_UNITS_FROM_FIXED (f->y); + u->z = CLUTTER_UNITS_FROM_FIXED (f->z); +} + /* * Utility functions for manipulating transformation matrix * @@ -779,49 +797,114 @@ clutter_actor_real_allocate (ClutterActor *self, */ #define M(m,row,col) (m)[(col) * 4 + (row)] -/* Transform point (x,y,z) by matrix */ -static void -mtx_transform (ClutterFixed m[16], - ClutterFixed *x, ClutterFixed *y, ClutterFixed *z, - ClutterFixed *w) +/* Transforms a vertex using the passed matrix; vertex is + * an in-out parameter + */ +static inline void +mtx_transform (const ClutterFixed m[], + fixed_vertex_t *vertex) { - ClutterFixed _x, _y, _z, _w; - _x = *x; - _y = *y; - _z = *z; - _w = *w; + ClutterFixed _x, _y, _z, _w; - /* We care lot about precision here, so have to use QMUL */ - *x = COGL_FIXED_MUL (M (m, 0, 0), _x) - + COGL_FIXED_MUL (M (m, 0, 1), _y) - + COGL_FIXED_MUL (M (m, 0, 2), _z) - + COGL_FIXED_MUL (M (m, 0, 3), _w); + _x = vertex->x; + _y = vertex->y; + _z = vertex->z; + _w = vertex->w; - *y = COGL_FIXED_MUL (M (m, 1, 0), _x) - + COGL_FIXED_MUL (M (m, 1, 1), _y) - + COGL_FIXED_MUL (M (m, 1, 2), _z) - + COGL_FIXED_MUL (M (m, 1, 3), _w); + /* We care lot about precision here, so have to use MUL instead + * of FAST_MUL + */ + vertex->x = COGL_FIXED_MUL (M (m, 0, 0), _x) + + COGL_FIXED_MUL (M (m, 0, 1), _y) + + COGL_FIXED_MUL (M (m, 0, 2), _z) + + COGL_FIXED_MUL (M (m, 0, 3), _w); - *z = COGL_FIXED_MUL (M (m, 2, 0), _x) - + COGL_FIXED_MUL (M (m, 2, 1), _y) - + COGL_FIXED_MUL (M (m, 2, 2), _z) - + COGL_FIXED_MUL (M (m, 2, 3), _w); + vertex->y = COGL_FIXED_MUL (M (m, 1, 0), _x) + + COGL_FIXED_MUL (M (m, 1, 1), _y) + + COGL_FIXED_MUL (M (m, 1, 2), _z) + + COGL_FIXED_MUL (M (m, 1, 3), _w); - *w = COGL_FIXED_MUL (M (m, 3, 0), _x) - + COGL_FIXED_MUL (M (m, 3, 1), _y) - + COGL_FIXED_MUL (M (m, 3, 2), _z) - + COGL_FIXED_MUL (M (m, 3, 3), _w); + vertex->z = COGL_FIXED_MUL (M (m, 2, 0), _x) + + COGL_FIXED_MUL (M (m, 2, 1), _y) + + COGL_FIXED_MUL (M (m, 2, 2), _z) + + COGL_FIXED_MUL (M (m, 2, 3), _w); - /* Specially for Matthew: was going to put a comment here, but could not - * think of anything at all to say ;) - */ + vertex->w = COGL_FIXED_MUL (M (m, 3, 0), _x) + + COGL_FIXED_MUL (M (m, 3, 1), _y) + + COGL_FIXED_MUL (M (m, 3, 2), _z) + + COGL_FIXED_MUL (M (m, 3, 3), _w); + + /* Specially for Matthew: was going to put a comment here, but could not + * think of anything at all to say ;) + */ } #undef M +/* Help macros to scale from OpenGL <-1,1> coordinates system to our + * X-window based <0,window-size> coordinates + */ +#define MTX_GL_SCALE_X(x,w,v1,v2) (COGL_FIXED_MUL (((COGL_FIXED_DIV ((x), (w)) + COGL_FIXED_1) >> 1), (v1)) + (v2)) +#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - COGL_FIXED_MUL (((COGL_FIXED_DIV ((y), (w)) + COGL_FIXED_1) >> 1), (v1)) + (v2)) +#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2))) + +/* transforms a 4-tuple of coordinates using @matrix and + * places the result into a fixed @vertex + */ +static inline void +fixed_vertex_transform (const ClutterFixed matrix[], + ClutterFixed x, + ClutterFixed y, + ClutterFixed z, + ClutterFixed w, + fixed_vertex_t *vertex) +{ + fixed_vertex_t tmp = { 0, }; + + tmp.x = x; + tmp.y = y; + tmp.z = z; + tmp.w = w; + + mtx_transform (matrix, &tmp); + + *vertex = tmp; +} + +/* scales a fixed @vertex using @matrix and @viewport, and + * transforms the result into ClutterUnits, filling @vertex_p + */ +static inline void +fixed_vertex_scale (const ClutterFixed matrix[], + const fixed_vertex_t *vertex, + const ClutterFixed viewport[], + ClutterVertex *vertex_p) +{ + ClutterFixed v_x, v_y, v_width, v_height; + fixed_vertex_t tmp = { 0, }; + + tmp = *vertex; + + mtx_transform (matrix, &tmp); + + v_x = viewport[0]; + v_y = viewport[1]; + v_width = viewport[2]; + v_height = viewport[3]; + + tmp.x = MTX_GL_SCALE_X (tmp.x, tmp.w, v_width, v_x); + tmp.y = MTX_GL_SCALE_Y (tmp.y, tmp.w, v_height, v_y); + tmp.z = MTX_GL_SCALE_Z (tmp.z, tmp.w, v_width, v_x); + tmp.w = 0; + + fixed_vertex_to_units (&tmp, vertex_p); +} + /* Applies the transforms associated with this actor and its ancestors, * retrieves the resulting OpenGL modelview matrix, and uses the matrix * to transform the supplied point + * + * The point coordinates are in-out parameters */ static void clutter_actor_transform_point_relative (ClutterActor *actor, @@ -832,14 +915,33 @@ clutter_actor_transform_point_relative (ClutterActor *actor, ClutterUnit *w) { ClutterFixed mtx[16]; + fixed_vertex_t vertex = { 0, }; + + vertex.x = (x != NULL) ? CLUTTER_UNITS_TO_FIXED (*x) : 0; + vertex.y = (y != NULL) ? CLUTTER_UNITS_TO_FIXED (*y) : 0; + vertex.z = (z != NULL) ? CLUTTER_UNITS_TO_FIXED (*z) : 0; + vertex.w = (w != NULL) ? CLUTTER_UNITS_TO_FIXED (*w) : 0; cogl_push_matrix(); _clutter_actor_apply_modelview_transform_recursive (actor, ancestor); + cogl_get_modelview_matrix (mtx); - mtx_transform (mtx, x, y, z, w); + mtx_transform (mtx, &vertex); cogl_pop_matrix(); + + if (x) + *x = CLUTTER_UNITS_FROM_FIXED (vertex.x); + + if (y) + *y = CLUTTER_UNITS_FROM_FIXED (vertex.y); + + if (z) + *z = CLUTTER_UNITS_FROM_FIXED (vertex.z); + + if (w) + *w = CLUTTER_UNITS_FROM_FIXED (vertex.w); } /* Applies the transforms associated with this actor and its ancestors, @@ -854,22 +956,34 @@ clutter_actor_transform_point (ClutterActor *actor, ClutterUnit *w) { ClutterFixed mtx[16]; + fixed_vertex_t vertex = { 0, }; + + vertex.x = (x != NULL) ? CLUTTER_UNITS_TO_FIXED (*x) : 0; + vertex.y = (y != NULL) ? CLUTTER_UNITS_TO_FIXED (*y) : 0; + vertex.z = (z != NULL) ? CLUTTER_UNITS_TO_FIXED (*z) : 0; + vertex.w = (w != NULL) ? CLUTTER_UNITS_TO_FIXED (*w) : 0; cogl_push_matrix(); _clutter_actor_apply_modelview_transform_recursive (actor, NULL); + cogl_get_modelview_matrix (mtx); - mtx_transform (mtx, x, y, z, w); + mtx_transform (mtx, &vertex); cogl_pop_matrix(); -} -/* Help macros to scale from OpenGL <-1,1> coordinates system to our - * X-window based <0,window-size> coordinates - */ -#define MTX_GL_SCALE_X(x,w,v1,v2) (COGL_FIXED_MUL (((COGL_FIXED_DIV ((x), (w)) + COGL_FIXED_1) >> 1), (v1)) + (v2)) -#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - COGL_FIXED_MUL (((COGL_FIXED_DIV ((y), (w)) + COGL_FIXED_1) >> 1), (v1)) + (v2)) -#define MTX_GL_SCALE_Z(z,w,v1,v2) (MTX_GL_SCALE_X ((z), (w), (v1), (v2))) + if (x) + *x = CLUTTER_UNITS_FROM_FIXED (vertex.x); + + if (y) + *y = CLUTTER_UNITS_FROM_FIXED (vertex.y); + + if (z) + *z = CLUTTER_UNITS_FROM_FIXED (vertex.z); + + if (w) + *w = CLUTTER_UNITS_FROM_FIXED (vertex.w); +} /** * clutter_actor_apply_relative_transform_to_point: @@ -896,21 +1010,22 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self, const ClutterVertex *point, ClutterVertex *vertex) { - ClutterVertex tmp = { 0, }; ClutterFixed v[4]; - ClutterFixed w = COGL_FIXED_1; + ClutterFixed x, y, z, w; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor)); g_return_if_fail (point != NULL); g_return_if_fail (vertex != NULL); - tmp = *point; + x = CLUTTER_UNITS_TO_FIXED (vertex->x); + y = CLUTTER_UNITS_TO_FIXED (vertex->y); + z = CLUTTER_UNITS_TO_FIXED (vertex->z); + w = COGL_FIXED_1; /* First we tranform the point using the OpenGL modelview matrix */ clutter_actor_transform_point_relative (self, ancestor, - &tmp.x, &tmp.y, &tmp.z, - &w); + &x, &y, &z, &w); cogl_get_viewport (v); @@ -918,9 +1033,12 @@ clutter_actor_apply_relative_transform_to_point (ClutterActor *self, * The w[3] parameter should always be 1.0 here, so we ignore it; otherwise * we would have to divide the original verts with it. */ - vertex->x = COGL_FIXED_MUL ((tmp.x + COGL_FIXED_0_5), v[2]); - vertex->y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - tmp.y), v[3]); - vertex->z = COGL_FIXED_MUL ((tmp.z + COGL_FIXED_0_5), v[2]); + vertex->x = + CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((x + COGL_FIXED_0_5), v[2])); + vertex->y = + CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((COGL_FIXED_0_5 - y), v[3])); + vertex->z = + CLUTTER_UNITS_FROM_FIXED (COGL_FIXED_MUL ((z + COGL_FIXED_0_5), v[2])); } /** @@ -940,30 +1058,35 @@ clutter_actor_apply_transform_to_point (ClutterActor *self, const ClutterVertex *point, ClutterVertex *vertex) { - ClutterVertex tmp = { 0, }; ClutterFixed mtx_p[16]; ClutterFixed v[4]; - ClutterFixed w = COGL_FIXED_1; + fixed_vertex_t tmp = { 0, }; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (point != NULL); g_return_if_fail (vertex != NULL); - tmp = *point; + tmp.x = CLUTTER_UNITS_TO_FIXED (vertex->x); + tmp.y = CLUTTER_UNITS_TO_FIXED (vertex->y); + tmp.z = CLUTTER_UNITS_TO_FIXED (vertex->z); + tmp.w = COGL_FIXED_1; /* First we tranform the point using the OpenGL modelview matrix */ - clutter_actor_transform_point (self, &tmp.x, &tmp.y, &tmp.z, &w); + clutter_actor_transform_point (self, &tmp.x, &tmp.y, &tmp.z, &tmp.w); cogl_get_projection_matrix (mtx_p); cogl_get_viewport (v); /* Now, transform it again with the projection matrix */ - mtx_transform (mtx_p, &tmp.x, &tmp.y, &tmp.z, &w); + mtx_transform (mtx_p, &tmp); /* Finaly translate from OpenGL coords to window coords */ - vertex->x = MTX_GL_SCALE_X (tmp.x, w, v[2], v[0]); - vertex->y = MTX_GL_SCALE_Y (tmp.y, w, v[3], v[1]); - vertex->z = MTX_GL_SCALE_Z (tmp.z, w, v[2], v[0]); + vertex->x = + CLUTTER_UNITS_FROM_FIXED (MTX_GL_SCALE_X (tmp.x, tmp.w, v[2], v[0])); + vertex->y = + CLUTTER_UNITS_FROM_FIXED (MTX_GL_SCALE_Y (tmp.y, tmp.w, v[3], v[1])); + vertex->z = + CLUTTER_UNITS_FROM_FIXED (MTX_GL_SCALE_Z (tmp.z, tmp.w, v[2], v[0])); } /* Recursively tranform supplied vertices with the tranform for the current @@ -971,66 +1094,27 @@ clutter_actor_apply_transform_to_point (ClutterActor *self, * for all the vertices in one go). */ static void -clutter_actor_transform_vertices_relative (ClutterActor *self, - ClutterActor *ancestor, - ClutterVertex verts[4], - ClutterFixed w[4]) +clutter_actor_transform_vertices_relative (ClutterActor *self, + ClutterActor *ancestor, + fixed_vertex_t vertices[]) { - ClutterFixed mtx[16]; - ClutterFixed _x, _y, _z, _w; + ClutterActorPrivate *priv = self->priv; + ClutterFixed mtx[16]; + ClutterFixed width, height; + + width = CLUTTER_UNITS_TO_FIXED (priv->allocation.x2 - priv->allocation.x1); + height = CLUTTER_UNITS_TO_FIXED (priv->allocation.y2 - priv->allocation.y1); cogl_push_matrix(); _clutter_actor_apply_modelview_transform_recursive (self, ancestor); + cogl_get_modelview_matrix (mtx); - _x = 0; - _y = 0; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[0].x = _x; - verts[0].y = _y; - verts[0].z = _z; - w[0] = _w; - - _x = self->priv->allocation.x2 - self->priv->allocation.x1; - _y = 0; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[1].x = _x; - verts[1].y = _y; - verts[1].z = _z; - w[1] = _w; - - _x = 0; - _y = self->priv->allocation.y2 - self->priv->allocation.y1; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[2].x = _x; - verts[2].y = _y; - verts[2].z = _z; - w[2] = _w; - - _x = self->priv->allocation.x2 - self->priv->allocation.x1; - _y = self->priv->allocation.y2 - self->priv->allocation.y1; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[3].x = _x; - verts[3].y = _y; - verts[3].z = _z; - w[3] = _w; + fixed_vertex_transform (mtx, 0, 0, 0, COGL_FIXED_1, &vertices[0]); + fixed_vertex_transform (mtx, width, 0, 0, COGL_FIXED_1, &vertices[1]); + fixed_vertex_transform (mtx, 0, height, 0, COGL_FIXED_1, &vertices[2]); + fixed_vertex_transform (mtx, width, height, 0, COGL_FIXED_1, &vertices[3]); cogl_pop_matrix(); } @@ -1045,12 +1129,15 @@ clutter_actor_transform_and_project_box (ClutterActor *self, const ClutterActorBox *box, ClutterVertex verts[4]) { - ClutterActor *stage; - ClutterFixed mtx[16]; - ClutterFixed mtx_p[16]; - ClutterFixed _x, _y, _z, _w; - ClutterFixed w[4]; - ClutterFixed v[4]; + ClutterActor *stage; + ClutterFixed mtx[16]; + ClutterFixed mtx_p[16]; + ClutterFixed v[4]; + ClutterFixed width, height; + fixed_vertex_t vertices[4]; + + width = CLUTTER_UNITS_TO_FIXED (box->x2 - box->x1); + height = CLUTTER_UNITS_TO_FIXED (box->y2 - box->y1); /* We essentially have to dupe some code from clutter_redraw() here * to make sure GL Matrices etc are initialised if we're called and we @@ -1071,102 +1158,25 @@ clutter_actor_transform_and_project_box (ClutterActor *self, _clutter_stage_maybe_setup_viewport (CLUTTER_STAGE (stage)); cogl_push_matrix(); + _clutter_actor_apply_modelview_transform_recursive (self, NULL); cogl_get_modelview_matrix (mtx); - _x = 0; - _y = 0; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[0].x = _x; - verts[0].y = _y; - verts[0].z = _z; - w[0] = _w; - - _x = box->x2 - box->x1; - _y = 0; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[1].x = _x; - verts[1].y = _y; - verts[1].z = _z; - w[1] = _w; - - _x = 0; - _y = box->y2 - box->y1; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[2].x = _x; - verts[2].y = _y; - verts[2].z = _z; - w[2] = _w; - - _x = box->x2 - box->x1; - _y = box->y2 - box->y1; - _z = 0; - _w = COGL_FIXED_1; - - mtx_transform (mtx, &_x, &_y, &_z, &_w); - - verts[3].x = _x; - verts[3].y = _y; - verts[3].z = _z; - w[3] = _w; + fixed_vertex_transform (mtx, 0, 0, 0, COGL_FIXED_1, &vertices[0]); + fixed_vertex_transform (mtx, width, 0, 0, COGL_FIXED_1, &vertices[1]); + fixed_vertex_transform (mtx, 0, height, 0, COGL_FIXED_1, &vertices[2]); + fixed_vertex_transform (mtx, width, height, 0, COGL_FIXED_1, &vertices[3]); cogl_pop_matrix(); cogl_get_projection_matrix (mtx_p); cogl_get_viewport (v); - mtx_transform (mtx_p, - &verts[0].x, - &verts[0].y, - &verts[0].z, - &w[0]); - - verts[0].x = MTX_GL_SCALE_X (verts[0].x, w[0], v[2], v[0]); - verts[0].y = MTX_GL_SCALE_Y (verts[0].y, w[0], v[3], v[1]); - verts[0].z = MTX_GL_SCALE_Z (verts[0].z, w[0], v[2], v[0]); - - mtx_transform (mtx_p, - &verts[1].x, - &verts[1].y, - &verts[1].z, - &w[1]); - - verts[1].x = MTX_GL_SCALE_X (verts[1].x, w[1], v[2], v[0]); - verts[1].y = MTX_GL_SCALE_Y (verts[1].y, w[1], v[3], v[1]); - verts[1].z = MTX_GL_SCALE_Z (verts[1].z, w[1], v[2], v[0]); - - mtx_transform (mtx_p, - &verts[2].x, - &verts[2].y, - &verts[2].z, - &w[2]); - - verts[2].x = MTX_GL_SCALE_X (verts[2].x, w[2], v[2], v[0]); - verts[2].y = MTX_GL_SCALE_Y (verts[2].y, w[2], v[3], v[1]); - verts[2].z = MTX_GL_SCALE_Z (verts[2].z, w[2], v[2], v[0]); - - mtx_transform (mtx_p, - &verts[3].x, - &verts[3].y, - &verts[3].z, - &w[3]); - - verts[3].x = MTX_GL_SCALE_X (verts[3].x, w[3], v[2], v[0]); - verts[3].y = MTX_GL_SCALE_Y (verts[3].y, w[3], v[3], v[1]); - verts[3].z = MTX_GL_SCALE_Z (verts[3].z, w[3], v[2], v[0]); + fixed_vertex_scale (mtx_p, &vertices[0], v, &verts[0]); + fixed_vertex_scale (mtx_p, &vertices[1], v, &verts[1]); + fixed_vertex_scale (mtx_p, &vertices[2], v, &verts[2]); + fixed_vertex_scale (mtx_p, &vertices[3], v, &verts[3]); } /** @@ -1181,10 +1191,10 @@ clutter_actor_transform_and_project_box (ClutterActor *self, * actor in the plane of @ancestor. The returned vertices relate to * the #ClutterActorBox coordinates as follows: * - * v[0] contains (x1, y1) - * v[1] contains (x2, y1) - * v[2] contains (x1, y2) - * v[3] contains (x2, y2) + * @verts[0] contains (x1, y1) + * @verts[1] contains (x2, y1) + * @verts[2] contains (x1, y2) + * @verts[3] contains (x2, y2) * * * If @ancestor is %NULL the ancestor will be the #ClutterStage. In @@ -1197,12 +1207,13 @@ clutter_actor_transform_and_project_box (ClutterActor *self, void clutter_actor_get_allocation_vertices (ClutterActor *self, ClutterActor *ancestor, - ClutterVertex verts[4]) + ClutterVertex verts[]) { - ClutterFixed v[4]; - ClutterFixed w[4]; - ClutterActorPrivate *priv; - ClutterActor *stage; + ClutterActorPrivate *priv; + ClutterActor *stage; + ClutterFixed v[4]; + fixed_vertex_t vertices[4]; + fixed_vertex_t tmp = { 0, }; g_return_if_fail (CLUTTER_IS_ACTOR (self)); g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor)); @@ -1234,28 +1245,33 @@ clutter_actor_get_allocation_vertices (ClutterActor *self, if (priv->needs_allocation) _clutter_stage_maybe_relayout (stage); - clutter_actor_transform_vertices_relative (self, ancestor, verts, w); + clutter_actor_transform_vertices_relative (self, ancestor, vertices); + cogl_get_viewport (v); /* - * The w[3] parameter should always be 1.0 here, so we ignore it; otherwise - * we would have to devide the original verts with it. + * The w[3] parameter should always be 1.0 here, so we ignore it; + * otherwise we would have to divide the original verts with it. */ - verts[0].x = COGL_FIXED_MUL ((verts[0].x + COGL_FIXED_0_5), v[2]); - verts[0].y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - verts[0].y), v[3]); - verts[0].z = COGL_FIXED_MUL ((verts[0].z + COGL_FIXED_0_5), v[2]); + tmp.x = COGL_FIXED_MUL ((vertices[0].x + COGL_FIXED_0_5), v[2]); + tmp.y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - vertices[0].y), v[3]); + tmp.z = COGL_FIXED_MUL ((vertices[0].z + COGL_FIXED_0_5), v[2]); + fixed_vertex_to_units (&tmp, &verts[0]); - verts[1].x = COGL_FIXED_MUL ((verts[1].x + COGL_FIXED_0_5), v[2]); - verts[1].y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - verts[1].y), v[3]); - verts[1].z = COGL_FIXED_MUL ((verts[1].z + COGL_FIXED_0_5), v[2]); + tmp.x = COGL_FIXED_MUL ((vertices[1].x + COGL_FIXED_0_5), v[2]); + tmp.y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - vertices[1].y), v[3]); + tmp.z = COGL_FIXED_MUL ((vertices[1].z + COGL_FIXED_0_5), v[2]); + fixed_vertex_to_units (&tmp, &verts[1]); - verts[2].x = COGL_FIXED_MUL ((verts[2].x + COGL_FIXED_0_5), v[2]); - verts[2].y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - verts[2].y), v[3]); - verts[2].z = COGL_FIXED_MUL ((verts[2].z + COGL_FIXED_0_5), v[2]); + tmp.x = COGL_FIXED_MUL ((vertices[2].x + COGL_FIXED_0_5), v[2]); + tmp.y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - vertices[2].y), v[3]); + tmp.z = COGL_FIXED_MUL ((vertices[2].z + COGL_FIXED_0_5), v[2]); + fixed_vertex_to_units (&tmp, &verts[2]); - verts[3].x = COGL_FIXED_MUL ((verts[3].x + COGL_FIXED_0_5), v[2]); - verts[3].y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - verts[3].y), v[3]); - verts[3].z = COGL_FIXED_MUL ((verts[3].z + COGL_FIXED_0_5), v[2]); + tmp.x = COGL_FIXED_MUL ((vertices[3].x + COGL_FIXED_0_5), v[2]); + tmp.y = COGL_FIXED_MUL ((COGL_FIXED_0_5 - vertices[3].y), v[3]); + tmp.z = COGL_FIXED_MUL ((vertices[3].z + COGL_FIXED_0_5), v[2]); + fixed_vertex_to_units (&tmp, &verts[3]); } /** @@ -6836,17 +6852,18 @@ clutter_scriptable_iface_init (ClutterScriptableIface *iface) * Since: 0.6 */ gboolean -clutter_actor_transform_stage_point (ClutterActor *self, - ClutterUnit x, - ClutterUnit y, - ClutterUnit *x_out, - ClutterUnit *y_out) +clutter_actor_transform_stage_point (ClutterActor *self, + ClutterUnit x, + ClutterUnit y, + ClutterUnit *x_out, + ClutterUnit *y_out) { ClutterVertex v[4]; ClutterFixed ST[3][3]; ClutterFixed RQ[3][3]; int du, dv, xi, yi; - ClutterFixed xf, yf, wf, px, py, det; + ClutterUnit px, py; + ClutterFixed xf, yf, wf, det; ClutterActorPrivate *priv; g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE); @@ -6859,11 +6876,12 @@ clutter_actor_transform_stage_point (ClutterActor *self, * * http://www.cs.cmu.edu/~ph/texfund/texfund.pdf * - * and the sample implementaion at http://www.cs.cmu.edu/~ph/src/texfund/. + * and the sample implementation at http://www.cs.cmu.edu/~ph/src/texfund/. * - * Our texture is a rectangle with origin [0,0], so we are mapping from quad - * to rectangle only, which significantly simplifies things; the function - * calls have been unrolled, and most of the math is done in fixed point. + * Our texture is a rectangle with origin [0, 0], so we are mapping from + * quad to rectangle only, which significantly simplifies things; the + * function calls have been unrolled, and most of the math is done in fixed + * point. */ clutter_actor_get_abs_allocation_vertices (self, v); @@ -6880,9 +6898,11 @@ clutter_actor_transform_stage_point (ClutterActor *self, #define FP2FX COGL_FIXED_FROM_FLOAT #define FX2FP COGL_FIXED_TO_DOUBLE +#define UX2FP CLUTTER_UNITS_TO_FLOAT +#define UX2FX CLUTTER_UNITS_TO_FIXED #define FP2INT CLUTTER_FLOAT_TO_INT -#define DET2X(a,b,c,d) (COGL_FIXED_MUL (a, d) - COGL_FIXED_MUL (b, c)) -#define DET2FP(a,b,c,d) (a*d - b*c) +#define DET2X(a,b,c,d) (COGL_FIXED_MUL ((a), (d)) - COGL_FIXED_MUL ((b), (c))) +#define DET2FP(a,b,c,d) ((a) * (d) - (b) * (c)) /* * First, find mapping from unit uv square to xy quadrilateral; this @@ -6894,20 +6914,21 @@ clutter_actor_transform_stage_point (ClutterActor *self, py = v[0].y - v[1].y + v[3].y - v[2].y; if (!px && !py) - { /* affine transform */ - RQ[0][0] = v[1].x - v[0].x; - RQ[1][0] = v[3].x - v[1].x; - RQ[2][0] = v[0].x; - RQ[0][1] = v[1].y - v[0].y; - RQ[1][1] = v[3].y - v[1].y; - RQ[2][1] = v[0].y; + { + /* affine transform */ + RQ[0][0] = UX2FX (v[1].x - v[0].x); + RQ[1][0] = UX2FX (v[3].x - v[1].x); + RQ[2][0] = UX2FX (v[0].x); + RQ[0][1] = UX2FX (v[1].y - v[0].y); + RQ[1][1] = UX2FX (v[3].y - v[1].y); + RQ[2][1] = UX2FX (v[0].y); RQ[0][2] = 0; RQ[1][2] = 0; RQ[2][2] = COGL_FIXED_1; } else - { /* - * projective transform + { + /* projective transform * * Must do this in floating point, as the del value can overflow the * range of ClutterFixed for large actors. @@ -6917,13 +6938,12 @@ clutter_actor_transform_stage_point (ClutterActor *self, */ double dx1, dx2, dy1, dy2, del; - dx1 = FX2FP (v[1].x - v[3].x); - dx2 = FX2FP (v[2].x - v[3].x); - dy1 = FX2FP (v[1].y - v[3].y); - dy2 = FX2FP (v[2].y - v[3].y); - - del = DET2FP (dx1,dx2, dy1,dy2); + dx1 = UX2FP (v[1].x - v[3].x); + dx2 = UX2FP (v[2].x - v[3].x); + dy1 = UX2FP (v[1].y - v[3].y); + dy2 = UX2FP (v[2].y - v[3].y); + del = DET2FP (dx1, dx2, dy1, dy2); if (!del) return FALSE; @@ -6931,16 +6951,20 @@ clutter_actor_transform_stage_point (ClutterActor *self, * The division here needs to be done in floating point for * precisions reasons. */ - RQ[0][2] = FP2FX (DET2FP (FX2FP(px),dx2, FX2FP(py),dy2) / del); - RQ[1][2] = FP2FX (DET2FP (dx1,FX2FP(px), dy1,FX2FP(py)) / del); - RQ[1][2] = FP2FX (DET2FP(dx1,FX2FP(px), dy1,FX2FP(py))/del); + RQ[0][2] = FP2FX (DET2FP (UX2FP (px), dx2, UX2FP (py), dy2) / del); + RQ[1][2] = FP2FX (DET2FP (dx1, UX2FP (px), dy1, UX2FP (py)) / del); + RQ[1][2] = FP2FX (DET2FP (dx1, UX2FP (px), dy1, UX2FP (py)) / del); RQ[2][2] = COGL_FIXED_1; - RQ[0][0] = v[1].x - v[0].x + COGL_FIXED_MUL (RQ[0][2], v[1].x); - RQ[1][0] = v[2].x - v[0].x + COGL_FIXED_MUL (RQ[1][2], v[2].x); - RQ[2][0] = v[0].x; - RQ[0][1] = v[1].y - v[0].y + COGL_FIXED_MUL (RQ[0][2], v[1].y); - RQ[1][1] = v[2].y - v[0].y + COGL_FIXED_MUL (RQ[1][2], v[2].y); - RQ[2][1] = v[0].y; + RQ[0][0] = UX2FX (v[1].x - v[0].x) + + COGL_FIXED_MUL (RQ[0][2], UX2FX (v[1].x)); + RQ[1][0] = UX2FX (v[2].x - v[0].x) + + COGL_FIXED_MUL (RQ[1][2], UX2FX (v[2].x)); + RQ[2][0] = UX2FX (v[0].x); + RQ[0][1] = UX2FX (v[1].y - v[0].y) + + COGL_FIXED_MUL (RQ[0][2], UX2FX (v[1].y)); + RQ[1][1] = UX2FX (v[2].y - v[0].y) + + COGL_FIXED_MUL (RQ[1][2], UX2FX (v[2].y)); + RQ[2][1] = UX2FX (v[0].y); } /* @@ -6979,24 +7003,27 @@ clutter_actor_transform_stage_point (ClutterActor *self, return FALSE; /* - * Now transform our point with the ST matrix; the notional w coordiance - * is 1, hence the last part is simply added. + * Now transform our point with the ST matrix; the notional w + * coordinate is 1, hence the last part is simply added. */ xi = CLUTTER_UNITS_TO_DEVICE (x); yi = CLUTTER_UNITS_TO_DEVICE (y); - xf = xi*ST[0][0] + yi*ST[1][0] + ST[2][0]; - yf = xi*ST[0][1] + yi*ST[1][1] + ST[2][1]; - wf = xi*ST[0][2] + yi*ST[1][2] + ST[2][2]; + xf = xi * ST[0][0] + yi * ST[1][0] + ST[2][0]; + yf = xi * ST[0][1] + yi * ST[1][1] + ST[2][1]; + wf = xi * ST[0][2] + yi * ST[1][2] + ST[2][2]; /* * The division needs to be done in floating point for precision reasons. */ if (x_out) *x_out = CLUTTER_UNITS_FROM_FLOAT (FX2FP (xf) / FX2FP (wf)); + if (y_out) *y_out = CLUTTER_UNITS_FROM_FLOAT (FX2FP (yf) / FX2FP (wf)); +#undef UX2FX +#undef UX2FP #undef FP2FX #undef FX2FP #undef FP2INT From f6e9a701e42ca4a01a41eaa7ab220bf48c23a49f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 19 Dec 2008 13:03:53 +0000 Subject: [PATCH 2/3] [tests] Fix the actor detection The test-unproject interactive test assumed that only the rectangle was on the stage. As it turns out, labels can be picked as well. --- tests/interactive/test-unproject.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/interactive/test-unproject.c b/tests/interactive/test-unproject.c index 422647e84..6af4a22cb 100644 --- a/tests/interactive/test-unproject.c +++ b/tests/interactive/test-unproject.c @@ -5,13 +5,15 @@ #include #include -ClutterActor *label; - #define RECT_L 200 #define RECT_T 150 #define RECT_W 320 #define RECT_H 240 +static ClutterActor *test_rectangle = NULL; +static ClutterActor *label = NULL; + + static gboolean on_event (ClutterStage *stage, ClutterEvent *event, @@ -29,15 +31,14 @@ on_event (ClutterStage *stage, actor = clutter_stage_get_actor_at_pos (stage, x, y); - if (clutter_actor_transform_stage_point (actor, - CLUTTER_UNITS_FROM_DEVICE (x), - CLUTTER_UNITS_FROM_DEVICE (y), - &xu2, &yu2)) + CLUTTER_UNITS_FROM_DEVICE (x), + CLUTTER_UNITS_FROM_DEVICE (y), + &xu2, &yu2)) { gchar *txt; - if (actor != CLUTTER_ACTOR (stage)) + if (actor == test_rectangle) txt = g_strdup_printf ("Click on rectangle\n" "Screen coords: [%d, %d]\n" "Local coords : [%d, %d]", @@ -117,6 +118,7 @@ test_unproject_main (int argc, char *argv[]) clutter_actor_set_rotation (rect, CLUTTER_Y_AXIS, rotate_y, 0, 0, 0); clutter_actor_set_rotation (rect, CLUTTER_Z_AXIS, rotate_z, 0, 0, 0); clutter_group_add (CLUTTER_GROUP (stage), rect); + test_rectangle = rect; txt = g_strdup_printf ("Rectangle: L %d, R %d, T %d, B %d\n" "Rotation : x %d, y %d, z %d", @@ -146,5 +148,8 @@ test_unproject_main (int argc, char *argv[]) clutter_main(); + test_rectangle = NULL; + label = NULL; + return EXIT_SUCCESS; } From cf5d69139d0ef7f380616e4eaf18fc82721f62f5 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 19 Dec 2008 13:42:17 +0000 Subject: [PATCH 3/3] [texture] Do not mix fixed point and units values Like we did for ClutterActor in commit cdb78ec4, fix ClutterTexture usage of CoglFixed and ClutterUnit values without conversion between the two types. --- clutter/clutter-texture.c | 40 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index dd95fc0a1..e636795e3 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -417,7 +417,8 @@ clutter_texture_set_fbo_projection (ClutterActor *self) ClutterTexturePrivate *priv = CLUTTER_TEXTURE (self)->priv; ClutterVertex verts[4]; ClutterFixed viewport[4]; - ClutterFixed x_min, x_max, y_min, y_max; + ClutterUnit x_min, x_max, y_min, y_max; + ClutterFixed tx_min, tx_max, ty_min, ty_max; ClutterPerspective perspective; ClutterStage *stage; ClutterFixed tan_angle, near_size; @@ -450,21 +451,26 @@ clutter_texture_set_fbo_projection (ClutterActor *self) /* Convert the coordinates back to [-1,1] range */ cogl_get_viewport (viewport); - x_min = COGL_FIXED_DIV (x_min, viewport[2]) * 2 - COGL_FIXED_1; - x_max = COGL_FIXED_DIV (x_max, viewport[2]) * 2 - COGL_FIXED_1; - y_min = COGL_FIXED_DIV (y_min, viewport[3]) * 2 - COGL_FIXED_1; - y_max = COGL_FIXED_DIV (y_max, viewport[3]) * 2 - COGL_FIXED_1; + + tx_min = COGL_FIXED_DIV (CLUTTER_UNITS_TO_FIXED (x_min), viewport[2]) + * 2 - COGL_FIXED_1; + tx_max = COGL_FIXED_DIV (CLUTTER_UNITS_TO_FIXED (x_max), viewport[2]) + * 2 - COGL_FIXED_1; + ty_min = COGL_FIXED_DIV (CLUTTER_UNITS_TO_FIXED (y_min), viewport[3]) + * 2 - COGL_FIXED_1; + ty_max = COGL_FIXED_DIV (CLUTTER_UNITS_TO_FIXED (y_max), viewport[3]) + * 2 - COGL_FIXED_1; /* Set up a projection matrix so that the actor will be projected as if it was drawn at its original location */ - tan_angle = clutter_tani (CLUTTER_ANGLE_FROM_DEGX (perspective.fovy / 2)); + tan_angle = cogl_angle_tan (COGL_ANGLE_FROM_DEGX (perspective.fovy / 2)); near_size = COGL_FIXED_MUL (perspective.z_near, tan_angle); - cogl_frustum (COGL_FIXED_MUL (x_min, near_size), - COGL_FIXED_MUL (x_max, near_size), - COGL_FIXED_MUL (-y_min, near_size), - COGL_FIXED_MUL (-y_max, near_size), - perspective.z_near, perspective.z_far); + cogl_frustum (COGL_FIXED_MUL (tx_min, near_size), + COGL_FIXED_MUL (tx_max, near_size), + COGL_FIXED_MUL (-ty_min, near_size), + COGL_FIXED_MUL (-ty_max, near_size), + perspective.z_near, perspective.z_far); } static void @@ -544,8 +550,10 @@ clutter_texture_paint (ClutterActor *self) /* Restore the perspective matrix using cogl_perspective so that the inverse matrix will be right */ - cogl_perspective (perspective.fovy, perspective.aspect, - perspective.z_near, perspective.z_far); + cogl_perspective (perspective.fovy, + perspective.aspect, + perspective.z_near, + perspective.z_far); /* If there is a shader on top of the shader stack, turn it back on. */ if (shader) @@ -588,9 +596,9 @@ clutter_texture_paint (ClutterActor *self) /* Paint will have translated us */ cogl_texture_rectangle (priv->texture, 0, 0, - COGL_FIXED_FROM_INT (x_2 - x_1), - COGL_FIXED_FROM_INT (y_2 - y_1), - 0, 0, t_w, t_h); + COGL_FIXED_FROM_INT (x_2 - x_1), + COGL_FIXED_FROM_INT (y_2 - y_1), + 0, 0, t_w, t_h); } static void