static void paint_matrix_pipeline (CoglPipeline *pipeline) { CoglMatrix matrices[4]; float matrix_floats[16 * 4]; int uniform_location; int i; for (i = 0; i < 4; i++) cogl_matrix_init_identity (matrices + i); /* Use the first matrix to make the color red */ cogl_matrix_translate (matrices + 0, 1.0f, 0.0f, 0.0f); /* Rotate the vertex so that it ends up green */ cogl_matrix_rotate (matrices + 1, 90.0f, 0.0f, 0.0f, 1.0f); /* Scale the vertex so it ends up halved */ cogl_matrix_scale (matrices + 2, 0.5f, 0.5f, 0.5f); /* Add a blue component in the final matrix. The final matrix is uploaded as transposed so we need to transpose first to cancel that out */ cogl_matrix_translate (matrices + 3, 0.0f, 0.0f, 1.0f); cogl_matrix_transpose (matrices + 3); for (i = 0; i < 4; i++) memcpy (matrix_floats + i * 16, cogl_matrix_get_array (matrices + i), sizeof (float) * 16); /* Set the first three matrices as transposed */ uniform_location = cogl_pipeline_get_uniform_location (pipeline, "matrix_array"); cogl_pipeline_set_uniform_matrix (pipeline, uniform_location, 4, /* dimensions */ 3, /* count */ FALSE, /* not transposed */ matrix_floats); /* Set the last matrix as untransposed */ uniform_location = cogl_pipeline_get_uniform_location (pipeline, "matrix_array[3]"); cogl_pipeline_set_uniform_matrix (pipeline, uniform_location, 4, /* dimensions */ 1, /* count */ TRUE, /* transposed */ matrix_floats + 16 * 3); paint_pipeline (pipeline, 12); }
static gboolean clutter_pan_action_real_pan (ClutterPanAction *self, ClutterActor *actor, gboolean is_interpolated) { ClutterPanActionPrivate *priv = self->priv; gfloat dx, dy; ClutterMatrix transform; clutter_pan_action_get_motion_delta (self, 0, &dx, &dy); switch (priv->pan_axis) { case CLUTTER_PAN_AXIS_NONE: break; case CLUTTER_PAN_X_AXIS: dy = 0.0f; break; case CLUTTER_PAN_Y_AXIS: dx = 0.0f; break; } clutter_actor_get_child_transform (actor, &transform); cogl_matrix_translate (&transform, dx, dy, 0.0f); clutter_actor_set_child_transform (actor, &transform); return TRUE; }
static void mx_fade_effect_post_paint (ClutterEffect *effect) { MxFadeEffectPrivate *priv = MX_FADE_EFFECT (effect)->priv; if (!priv->freeze_update) CLUTTER_EFFECT_CLASS (mx_fade_effect_parent_class)->post_paint (effect); else { CoglMatrix modelview; ClutterActor *actor, *stage; actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); stage = clutter_actor_get_stage (actor); /* Set up the draw matrix so we draw the offscreen texture at the * absolute coordinates of the actor-box. We need to do this to * avoid transforming by the actor matrix twice, as when it's drawn * into the offscreen surface, it'll already be transformed. */ cogl_push_matrix (); cogl_matrix_init_identity (&modelview); CLUTTER_ACTOR_CLASS (G_OBJECT_GET_CLASS (stage))-> apply_transform (stage, &modelview); cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.f); cogl_set_modelview_matrix (&modelview); clutter_offscreen_effect_paint_target (CLUTTER_OFFSCREEN_EFFECT (effect)); cogl_pop_matrix (); } }
void cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix, float left, float right, float bottom, float top, float z_near, float z_2d, float width_2d, float height_2d) { float left_2d_plane = left / z_near * z_2d; float right_2d_plane = right / z_near * z_2d; float bottom_2d_plane = bottom / z_near * z_2d; float top_2d_plane = top / z_near * z_2d; float width_2d_start = right_2d_plane - left_2d_plane; float height_2d_start = top_2d_plane - bottom_2d_plane; /* Factors to scale from framebuffer geometry to frustum * cross-section geometry. */ float width_scale = width_2d_start / width_2d; float height_scale = height_2d_start / height_2d; cogl_matrix_translate (matrix, left_2d_plane, top_2d_plane, -z_2d); cogl_matrix_scale (matrix, width_scale, -height_scale, width_scale); }
void rut_transform_translate (RutTransform *transform, float x, float y, float z) { cogl_matrix_translate (&transform->matrix, x, y, z); }
void _cogl_matrix_stack_translate (CoglMatrixStack *stack, float x, float y, float z) { CoglMatrixState *state; state = _cogl_matrix_stack_top_mutable (stack, TRUE); cogl_matrix_translate (&state->matrix, x, y, z); state->is_identity = FALSE; stack->age++; }
static void mex_column_apply_transform (ClutterActor *actor, CoglMatrix *matrix) { MexColumnPrivate *priv = MEX_COLUMN (actor)->priv; CLUTTER_ACTOR_CLASS (mex_column_parent_class)-> apply_transform (actor, matrix); if (priv->adjustment) cogl_matrix_translate (matrix, 0, -priv->adjustment_value, 0); }
void mai_node_draw_recursive (MaiNode *self) { CoglMatrix initial_mtx; cogl_matrix_init_identity (&initial_mtx); cogl_set_modelview_matrix (&initial_mtx); cogl_set_source_color4ub ('\x1', '\x1', '\xFF', 255); cogl_set_source_texture (g_testtex); cogl_ortho (0, 64, 0, 64, -1, 1); cogl_matrix_translate (&initial_mtx, 20.0f, 20.0f, 0.0f); cogl_matrix_scale (&initial_mtx, 5.0f, 5.0f, 1.0f); cogl_matrix_rotate(&initial_mtx, -90.0f, 1.0f, 0.0f, 0.0f); _mai_node_draw_recursive (self, &initial_mtx); cogl_flush (); }
static void mx_deform_bow_tie_texture_vflip (ClutterTexture *texture) { CoglHandle material; material = clutter_texture_get_cogl_material (texture); if (material) { CoglMatrix matrix; cogl_matrix_init_identity (&matrix); /* Vflip */ cogl_matrix_scale (&matrix, 1.f, -1.f, 1.f); cogl_matrix_translate (&matrix, 0.f, 1.f, 0.f); cogl_material_set_layer_matrix (material, 0, &matrix); } }
/* Update view depending on scrollbar values */ static void _xfdashboard_viewpad_update_view_viewport(XfdashboardViewpad *self) { XfdashboardViewpadPrivate *priv; ClutterMatrix transform; gfloat x, y, w, h; g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self)); priv=self->priv; /* Check for active view */ if(priv->activeView==NULL) { g_warning(_("Cannot update viewport of view because no one is active")); return; } /* Get offset from scrollbars and view size from clipping */ if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView))) { clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, &w, &h); } else { x=y=0.0f; clutter_actor_get_size(CLUTTER_ACTOR(priv->activeView), &w, &h); } /* To avoid blur convert float to ints (virtually) */ x=ceil(x); y=ceil(y); w=ceil(w); h=ceil(h); /* Set transformation (offset) */ cogl_matrix_init_identity(&transform); cogl_matrix_translate(&transform, -x, -y, 0.0f); clutter_actor_set_transform(CLUTTER_ACTOR(priv->activeView), &transform); /* Set new clipping */ clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, w, h); }
static void mx_viewport_apply_transform (ClutterActor *actor, CoglMatrix *matrix) { MxViewportPrivate *priv = MX_VIEWPORT (actor)->priv; gdouble x, y; CLUTTER_ACTOR_CLASS (mx_viewport_parent_class)->apply_transform (actor, matrix); if (priv->hadjustment) x = mx_adjustment_get_value (priv->hadjustment); else x = 0; if (priv->vadjustment) y = mx_adjustment_get_value (priv->vadjustment); else y = 0; cogl_matrix_translate (matrix, (int) -x, (int) -y, 0); }
static void st_box_layout_apply_transform (ClutterActor *a, CoglMatrix *m) { StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (a)->priv; gdouble x, y; CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->apply_transform (a, m); if (priv->hadjustment) x = st_adjustment_get_value (priv->hadjustment); else x = 0; if (priv->vadjustment) y = st_adjustment_get_value (priv->vadjustment); else y = 0; cogl_matrix_translate (m, (int) -x, (int) -y, 0); }
G_MODULE_EXPORT int test_cogl_multitexture_main (int argc, char *argv[]) { GError *error = NULL; ClutterActor *stage; ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff }; TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1); gfloat stage_w, stage_h; gchar **files; gfloat tex_coords[] = { /* tx1 ty1 tx2 ty2 */ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1 }; if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; stage = clutter_stage_new (); clutter_actor_get_size (stage, &stage_w, &stage_h); clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl: Multi-texturing"); clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); /* We create a non-descript actor that we know doesn't have a * default paint handler, so that we can easily control * painting in a paint signal handler, without having to * sub-class anything etc. */ state->group = clutter_group_new (); clutter_actor_set_position (state->group, stage_w / 2, stage_h / 2); g_signal_connect (state->group, "paint", G_CALLBACK(material_rectangle_paint), state); files = g_new (gchar*, 4); files[0] = g_build_filename (TESTS_DATADIR, "redhand_alpha.png", NULL); files[1] = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); files[2] = g_build_filename (TESTS_DATADIR, "light0.png", NULL); files[3] = NULL; state->alpha_tex = cogl_texture_new_from_file (files[0], COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!state->alpha_tex) g_critical ("Failed to load redhand_alpha.png: %s", error->message); state->redhand_tex = cogl_texture_new_from_file (files[1], COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!state->redhand_tex) g_critical ("Failed to load redhand.png: %s", error->message); state->light_tex0 = cogl_texture_new_from_file (files[2], COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!state->light_tex0) g_critical ("Failed to load light0.png: %s", error->message); state->light_tex1 = cogl_texture_new_from_file (files[2], COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_ANY, &error); if (!state->light_tex1) g_critical ("Failed to load light0.png: %s", error->message); g_strfreev (files); state->material0 = cogl_material_new (); cogl_material_set_layer (state->material0, 0, state->alpha_tex); cogl_material_set_layer (state->material0, 1, state->redhand_tex); cogl_material_set_layer (state->material0, 2, state->light_tex0); state->material1 = cogl_material_new (); cogl_material_set_layer (state->material1, 0, state->alpha_tex); cogl_material_set_layer (state->material1, 1, state->redhand_tex); cogl_material_set_layer (state->material1, 2, state->light_tex1); state->tex_coords = tex_coords; cogl_matrix_init_identity (&state->tex_matrix0); cogl_matrix_init_identity (&state->tex_matrix1); cogl_matrix_init_identity (&state->rot_matrix0); cogl_matrix_init_identity (&state->rot_matrix1); cogl_matrix_translate (&state->rot_matrix0, 0.5, 0.5, 0); cogl_matrix_rotate (&state->rot_matrix0, 10.0, 0, 0, 1.0); cogl_matrix_translate (&state->rot_matrix0, -0.5, -0.5, 0); cogl_matrix_translate (&state->rot_matrix1, 0.5, 0.5, 0); cogl_matrix_rotate (&state->rot_matrix1, -10.0, 0, 0, 1.0); cogl_matrix_translate (&state->rot_matrix1, -0.5, -0.5, 0); clutter_actor_set_anchor_point (state->group, 86, 125); clutter_container_add_actor (CLUTTER_CONTAINER(stage), state->group); state->timeline = clutter_timeline_new (2812); g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state); clutter_actor_animate_with_timeline (state->group, CLUTTER_LINEAR, state->timeline, "rotation-angle-y", 30.0, "signal-after::completed", animation_completed_cb, state, NULL); /* start the timeline and thus the animations */ clutter_timeline_start (state->timeline); clutter_actor_show_all (stage); clutter_main(); cogl_handle_unref (state->material1); cogl_handle_unref (state->material0); cogl_handle_unref (state->alpha_tex); cogl_handle_unref (state->redhand_tex); cogl_handle_unref (state->light_tex0); cogl_handle_unref (state->light_tex1); g_free (state); return 0; }
static RutShapeModel * shape_model_new (RutContext *ctx, CoglBool shaped, float tex_width, float tex_height) { RutShapeModel *shape_model = g_slice_new (RutShapeModel); RutBuffer *buffer = rut_buffer_new (sizeof (CoglVertexP3) * 6); RutMesh *pick_mesh = rut_mesh_new_from_buffer_p3 (COGL_VERTICES_MODE_TRIANGLES, 6, buffer); CoglVertexP3 *pick_vertices = (CoglVertexP3 *)buffer->data; CoglMatrix matrix; float tex_aspect; float size_x; float size_y; float half_size_x; float half_size_y; float geom_size_x; float geom_size_y; float half_geom_size_x; float half_geom_size_y; rut_object_init (&shape_model->_parent, &rut_shape_model_type); shape_model->ref_count = 1; if (shaped) { /* In this case we are using a shape mask texture which is has a * square size and is padded with transparent pixels to provide * antialiasing. The shape mask is half the size of the texture * itself so we make the geometry twice as large to compensate. */ size_x = MIN (tex_width, tex_height); size_y = size_x; geom_size_x = size_x * 2.0; geom_size_y = geom_size_x; } else { size_x = tex_width; size_y = tex_height; geom_size_x = tex_width; geom_size_y = tex_height; } half_size_x = size_x / 2.0; half_size_y = size_y / 2.0; half_geom_size_x = geom_size_x / 2.0; half_geom_size_y = geom_size_y / 2.0; { int n_vertices; int i; VertexP2T2T2 vertices[] = { { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 }, { -half_geom_size_x, half_geom_size_y, 0, 1, 0, 1 }, { half_geom_size_x, half_geom_size_y, 1, 1, 1, 1 }, { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 }, { half_geom_size_x, half_geom_size_y, 1, 1, 1, 1 }, { half_geom_size_x, -half_geom_size_y, 1, 0, 1, 0 }, }; cogl_matrix_init_identity (&matrix); tex_aspect = (float)tex_width / (float)tex_height; if (shaped) { float s_scale, t_scale; float s0, t0; /* NB: The circle mask texture has a centered circle that is * half the width of the texture itself. We want the primary * texture to be mapped to this center circle. */ s_scale = 2; t_scale = 2; if (tex_aspect < 1) /* taller than it is wide */ t_scale *= tex_aspect; else /* wider than it is tall */ { float inverse_aspect = 1.0f / tex_aspect; s_scale *= inverse_aspect; } s0 = 0.5 - (s_scale / 2.0); t0 = 0.5 - (t_scale / 2.0); cogl_matrix_translate (&matrix, s0, t0, 0); cogl_matrix_scale (&matrix, s_scale, t_scale, 1); } n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2); for (i = 0; i < n_vertices; i++) { float z = 0, w = 1; cogl_matrix_transform_point (&matrix, &vertices[i].s1, &vertices[i].t1, &z, &w); #ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND vertices[i].Nx = 0; vertices[i].Ny = 0; vertices[i].Nz = 1; vertices[i].Tx = 1; vertices[i].Ty = 0; vertices[i].Tz = 0; #endif } shape_model->primitive = primitive_new_p2t2t2 (ctx->cogl_context, COGL_VERTICES_MODE_TRIANGLES, n_vertices, vertices); } shape_model->shape_texture = cogl_object_ref (ctx->circle_texture); pick_vertices[0].x = -half_size_x; pick_vertices[0].y = -half_size_y; pick_vertices[1].x = -half_size_x; pick_vertices[1].y = half_size_y; pick_vertices[2].x = half_size_x; pick_vertices[2].y = half_size_y; pick_vertices[3] = pick_vertices[0]; pick_vertices[4] = pick_vertices[2]; pick_vertices[5].x = half_size_x; pick_vertices[5].y = -half_size_y; shape_model->pick_mesh = pick_mesh; return shape_model; }
/* In addition to writing the stack matrix into the give @matrix * argument this function *may* sometimes also return a pointer * to a matrix too so if we are querying the inverse matrix we * should query from the return matrix so that the result can * be cached within the stack. */ CoglMatrix * cogl_matrix_entry_get (CoglMatrixEntry *entry, CoglMatrix *matrix) { int depth; CoglMatrixEntry *current; CoglMatrixEntry **children; int i; for (depth = 0, current = entry; current; current = current->parent, depth++) { switch (current->op) { case COGL_MATRIX_OP_LOAD_IDENTITY: cogl_matrix_init_identity (matrix); goto initialized; case COGL_MATRIX_OP_LOAD: { CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)current; *matrix = *load->matrix; goto initialized; } case COGL_MATRIX_OP_SAVE: { CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)current; if (!save->cache_valid) { CoglMagazine *matrices_magazine = cogl_matrix_stack_matrices_magazine; save->cache = _cogl_magazine_chunk_alloc (matrices_magazine); cogl_matrix_entry_get (current->parent, save->cache); save->cache_valid = TRUE; } *matrix = *save->cache; goto initialized; } default: continue; } } initialized: if (depth == 0) { switch (entry->op) { case COGL_MATRIX_OP_LOAD_IDENTITY: case COGL_MATRIX_OP_TRANSLATE: case COGL_MATRIX_OP_ROTATE: case COGL_MATRIX_OP_ROTATE_QUATERNION: case COGL_MATRIX_OP_ROTATE_EULER: case COGL_MATRIX_OP_SCALE: case COGL_MATRIX_OP_MULTIPLY: return NULL; case COGL_MATRIX_OP_LOAD: { CoglMatrixEntryLoad *load = (CoglMatrixEntryLoad *)entry; return load->matrix; } case COGL_MATRIX_OP_SAVE: { CoglMatrixEntrySave *save = (CoglMatrixEntrySave *)entry; return save->cache; } } g_warn_if_reached (); return NULL; } #ifdef COGL_ENABLE_DEBUG if (!current) { g_warning ("Inconsistent matrix stack"); return NULL; } entry->composite_gets++; #endif children = g_alloca (sizeof (CoglMatrixEntry) * depth); /* We need walk the list of entries from the init/load/save entry * back towards the leaf node but the nodes don't link to their * children so we need to re-walk them here to add to a separate * array. */ for (i = depth - 1, current = entry; i >= 0 && current; i--, current = current->parent) { children[i] = current; } #ifdef COGL_ENABLE_DEBUG if (COGL_DEBUG_ENABLED (COGL_DEBUG_PERFORMANCE) && entry->composite_gets >= 2) { COGL_NOTE (PERFORMANCE, "Re-composing a matrix stack entry multiple times"); } #endif for (i = 0; i < depth; i++) { switch (children[i]->op) { case COGL_MATRIX_OP_TRANSLATE: { CoglMatrixEntryTranslate *translate = (CoglMatrixEntryTranslate *)children[i]; cogl_matrix_translate (matrix, translate->x, translate->y, translate->z); continue; } case COGL_MATRIX_OP_ROTATE: { CoglMatrixEntryRotate *rotate= (CoglMatrixEntryRotate *)children[i]; cogl_matrix_rotate (matrix, rotate->angle, rotate->x, rotate->y, rotate->z); continue; } case COGL_MATRIX_OP_ROTATE_EULER: { CoglMatrixEntryRotateEuler *rotate = (CoglMatrixEntryRotateEuler *)children[i]; CoglEuler euler; cogl_euler_init (&euler, rotate->heading, rotate->pitch, rotate->roll); cogl_matrix_rotate_euler (matrix, &euler); continue; } case COGL_MATRIX_OP_ROTATE_QUATERNION: { CoglMatrixEntryRotateQuaternion *rotate = (CoglMatrixEntryRotateQuaternion *)children[i]; CoglQuaternion quaternion; cogl_quaternion_init_from_array (&quaternion, rotate->values); cogl_matrix_rotate_quaternion (matrix, &quaternion); continue; } case COGL_MATRIX_OP_SCALE: { CoglMatrixEntryScale *scale = (CoglMatrixEntryScale *)children[i]; cogl_matrix_scale (matrix, scale->x, scale->y, scale->z); continue; } case COGL_MATRIX_OP_MULTIPLY: { CoglMatrixEntryMultiply *multiply = (CoglMatrixEntryMultiply *)children[i]; cogl_matrix_multiply (matrix, matrix, multiply->matrix); continue; } case COGL_MATRIX_OP_LOAD_IDENTITY: case COGL_MATRIX_OP_LOAD: case COGL_MATRIX_OP_SAVE: g_warn_if_reached (); continue; } } return NULL; }
static RutDiamondSlice * diamond_slice_new (RutContext *ctx, float size, int tex_width, int tex_height) { RutDiamondSlice *diamond_slice = g_slice_new (RutDiamondSlice); float width = size; float height = size; #define DIAMOND_SLICE_CORNER_RADIUS 20 CoglMatrix matrix; float tex_aspect; rut_object_init (&diamond_slice->_parent, &rut_diamond_slice_type); diamond_slice->ref_count = 1; diamond_slice->size = size; { /* x0,y0,x1,y1 and s0,t0,s1,t1 define the postion and texture * coordinates for the center rectangle... */ float x0 = DIAMOND_SLICE_CORNER_RADIUS; float y0 = DIAMOND_SLICE_CORNER_RADIUS; float x1 = width - DIAMOND_SLICE_CORNER_RADIUS; float y1 = height - DIAMOND_SLICE_CORNER_RADIUS; /* The center region of the nine-slice can simply map to the * degenerate center of the circle */ float s0 = 0.5; float t0 = 0.5; float s1 = 0.5; float t1 = 0.5; int n_vertices; int i; /* * 0,0 x0,0 x1,0 width,0 * 0,0 s0,0 s1,0 1,0 * 0 1 2 3 * * 0,y0 x0,y0 x1,y0 width,y0 * 0,t0 s0,t0 s1,t0 1,t0 * 4 5 6 7 * * 0,y1 x0,y1 x1,y1 width,y1 * 0,t1 s0,t1 s1,t1 1,t1 * 8 9 10 11 * * 0,height x0,height x1,height width,height * 0,1 s0,1 s1,1 1,1 * 12 13 14 15 */ VertexP2T2T2 vertices[] = { { 0, 0, 0, 0, 0, 0 }, { x0, 0, s0, 0, x0, 0}, { x1, 0, s1, 0, x1, 0}, { width, 0, 1, 0, width, 0}, { 0, y0, 0, t0, 0, y0}, { x0, y0, s0, t0, x0, y0}, { x1, y0, s1, t0, x1, y0}, { width, y0, 1, t0, width, y0}, { 0, y1, 0, t1, 0, y1}, { x0, y1, s0, t1, x0, y1}, { x1, y1, s1, t1, x1, y1}, { width, y1, 1, t1, width, y1}, { 0, height, 0, 1, 0, height}, { x0, height, s0, 1, x0, height}, { x1, height, s1, 1, x1, height}, { width, height, 1, 1, width, height}, }; cogl_matrix_init_identity (&diamond_slice->rotate_matrix); cogl_matrix_rotate (&diamond_slice->rotate_matrix, 45, 0, 0, 1); cogl_matrix_translate (&diamond_slice->rotate_matrix, - width / 2.0, - height / 2.0, 0); n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2); for (i = 0; i < n_vertices; i++) { float z = 0, w = 1; cogl_matrix_transform_point (&diamond_slice->rotate_matrix, &vertices[i].x, &vertices[i].y, &z, &w); #ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND vertices[i].Nx = 0; vertices[i].Ny = 0; vertices[i].Nz = 1; vertices[i].Tx = 1; vertices[i].Ty = 0; vertices[i].Tz = 0; #endif } cogl_matrix_init_identity (&matrix); { float s_scale = 1.0, t_scale = 1.0; float s0, t0; float diagonal_size_scale = 1.0 / (sinf (G_PI_4) * 2.0); tex_aspect = (float)tex_width / (float)tex_height; if (tex_aspect < 1) /* taller than it is wide */ t_scale *= tex_aspect; else /* wider than it is tall */ { float inverse_aspect = 1.0f / tex_aspect; s_scale *= inverse_aspect; } s_scale *= diagonal_size_scale; t_scale *= diagonal_size_scale; s0 = 0.5 - (s_scale / 2.0); t0 = 0.5 - (t_scale / 2.0); cogl_matrix_translate (&matrix, s0, t0, 0); cogl_matrix_scale (&matrix, s_scale / width, t_scale / height, 1); cogl_matrix_translate (&matrix, width / 2.0, height / 2.0, 1); cogl_matrix_rotate (&matrix, 45, 0, 0, 1); cogl_matrix_translate (&matrix, -width / 2.0, -height / 2.0, 1); } n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2); for (i = 0; i < n_vertices; i++) { float z = 0, w = 1; cogl_matrix_transform_point (&matrix, &vertices[i].s1, &vertices[i].t1, &z, &w); } diamond_slice->primitive = primitive_new_p2t2t2 (ctx->cogl_context, COGL_VERTICES_MODE_TRIANGLES, n_vertices, vertices); /* The vertices uploaded only map to the key intersection points of the * 9-slice grid which isn't a topology that GPUs can handle directly so * this specifies an array of indices that allow the GPU to interpret the * vertices as a list of triangles... */ cogl_primitive_set_indices (diamond_slice->primitive, ctx->nine_slice_indices, sizeof (_rut_nine_slice_indices_data) / sizeof (_rut_nine_slice_indices_data[0])); } return diamond_slice; }
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 = 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 */ shear_res = shear1[2] + (shear2[2] - shear1[2]) * progress; /* YZ */ if (shear_res != 0.f) _clutter_util_matrix_skew_yz (&res, shear_res); shear_res = shear1[1] + (shear2[1] - shear1[1]) * progress; /* XZ */ if (shear_res != 0.f) _clutter_util_matrix_skew_xz (&res, shear_res); shear_res = shear1[0] + (shear2[0] - shear1[0]) * progress; /* XY */ if (shear_res != 0.f) _clutter_util_matrix_skew_xy (&res, shear_res); /* 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; }