From e2cc64faa29c27d726eb43bcfb7ae39bbac62fee Mon Sep 17 00:00:00 2001 From: Tomas Frydrych Date: Thu, 31 May 2007 19:14:28 +0000 Subject: [PATCH] include perspective transfore in calculation of vertices --- ChangeLog | 12 +++ clutter/clutter-actor.c | 204 +++++++++++++++++++++++++++++++------- clutter/clutter-private.h | 2 + clutter/clutter-stage.c | 43 ++++++++ 4 files changed, 226 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9c3cb607..57764982c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,18 @@ * examples/test-entry.c: (on_key_release_cb), (main): A basic test for ClutterEntry +2007-05-31 Tomas Frydrych + + * clutter/clutter-stage.c: + * clutter/clutter-private.h: + (_clutter_stage_get_perspective_matrix): + New function. + + * clutter/clutter-actor.c: + (clutter_actor_get_tranformed_vertices): + (clutter_actor_get_tranformed_point): + Apply perspective matrix on the top of actor transform matrix. + 2007-05-31 Tomas Frydrych * clutter/clutter-actor.c: diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 4410841be..0f22d0c3e 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -454,74 +454,202 @@ mtx_transform (ClutterFixed *m, } static void -mtx_create (ClutterActorPrivate *priv, ClutterFixed *mtx) +mtx_mul (ClutterFixed * m1, const ClutterFixed * m2) +{ + ClutterFixed n0, n1, n2, n3; + + n0 = + CFX_MUL (M(m1,0,0),M(m2,0,0)) + + CFX_MUL (M(m1,0,1),M(m2,1,0)) + + CFX_MUL (M(m1,0,2),M(m2,2,0)) + + CFX_MUL (M(m1,0,3),M(m2,3,0)); + + n1 = + CFX_MUL (M(m1,0,0),M(m2,0,1)) + + CFX_MUL (M(m1,0,1),M(m2,1,1)) + + CFX_MUL (M(m1,0,2),M(m2,2,1)) + + CFX_MUL (M(m1,0,3),M(m2,3,1)); + + n2 = + CFX_MUL (M(m1,0,0),M(m2,0,2)) + + CFX_MUL (M(m1,0,1),M(m2,1,2)) + + CFX_MUL (M(m1,0,2),M(m2,2,2)) + + CFX_MUL (M(m1,0,3),M(m2,3,2)); + + n3 = + CFX_MUL (M(m1,0,0),M(m2,0,3)) + + CFX_MUL (M(m1,0,1),M(m2,1,3)) + + CFX_MUL (M(m1,0,2),M(m2,2,3)) + + CFX_MUL (M(m1,0,3),M(m2,3,3)); + + M(m1,0,0) = n0; + M(m1,0,1) = n1; + M(m1,0,2) = n2; + M(m1,0,3) = n3; + + n0 = + CFX_MUL (M(m1,1,0),M(m2,0,0)) + + CFX_MUL (M(m1,1,1),M(m2,1,0)) + + CFX_MUL (M(m1,1,2),M(m2,2,0)) + + CFX_MUL (M(m1,1,3),M(m2,3,0)); + + n1 = + CFX_MUL (M(m1,1,0),M(m2,0,1)) + + CFX_MUL (M(m1,1,1),M(m2,1,1)) + + CFX_MUL (M(m1,1,2),M(m2,2,1)) + + CFX_MUL (M(m1,1,3),M(m2,3,1)); + + n2 = + CFX_MUL (M(m1,1,0),M(m2,0,2)) + + CFX_MUL (M(m1,1,1),M(m2,1,2)) + + CFX_MUL (M(m1,1,2),M(m2,2,2)) + + CFX_MUL (M(m1,1,3),M(m2,3,2)); + + n3 = + CFX_MUL (M(m1,1,0),M(m2,0,3)) + + CFX_MUL (M(m1,1,1),M(m2,1,3)) + + CFX_MUL (M(m1,1,2),M(m2,2,3)) + + CFX_MUL (M(m1,1,3),M(m2,3,3)); + + M(m1,1,0) = n0; + M(m1,1,1) = n1; + M(m1,1,2) = n2; + M(m1,1,3) = n3; + + n0 = + CFX_MUL (M(m1,2,0),M(m2,0,0)) + + CFX_MUL (M(m1,2,1),M(m2,1,0)) + + CFX_MUL (M(m1,2,2),M(m2,2,0)) + + CFX_MUL (M(m1,2,3),M(m2,3,0)); + + n1 = + CFX_MUL (M(m1,2,0),M(m2,0,1)) + + CFX_MUL (M(m1,2,1),M(m2,1,1)) + + CFX_MUL (M(m1,2,2),M(m2,2,1)) + + CFX_MUL (M(m1,2,3),M(m2,3,1)); + + n2 = + CFX_MUL (M(m1,2,0),M(m2,0,2)) + + CFX_MUL (M(m1,2,1),M(m2,1,2)) + + CFX_MUL (M(m1,2,2),M(m2,2,2)) + + CFX_MUL (M(m1,2,3),M(m2,3,2)); + + n3 = + CFX_MUL (M(m1,2,0),M(m2,0,3)) + + CFX_MUL (M(m1,2,1),M(m2,1,3)) + + CFX_MUL (M(m1,2,2),M(m2,2,3)) + + CFX_MUL (M(m1,2,3),M(m2,3,3)); + + M(m1,2,0) = n0; + M(m1,2,1) = n1; + M(m1,2,2) = n2; + M(m1,2,3) = n3; + + n0 = + CFX_MUL (M(m1,3,0),M(m2,0,0)) + + CFX_MUL (M(m1,3,1),M(m2,1,0)) + + CFX_MUL (M(m1,3,2),M(m2,2,0)) + + CFX_MUL (M(m1,3,3),M(m2,3,0)); + + n1 = + CFX_MUL (M(m1,3,0),M(m2,0,1)) + + CFX_MUL (M(m1,3,1),M(m2,1,1)) + + CFX_MUL (M(m1,3,2),M(m2,2,1)) + + CFX_MUL (M(m1,3,3),M(m2,3,1)); + + n2 = + CFX_MUL (M(m1,3,0),M(m2,0,2)) + + CFX_MUL (M(m1,3,1),M(m2,1,2)) + + CFX_MUL (M(m1,3,2),M(m2,2,2)) + + CFX_MUL (M(m1,3,3),M(m2,3,2)); + + n3 = + CFX_MUL (M(m1,3,0),M(m2,0,3)) + + CFX_MUL (M(m1,3,1),M(m2,1,3)) + + CFX_MUL (M(m1,3,2),M(m2,2,3)) + + CFX_MUL (M(m1,3,3),M(m2,3,3)); + + M(m1,3,0) = n0; + M(m1,3,1) = n1; + M(m1,3,2) = n2; + M(m1,3,3) = n3; +} + +/* Creates a transform matrix by combining the actor transformations and the + * stage perspective + */ +static void +mtx_create (ClutterActorPrivate *priv, + ClutterFixed *mtx, + const ClutterFixed * mtx_p) { /* FIXME: need to apply perspective / viewport transforms */ - - mtx_identity (&mtx[0]); + mtx_identity (mtx); /* * 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], + mtx_translate (mtx, CLUTTER_UNITS_TO_FIXED (priv->coords.x1), CLUTTER_UNITS_TO_FIXED (priv->coords.y1), CLUTTER_INT_TO_FIXED (priv->z)); if (priv->rzang) { - mtx_translate (&mtx[0], - CLUTTER_INT_TO_FIXED (priv->rzx), - CLUTTER_INT_TO_FIXED (priv->rzy), - 0); + mtx_translate (mtx, + CLUTTER_INT_TO_FIXED (priv->rzx), + CLUTTER_INT_TO_FIXED (priv->rzy), + 0); - mtx_rotate_z (&mtx[0], priv->rzang); + mtx_rotate_z (mtx, priv->rzang); - mtx_translate (&mtx[0], - CLUTTER_INT_TO_FIXED (-priv->rzx), - CLUTTER_INT_TO_FIXED (-priv->rzy), - 0); + mtx_translate (mtx, + CLUTTER_INT_TO_FIXED (-priv->rzx), + CLUTTER_INT_TO_FIXED (-priv->rzy), + 0); } if (priv->ryang) { - mtx_translate (&mtx[0], - CLUTTER_INT_TO_FIXED (priv->ryx), - 0, - CLUTTER_INT_TO_FIXED (priv->z + priv->ryz)); + mtx_translate (mtx, + CLUTTER_INT_TO_FIXED (priv->ryx), + 0, + CLUTTER_INT_TO_FIXED (priv->z + priv->ryz)); - mtx_rotate_y (&mtx[0], priv->ryang); + mtx_rotate_y (mtx, priv->ryang); - mtx_translate (&mtx[0], - CLUTTER_INT_TO_FIXED (-priv->ryx), - 0, - CLUTTER_INT_TO_FIXED (-(priv->z + priv->ryz))); + mtx_translate (mtx, + CLUTTER_INT_TO_FIXED (-priv->ryx), + 0, + CLUTTER_INT_TO_FIXED (-(priv->z + priv->ryz))); } if (priv->rxang) { - mtx_translate (&mtx[0], - 0, - CLUTTER_INT_TO_FIXED (priv->rxy), - CLUTTER_INT_TO_FIXED (priv->z + priv->rxz)); + mtx_translate (mtx, + 0, + CLUTTER_INT_TO_FIXED (priv->rxy), + CLUTTER_INT_TO_FIXED (priv->z + priv->rxz)); - mtx_rotate_x (&mtx[0], priv->rxang); + mtx_rotate_x (mtx, priv->rxang); - mtx_translate (&mtx[0], - 0, - CLUTTER_INT_TO_FIXED (-priv->rxy), - CLUTTER_INT_TO_FIXED (-(priv->z - priv->rxz))); + mtx_translate (mtx, + 0, + CLUTTER_INT_TO_FIXED (-priv->rxy), + CLUTTER_INT_TO_FIXED (-(priv->z - priv->rxz))); } if (priv->z) - mtx_translate (&mtx[0], 0, 0, CLUTTER_INT_TO_FIXED (priv->z)); + mtx_translate (mtx, 0, 0, CLUTTER_INT_TO_FIXED (priv->z)); if (priv->scale_x != CFX_ONE || priv->scale_y != CFX_ONE) { - mtx_scale (&mtx[0], priv->scale_x, priv->scale_y); + mtx_scale (mtx, priv->scale_x, priv->scale_y); } + + mtx_mul (mtx, mtx_p); } /** @@ -547,13 +675,16 @@ clutter_actor_get_transformed_point (ClutterActor *actor, ClutterUnit *z_return) { ClutterFixed mtx[16]; + const ClutterFixed *mtx_p; ClutterActorPrivate *priv; g_return_if_fail (CLUTTER_IS_ACTOR (actor)); priv = actor->priv; - mtx_create (priv, &mtx[0]); + mtx_p = _clutter_stage_get_perspective_matrix (CLUTTER_STAGE (clutter_stage_get_default())); + + mtx_create (priv, &mtx[0], mtx_p); *x_return = CLUTTER_UNITS_FROM_INT(x) - priv->coords.x1; *y_return = CLUTTER_UNITS_FROM_INT(y) - priv->coords.y1; @@ -576,6 +707,7 @@ clutter_actor_get_transformed_vertices (ClutterActor * self, ClutterVertices * verts) { ClutterFixed mtx[16]; + const ClutterFixed *mtx_p; ClutterFixed x, y, z; ClutterActorPrivate *priv; @@ -587,7 +719,9 @@ clutter_actor_get_transformed_vertices (ClutterActor * self, priv = self->priv; - mtx_create (priv, &mtx[0]); + mtx_p = _clutter_stage_get_perspective_matrix (CLUTTER_STAGE (clutter_stage_get_default())); + + mtx_create (priv, &mtx[0], mtx_p); #if 0 g_debug ("Matrix\n" diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 0844df7b2..9bdd29e88 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -119,6 +119,8 @@ void _clutter_event_button_generate (ClutterBackend *backend, void _clutter_feature_init (void); +const ClutterFixed * _clutter_stage_get_perspective_matrix (ClutterStage * stage); + /* Does this need to be private ? */ void clutter_do_event (ClutterEvent *event); diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 7ea15e1d3..31fb2b69d 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -61,6 +61,8 @@ struct _ClutterStagePrivate guint is_fullscreen : 1; guint is_offscreen : 1; guint is_cursor_visible : 1; + + ClutterFixed perspective_mtx[16]; }; enum @@ -484,6 +486,43 @@ clutter_stage_get_color (ClutterStage *stage, color->alpha = priv->color.alpha; } +static void +_clutter_stage_refresh_perspective_matrix (ClutterStagePrivate * priv) +{ + ClutterFixed xmax, ymax; + ClutterFixed x, y, c, d; + + memset (&priv->perspective_mtx[0], 0, sizeof (priv->perspective_mtx)); + + ymax = clutter_qmulx (priv->perspective.z_near, + clutter_tani (priv->perspective.fovy >> 1)); + + xmax = clutter_qmulx (ymax, priv->perspective.aspect); + + x = CFX_DIV (priv->perspective.z_near, xmax); + y = CFX_DIV (priv->perspective.z_near, ymax); + c = CFX_DIV (-(priv->perspective.z_far + priv->perspective.z_near), + ( priv->perspective.z_far - priv->perspective.z_near)); + + d = CFX_DIV (-(clutter_qmulx (2 * priv->perspective.z_far, + priv->perspective.z_near)), + (priv->perspective.z_far - priv->perspective.z_near)); + +#define M(row,col) priv->perspective_mtx[col*4+row] + M(0,0) = x; + M(1,1) = y; + M(2,2) = c; + M(2,3) = d; + M(3,2) = -CFX_ONE; +#undef M +} + +const ClutterFixed * +_clutter_stage_get_perspective_matrix (ClutterStage * stage) +{ + return &stage->priv->perspective_mtx[0]; +} + /** * clutter_stage_set_perspectivex * @stage: A #ClutterStage @@ -505,6 +544,8 @@ clutter_stage_set_perspectivex (ClutterStage *stage, priv->perspective.z_near = perspective->z_near; priv->perspective.z_far = perspective->z_far; + _clutter_stage_refresh_perspective_matrix (priv); + CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES); } @@ -554,6 +595,8 @@ clutter_stage_set_perspective (ClutterStage *stage, priv->perspective.z_near = CLUTTER_FLOAT_TO_FIXED(z_near); priv->perspective.z_far = CLUTTER_FLOAT_TO_FIXED(z_far); + _clutter_stage_refresh_perspective_matrix (priv); + CLUTTER_SET_PRIVATE_FLAGS(stage, CLUTTER_ACTOR_SYNC_MATRICES); }