From 962b84ed56877237344c0f9f8079585392ed5580 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 8 Feb 2011 15:21:41 +0000 Subject: [PATCH] matrix: adds 2d view transform conveniences This adds two new experimental functions to cogl-matrix.c: cogl_matrix_view_2d_in_perspective and cogl_matrix_view_2d_in_frustum which can be used to setup a view transform that maps a 2D coordinate system (0,0) top left and (width,height) bottom right to the current viewport. Toolkits such as Clutter that want to mix 2D and 3D drawing can use these APIs to position a 2D coordinate system at an arbitrary depth inside a 3D perspective projected viewing frustum. --- cogl/cogl-matrix.c | 57 +++++++++++++++++++++++++++++++++ cogl/cogl-matrix.h | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/cogl/cogl-matrix.c b/cogl/cogl-matrix.c index 5da5b474a..344b67d5b 100644 --- a/cogl/cogl-matrix.c +++ b/cogl/cogl-matrix.c @@ -304,6 +304,63 @@ cogl_matrix_ortho (CoglMatrix *matrix, _COGL_MATRIX_DEBUG_PRINT (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); +} + +/* Assuming a symmetric perspective matrix is being used for your + * projective transform this convenience function lets you compose a + * view transform such that geometry on the z=0 plane will map to + * screen coordinates with a top left origin of (0,0) and with the + * given width and height. + */ +void +cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_2d, + float width_2d, + float height_2d) +{ + float top = z_near * tan (fov_y * G_PI / 360.0); + cogl_matrix_view_2d_in_frustum (matrix, + -top * aspect, + top * aspect, + -top, + top, + z_near, + z_2d, + width_2d, + height_2d); +} + void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array) { diff --git a/cogl/cogl-matrix.h b/cogl/cogl-matrix.h index 8e9f207ab..c5d59871d 100644 --- a/cogl/cogl-matrix.h +++ b/cogl/cogl-matrix.h @@ -258,6 +258,86 @@ cogl_matrix_ortho (CoglMatrix *matrix, float z_near, float z_far); +#ifdef COGL_ENABLE_EXPERIMENTAL_API +#define cogl_matrix_view_2d_in_frustum cogl_matrix_view_2d_in_frustum_EXP +#define cogl_matrix_view_2d_in_perspective \ + cogl_matrix_view_2d_in_perspective_EXP + +/** + * cogl_matrix_view_2d_in_frustum: + * @matrix: A 4x4 transformation matrix + * @left: coord of left vertical clipping plane + * @right: coord of right vertical clipping plane + * @bottom: coord of bottom horizontal clipping plane + * @top: coord of top horizontal clipping plane + * @z_near: The distance to the near clip plane. Never pass 0 and always pass + * a positive number. + * @z_2d: The distance to the 2D plane. (Should always be positive and + * be between @z_near and the z_far value that was passed to + * cogl_matrix_frustum()) + * @width_2d: The width of the 2D coordinate system + * @height_2d: The height of the 2D coordinate system + * + * Multiplies @matrix by a view transform that maps the 2D coordinates + * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport + * size. Geometry at a depth of 0 will now lie on this 2D plane. + * + * Note: this doesn't multiply the matrix by any projection matrix, + * but it assumes you have a perspective projection as defined by + * passing the corresponding arguments to cogl_matrix_frustum(). + + * Toolkits such as Clutter that mix 2D and 3D drawing can use this to + * create a 2D coordinate system within a 3D perspective projected + * view frustum. + */ +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); + +/** + * cogl_matrix_view_2d_in_perspective: + * @fov_y: A field of view angle for the Y axis + * @aspect: The ratio of width to height determining the field of view angle + * for the x axis. + * @z_near: The distance to the near clip plane. Never pass 0 and always pass + * a positive number. + * @z_2d: The distance to the 2D plane. (Should always be positive and + * be between @z_near and the z_far value that was passed to + * cogl_matrix_frustum()) + * @width_2d: The width of the 2D coordinate system + * @height_2d: The height of the 2D coordinate system + * + * Multiplies @matrix by a view transform that maps the 2D coordinates + * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport + * size. Geometry at a depth of 0 will now lie on this 2D plane. + * + * Note: this doesn't multiply the matrix by any projection matrix, + * but it assumes you have a perspective projection as defined by + * passing the corresponding arguments to cogl_matrix_perspective(). + * + * Toolkits such as Clutter that mix 2D and 3D drawing can use this to + * create a 2D coordinate system within a 3D perspective projected + * view frustum. + + */ +void +cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix, + float fov_y, + float aspect, + float z_near, + float z_2d, + float width_2d, + float height_2d); + +#endif + /** * cogl_matrix_init_from_array: * @matrix: A 4x4 transformation matrix