/*<private> * _clutter_paint_volume_get_box: * @pv: a #ClutterPaintVolume * @box: a pixel aligned #ClutterGeometry * * Transforms a 3D paint volume into a 2D bounding box in the * same coordinate space as the 3D paint volume. * * To get an actors "paint box" you should first project * the paint volume into window coordinates before getting * the 2D bounding box. * * <note>The coordinates of the returned box are not clamped to * integer pixel values, if you need them to be clamped you can use * clutter_actor_box_clamp_to_pixel()</note> * * Since: 1.6 */ void _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv, ClutterActorBox *box) { gfloat x_min, y_min, x_max, y_max; ClutterVertex *vertices; int count; gint i; g_return_if_fail (pv != NULL); g_return_if_fail (box != NULL); if (pv->is_empty) { box->x1 = box->x2 = pv->vertices[0].x; box->y1 = box->y2 = pv->vertices[0].y; return; } /* Updates the vertices we calculate lazily * (See ClutterPaintVolume typedef for more details) */ _clutter_paint_volume_complete (pv); vertices = pv->vertices; x_min = x_max = vertices[0].x; y_min = y_max = vertices[0].y; /* Most actors are 2D so we only have to look at the front 4 * vertices of the paint volume... */ if (G_LIKELY (pv->is_2d)) count = 4; else count = 8; for (i = 1; i < count; i++) { if (vertices[i].x < x_min) x_min = vertices[i].x; else if (vertices[i].x > x_max) x_max = vertices[i].x; if (vertices[i].y < y_min) y_min = vertices[i].y; else if (vertices[i].y > y_max) y_max = vertices[i].y; } box->x1 = x_min; box->y1 = y_min; box->x2 = x_max; box->y2 = y_max; }
void _clutter_paint_volume_project (ClutterPaintVolume *pv, const CoglMatrix *modelview, const CoglMatrix *projection, const int *viewport) { int transform_count; if (pv->is_empty) { /* Just transform the origin... */ _clutter_util_fully_transform_vertices (modelview, projection, viewport, pv->vertices, pv->vertices, 1); return; } /* All the vertices must be up to date, since after the projection * it wont be trivial to derive the other vertices. */ _clutter_paint_volume_complete (pv); /* Most actors are 2D so we only have to transform the front 4 * vertices of the paint volume... */ if (G_LIKELY (pv->is_2d)) transform_count = 4; else transform_count = 8; _clutter_util_fully_transform_vertices (modelview, projection, viewport, pv->vertices, pv->vertices, transform_count); pv->is_axis_aligned = FALSE; }
void _clutter_paint_volume_transform (ClutterPaintVolume *pv, const CoglMatrix *matrix) { int transform_count; if (pv->is_empty) { gfloat w = 1; /* Just transform the origin */ cogl_matrix_transform_point (matrix, &pv->vertices[0].x, &pv->vertices[0].y, &pv->vertices[0].z, &w); return; } /* All the vertices must be up to date, since after the transform * it wont be trivial to derive the other vertices. */ _clutter_paint_volume_complete (pv); /* Most actors are 2D so we only have to transform the front 4 * vertices of the paint volume... */ if (G_LIKELY (pv->is_2d)) transform_count = 4; else transform_count = 8; cogl_matrix_transform_points (matrix, 3, sizeof (ClutterVertex), pv->vertices, sizeof (ClutterVertex), pv->vertices, transform_count); pv->is_axis_aligned = FALSE; }
/* Given a paint volume that has been transformed by an arbitrary * modelview and is no longer axis aligned, this derives a replacement * that is axis aligned. */ void _clutter_paint_volume_axis_align (ClutterPaintVolume *pv) { int count; int i; ClutterVertex origin; float max_x; float max_y; float max_z; g_return_if_fail (pv != NULL); if (pv->is_empty) return; if (G_LIKELY (pv->is_axis_aligned)) return; if (G_LIKELY (pv->vertices[0].x == pv->vertices[1].x && pv->vertices[0].y == pv->vertices[3].y && pv->vertices[0].z == pv->vertices[4].z)) { pv->is_axis_aligned = TRUE; return; } if (!pv->is_complete) _clutter_paint_volume_complete (pv); origin = pv->vertices[0]; max_x = pv->vertices[0].x; max_y = pv->vertices[0].y; max_z = pv->vertices[0].z; count = pv->is_2d ? 4 : 8; for (i = 1; i < count; i++) { if (pv->vertices[i].x < origin.x) origin.x = pv->vertices[i].x; else if (pv->vertices[i].x > max_x) max_x = pv->vertices[i].x; if (pv->vertices[i].y < origin.y) origin.y = pv->vertices[i].y; else if (pv->vertices[i].y > max_y) max_y = pv->vertices[i].y; if (pv->vertices[i].z < origin.z) origin.z = pv->vertices[i].z; else if (pv->vertices[i].z > max_z) max_z = pv->vertices[i].z; } pv->vertices[0] = origin; pv->vertices[1].x = max_x; pv->vertices[1].y = origin.y; pv->vertices[1].z = origin.z; pv->vertices[3].x = origin.x; pv->vertices[3].y = max_y; pv->vertices[3].z = origin.z; pv->vertices[4].x = origin.x; pv->vertices[4].y = origin.y; pv->vertices[4].z = max_z; pv->is_complete = FALSE; pv->is_axis_aligned = TRUE; if (pv->vertices[4].z == pv->vertices[0].z) pv->is_2d = TRUE; else pv->is_2d = FALSE; }