diff --git a/clutter/cogl/cogl/cogl-matrix.c b/clutter/cogl/cogl/cogl-matrix.c index e938f6325..85abab7f8 100644 --- a/clutter/cogl/cogl/cogl-matrix.c +++ b/clutter/cogl/cogl/cogl-matrix.c @@ -24,6 +24,10 @@ * Robert Bragg */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define USE_MESA_MATRIX_API #include @@ -391,4 +395,346 @@ cogl_matrix_transform_point (const CoglMatrix *matrix, *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w; } +typedef struct _Point2f +{ + float x; + float y; +} Point2f; + +typedef struct _Point3f +{ + float x; + float y; + float z; +} Point3f; + +typedef struct _Point4f +{ + float x; + float y; + float z; + float w; +} Point4f; + +static void +_cogl_matrix_transform_points_f2_packed (const CoglMatrix *matrix, + void *points_in, + void *points_out, + int n_points) +{ + Point2f *p = points_in; + Point3f *o = points_out; + int i; + + for (i = 0; i < n_points; i++) + { + o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y + + matrix->xw; + o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y + + matrix->yw; + o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y + + matrix->zw; + } +} + +static void +_cogl_matrix_transform_points_f2_strided (const CoglMatrix *matrix, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point2f *p = (Point2f *)((guint8 *)points_in + i * stride_in); + Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out); + + o->x = matrix->xx * p->x + matrix->xy * p->y + matrix->xw; + o->y = matrix->yx * p->x + matrix->yy * p->y + matrix->yw; + o->z = matrix->zx * p->x + matrix->zy * p->y + matrix->zw; + } +} + +static void +_cogl_matrix_project_points_f2_packed (const CoglMatrix *matrix, + void *points_in, + void *points_out, + int n_points) +{ + Point2f *p = points_in; + Point4f *o = points_out; + int i; + + for (i = 0; i < n_points; i++) + { + o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y + + matrix->xw; + o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y + + matrix->yw; + o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y + + matrix->zw; + o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y + + matrix->ww; + } +} + +static void +_cogl_matrix_project_points_f2_strided (const CoglMatrix *matrix, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point2f *p = (Point2f *)((guint8 *)points_in + i * stride_in); + Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out); + + o->x = matrix->xx * p->x + matrix->xy * p->y + matrix->xw; + o->y = matrix->yx * p->x + matrix->yy * p->y + matrix->yw; + o->z = matrix->zx * p->x + matrix->zy * p->y + matrix->zw; + o->w = matrix->wx * p->x + matrix->wy * p->y + matrix->ww; + } +} + +static void +_cogl_matrix_transform_points_f3_packed (const CoglMatrix *matrix, + void *points_in, + void *points_out, + int n_points) +{ + Point3f *p = points_in; + Point3f *o = points_out; + int i; + + for (i = 0; i < n_points; i++) + { + o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y + + matrix->xz * p[i].z + matrix->xw; + o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y + + matrix->yz * p[i].z + matrix->yw; + o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y + + matrix->zz * p[i].z + matrix->zw; + } +} + +static void +_cogl_matrix_transform_points_f3_strided (const CoglMatrix *matrix, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point3f *p = (Point3f *)((guint8 *)points_in + i * stride_in); + Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out); + + o->x = matrix->xx * p->x + matrix->xy * p->y + + matrix->xz * p->z + matrix->xw; + o->y = matrix->yx * p->x + matrix->yy * p->y + + matrix->yz * p->z + matrix->yw; + o->z = matrix->zx * p->x + matrix->zy * p->y + + matrix->zz * p->z + matrix->zw; + } +} + +static void +_cogl_matrix_project_points_f3_packed (const CoglMatrix *matrix, + void *points_in, + void *points_out, + int n_points) +{ + Point3f *p = points_in; + Point4f *o = points_out; + int i; + + for (i = 0; i < n_points; i++) + { + o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y + + matrix->xz * p[i].z + matrix->xw; + o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y + + matrix->yz * p[i].z + matrix->yw; + o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y + + matrix->zz * p[i].z + matrix->zw; + o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y + + matrix->wz * p[i].z + matrix->ww; + } +} + +static void +_cogl_matrix_project_points_f3_strided (const CoglMatrix *matrix, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point3f *p = (Point3f *)((guint8 *)points_in + i * stride_in); + Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out); + + o->x = matrix->xx * p->x + matrix->xy * p->y + + matrix->xz * p->z + matrix->xw; + o->y = matrix->yx * p->x + matrix->yy * p->y + + matrix->yz * p->z + matrix->yw; + o->z = matrix->zx * p->x + matrix->zy * p->y + + matrix->zz * p->z + matrix->zw; + o->w = matrix->wx * p->x + matrix->wy * p->y + + matrix->wz * p->z + matrix->ww; + } +} + +static void +_cogl_matrix_project_points_f4_packed (const CoglMatrix *matrix, + void *points_in, + void *points_out, + int n_points) +{ + Point4f *p = points_in; + Point4f *o = points_out; + int i; + + for (i = 0; i < n_points; i++) + { + o[i].x = matrix->xx * p[i].x + matrix->xy * p[i].y + + matrix->xz * p[i].z + matrix->xw * p[i].w; + o[i].y = matrix->yx * p[i].x + matrix->yy * p[i].y + + matrix->yz * p[i].z + matrix->yw * p[i].w; + o[i].z = matrix->zx * p[i].x + matrix->zy * p[i].y + + matrix->zz * p[i].z + matrix->zw * p[i].w; + o[i].w = matrix->wx * p[i].x + matrix->wy * p[i].y + + matrix->wz * p[i].z + matrix->ww * p[i].w; + } +} + +static void +_cogl_matrix_project_points_f4_strided (const CoglMatrix *matrix, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + int i; + + for (i = 0; i < n_points; i++) + { + Point4f *p = (Point4f *)((guint8 *)points_in + i * stride_in); + Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out); + + o->x = matrix->xx * p->x + matrix->xy * p->y + + matrix->xz * p->z + matrix->xw * p->w; + o->y = matrix->yx * p->x + matrix->yy * p->y + + matrix->yz * p->z + matrix->yw * p->w; + o->z = matrix->zx * p->x + matrix->zy * p->y + + matrix->zz * p->z + matrix->zw * p->w; + o->w = matrix->wx * p->x + matrix->wy * p->y + + matrix->wz * p->z + matrix->ww * p->w; + } +} + +void +cogl_matrix_transform_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + /* The results of transforming always have three components... */ + g_return_if_fail (stride_out >= sizeof (Point3f)); + + if (n_components == 2) + { + if (stride_in == sizeof (Point2f) && + stride_out == sizeof (Point3f)) + _cogl_matrix_transform_points_f2_packed (matrix, + points_in, points_out, + n_points); + else + _cogl_matrix_transform_points_f2_strided (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } + else + { + g_return_if_fail (n_components == 3); + + if (stride_in == sizeof (Point3f) && stride_out == stride_in) + _cogl_matrix_transform_points_f3_packed (matrix, + points_in, points_out, + n_points); + else + _cogl_matrix_transform_points_f3_strided (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } +} + +void +cogl_matrix_project_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points) +{ + if (n_components == 2) + { + if (stride_in == sizeof (Point2f) && + stride_out == sizeof (Point4f)) + _cogl_matrix_project_points_f2_packed (matrix, + points_in, points_out, + n_points); + else + _cogl_matrix_project_points_f2_strided (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } + else if (n_components == 3) + { + if (stride_in == sizeof (Point3f) && + stride_out == sizeof (Point4f)) + _cogl_matrix_project_points_f3_packed (matrix, + points_in, points_out, + n_points); + else + _cogl_matrix_project_points_f3_strided (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } + else + { + g_return_if_fail (n_components == 4); + + if (stride_in == sizeof (Point4f) && stride_out == stride_in) + _cogl_matrix_project_points_f4_packed (matrix, + points_in, points_out, + n_points); + else + _cogl_matrix_project_points_f4_strided (matrix, + stride_in, points_in, + stride_out, points_out, + n_points); + } +} diff --git a/clutter/cogl/cogl/cogl-matrix.h b/clutter/cogl/cogl/cogl-matrix.h index d866437f3..8904d881b 100644 --- a/clutter/cogl/cogl/cogl-matrix.h +++ b/clutter/cogl/cogl/cogl-matrix.h @@ -316,6 +316,10 @@ gboolean cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse); +/* FIXME: to be consistent with cogl_matrix_{transform,project}_points + * this could be renamed to cogl_matrix_project_point for Cogl 2.0... + */ + /** * cogl_matrix_transform_point: * @matrix: A 4x4 transformation matrix @@ -334,6 +338,125 @@ cogl_matrix_transform_point (const CoglMatrix *matrix, float *z, float *w); +#ifdef COGL_ENABLE_EXPERIMENTAL_API +#define cogl_matrix_transform_points cogl_matrix_transform_points_EXP +#define cogl_matrix_project_points cogl_matrix_project_points_EXP + +/** + * cogl_matrix_transform_points: + * @matrix: A transformation matrix + * @n_components: The number of position components for each input point. + * (either 2 or 3) + * @stride_in: The stride in bytes between input points. + * @points_in: A pointer to the first component of the first input point. + * @stride_out: The stride in bytes between output points. + * @points_out: A pointer to the first component of the first output point. + * @n_points: The number of points to transform. + * + * Transforms an array of input points and writes the result to + * another array of output points. The input points can either have 2 + * or 3 components each. The output points always have 3 components. + * The output array can simply point to the input array to do the + * transform in-place. + * + * If you need to transform 4 component points see + * cogl_matrix_project_points(). + * + * Here's an example with differing input/output strides: + * |[ + * typedef struct { + * float x,y; + * guint8 r,g,b,a; + * float s,t,p; + * } MyInVertex; + * typedef struct { + * guint8 r,g,b,a; + * float x,y,z; + * } MyOutVertex; + * MyInVertex vertices[N_VERTICES]; + * MyOutVertex results[N_VERTICES]; + * CoglMatrix matrix; + * + * my_load_vertices (vertices); + * my_get_matrix (&matrix); + * + * cogl_matrix_transform_points (&matrix, + * 2, + * sizeof (MyInVertex), + * &vertices[0].x, + * sizeof (MyOutVertex), + * &results[0].x, + * N_VERTICES); + * ]| + * + * Stability: Unstable + */ +void +cogl_matrix_transform_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points); + +/** + * cogl_matrix_project_points: + * @matrix: A projection matrix + * @n_components: The number of position components for each input point. + * (either 2, 3 or 4) + * @stride_in: The stride in bytes between input points. + * @points_in: A pointer to the first component of the first input point. + * @stride_out: The stride in bytes between output points. + * @points_out: A pointer to the first component of the first output point. + * @n_points: The number of points to transform. + * + * Projects an array of input points and writes the result to another + * array of output points. The input points can either have 2, 3 or 4 + * components each. The output points always have 4 components (known + * as homogenous coordinates). The output array can simply point to + * the input array to do the transform in-place. + * + * Here's an example with differing input/output strides: + * |[ + * typedef struct { + * float x,y; + * guint8 r,g,b,a; + * float s,t,p; + * } MyInVertex; + * typedef struct { + * guint8 r,g,b,a; + * float x,y,z; + * } MyOutVertex; + * MyInVertex vertices[N_VERTICES]; + * MyOutVertex results[N_VERTICES]; + * CoglMatrix matrix; + * + * my_load_vertices (vertices); + * my_get_matrix (&matrix); + * + * cogl_matrix_project_points (&matrix, + * 2, + * sizeof (MyInVertex), + * &vertices[0].x, + * sizeof (MyOutVertex), + * &results[0].x, + * N_VERTICES); + * ]| + * + * Stability: Unstable + */ +void +cogl_matrix_project_points (const CoglMatrix *matrix, + int n_components, + size_t stride_in, + void *points_in, + size_t stride_out, + void *points_out, + int n_points); + +#endif /* COGL_ENABLE_EXPERIMENTAL_API */ + G_END_DECLS #endif /* __COGL_MATRIX_H */ diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index d6c0cb74f..098be39aa 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -436,7 +436,6 @@ cogl_matrix_init_identity cogl_matrix_frustum cogl_matrix_ortho cogl_matrix_perspective -cogl_matrix_transform_point cogl_matrix_multiply cogl_matrix_rotate cogl_matrix_translate @@ -444,6 +443,7 @@ cogl_matrix_scale cogl_matrix_init_from_array cogl_matrix_get_array cogl_matrix_get_inverse +cogl_matrix_transform_point