From fa8d6dc69b61e31873a6aa5550a5e3a0c203d6ae Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 11 Dec 2008 20:08:15 +0000 Subject: [PATCH] Adds CoglMatrix utility code --- clutter/cogl/cogl-matrix.h | 102 ++++++++++++++++++++++ clutter/cogl/common/Makefile.am | 3 +- clutter/cogl/common/cogl-matrix.c | 138 ++++++++++++++++++++++++++++++ clutter/cogl/common/cogl-matrix.h | 57 ++++++++++++ 4 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 clutter/cogl/cogl-matrix.h create mode 100644 clutter/cogl/common/cogl-matrix.c create mode 100644 clutter/cogl/common/cogl-matrix.h diff --git a/clutter/cogl/cogl-matrix.h b/clutter/cogl/cogl-matrix.h new file mode 100644 index 000000000..44444691e --- /dev/null +++ b/clutter/cogl/cogl-matrix.h @@ -0,0 +1,102 @@ +#ifndef __COGL_MATRIX_H +#define __COGL_MATRIX_H + +/* Note: This is ordered according to how OpenGL expects to get 4x4 matrices */ +typedef struct { + /* column 0 */ + float xx; + float yx; + float zx; + float wx; + + /* column 1 */ + float xy; + float yy; + float zy; + float wy; + + /* column 2 */ + float xz; + float yz; + float zz; + float wz; + + /* column 3 */ + float xw; + float yw; + float zw; + float ww; + + /* Note: we may want to extend this later with private flags + * and a cache of the inverse transform matrix. */ +} CoglMatrix; + +/** + * cogl_matrix_init_identity: + * @matrix: A 4x4 transformation matrix + * + * Resets matrix to the identity matrix + */ +void cogl_matrix_init_identity (CoglMatrix *matrix); + +/** + * cogl_matrix_multiply: + * @result: The address of a 4x4 matrix to store the result in + * @a: A 4x4 transformation matrix + * @b: A 4x4 transformation matrix + * + * This function multiples the two supplied matricies together and stores + * the result in 'result' + */ +void cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b); + +/** + * cogl_matrix_rotate: + * @matrix: A 4x4 transformation matrix + * @angle: The angle you want to rotate in degrees + * @x: X component of your rotation vector + * @y: Y component of your rotation vector + * @z: Z component of your rotation vector + * + * This function multiples your matrix with a rotation matrix that applies + * a rotation of angle degrees around the specified 3D vector. + */ +void cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z); + +/* cogl_matrix_translate: + * @matrix: A 4x4 transformation matrix + * @x: The X translation you want to apply + * @y: The Y translation you want to apply + * @z: The Z translation you want to apply + * + * This function multiples your matrix with a transform matrix that translates + * along the X, Y and Z axis. + */ +void cogl_matrix_translate (CoglMatrix *matrix, + float x, + float y, + float z); + +/** + * cogl_matrix_scale: + * @matrix: A 4x4 transformation matrix + * @sx: The X scale factor + * @sy: The Y scale factor + * @sz: The Z scale factor + * + * This function multiples your matrix with a transform matrix that scales + * along the X, Y and Z axis. + */ +void cogl_matrix_scale (CoglMatrix *matrix, + float sx, + float sy, + float sz); + +#endif /* __COGL_MATRIX_H */ + diff --git a/clutter/cogl/common/Makefile.am b/clutter/cogl/common/Makefile.am index db0f0b42d..755001e1f 100644 --- a/clutter/cogl/common/Makefile.am +++ b/clutter/cogl/common/Makefile.am @@ -29,4 +29,5 @@ libclutter_cogl_common_la_SOURCES = \ cogl-clip-stack.c \ cogl-fixed.c \ cogl-color.c \ - cogl-mesh.c + cogl-mesh.c \ + cogl-matrix.c diff --git a/clutter/cogl/common/cogl-matrix.c b/clutter/cogl/common/cogl-matrix.c new file mode 100644 index 000000000..8786da570 --- /dev/null +++ b/clutter/cogl/common/cogl-matrix.c @@ -0,0 +1,138 @@ +#include + +#include +#include + +void +cogl_matrix_init_identity (CoglMatrix *matrix) +{ + matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0; + matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0; + matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0; + matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1; +} + +void +cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b) +{ + CoglMatrix r; + + /* row 0 */ + r.xx = a->xx * b->xx + a->xy * b->yx + a->xz * b->zx + a->xw * b->wx; + r.xy = a->xx * b->xy + a->xy * b->yy + a->xz * b->zy + a->xw * b->wy; + r.xz = a->xx * b->xz + a->xy * b->yz + a->xz * b->zz + a->xw * b->wz; + r.xw = a->xx * b->xw + a->xy * b->yw + a->xz * b->zw + a->xw * b->ww; + + /* row 1 */ + r.yx = a->yx * b->xx + a->yy * b->yx + a->yz * b->zx + a->yw * b->wx; + r.yy = a->yx * b->xy + a->yy * b->yy + a->yz * b->zy + a->yw * b->wy; + r.yz = a->yx * b->xz + a->yy * b->yz + a->yz * b->zz + a->yw * b->wz; + r.yw = a->yx * b->xw + a->yy * b->yw + a->yz * b->zw + a->yw * b->ww; + + /* row 2 */ + r.zx = a->zx * b->xx + a->zy * b->yx + a->zz * b->zx + a->zw * b->wx; + r.zy = a->zx * b->xy + a->zy * b->yy + a->zz * b->zy + a->zw * b->wy; + r.zz = a->zx * b->xz + a->zy * b->yz + a->zz * b->zz + a->zw * b->wz; + r.zw = a->zx * b->xw + a->zy * b->yw + a->zz * b->zw + a->zw * b->ww; + + /* row 3 */ + r.wx = a->wx * b->xx + a->wy * b->yx + a->wz * b->zx + a->ww * b->wx; + r.wy = a->wx * b->xy + a->wy * b->yy + a->wz * b->zy + a->ww * b->wy; + r.wz = a->wx * b->xz + a->wy * b->yz + a->wz * b->zz + a->ww * b->wz; + r.ww = a->wx * b->xw + a->wy * b->yw + a->wz * b->zw + a->ww * b->ww; + + /* The idea was that having this unrolled; it might be easier for the + * compiler to vectorize, but that's probably not true. Mesa does it + * using a single for (i=0; i<4; i++) approach, may that's better... + */ + + *result = r; +} + +/** + * cogl_3dmatrix_rotate: + * matrix: A 3D Affine transformation matrix + * angle: The angle in degrees you want to rotate by + * x: The X component of your rotation vector + * y: The Y component of your rotation vector + * z: The Z component of your rotation vector + * + * The matrix is multiplied with a rotation matrix representing a rotation + * of angle degress around the vector (x,y,z) + */ +void +cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z) +{ + CoglMatrix rotation; + CoglMatrix result; + angle *= G_PI / 180.0f; + float c = cosf (angle); + float s = sinf (angle); + + rotation.xx = x * x * (1.0f - c) + c; + rotation.yx = y * x * (1.0f - c) + z * s; + rotation.zx = x * z * (1.0f - c) - y * s; + rotation.wx = 0.0f; + + rotation.xy = x * y * (1.0f - c) - z * s; + rotation.yy = y * y * (1.0f - c) + c; + rotation.zy = y * z * (1.0f - c) + x * s; + rotation.wy = 0.0f; + + rotation.xz = x * z * (1.0f - c) + y * s; + rotation.yz = y * z * (1.0f - c) - x * s; + rotation.zz = z * z * (1.0f - c) + c; + rotation.wz = 0.0f; + + rotation.xw = 0.0f; + rotation.yw = 0.0f; + rotation.zw = 0.0f; + rotation.ww = 1.0f; + + cogl_matrix_multiply (&result, matrix, &rotation); + *matrix = result; +} + +void +cogl_matrix_translate (CoglMatrix *matrix, + float x, + float y, + float z) +{ + matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw; + matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw; + matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw; + matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww; +} + +void +cogl_matrix_scale (CoglMatrix *matrix, + float sx, + float sy, + float sz) +{ + matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz; + matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz; + matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz; + matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz; +} + +#if 0 +gboolean +cogl_matrix_invert (CoglMatrix *matrix) +{ + /* TODO */ + /* Note: It might be nice to also use the flag based tricks that mesa does + * to alow it to track the type of transformations a matrix represents + * so it can use various assumptions to optimise the inversion. + */ +} +#endif + + diff --git a/clutter/cogl/common/cogl-matrix.h b/clutter/cogl/common/cogl-matrix.h new file mode 100644 index 000000000..2f6874fae --- /dev/null +++ b/clutter/cogl/common/cogl-matrix.h @@ -0,0 +1,57 @@ +#ifndef __COGL_MATRIX_H +#define __COGL_MATRIX_H + +/* Note: This is ordered according to how OpenGL expects to get 4x4 matrices */ +typedef struct { + /* column 0 */ + float xx; + float yx; + float zx; + float wx; + + /* column 1 */ + float xy; + float yy; + float zy; + float wy; + + /* column 2 */ + float xz; + float yz; + float zz; + float wz; + + /* column 3 */ + float xw; + float yw; + float zw; + float ww; + + /* Note: we may want to extend this later with private flags + * and a cache of the inverse transform matrix. */ +} CoglMatrix; + +void cogl_matrix_init_identity (CoglMatrix *matrix); + +void cogl_matrix_multiply (CoglMatrix *result, + const CoglMatrix *a, + const CoglMatrix *b); + +void cogl_matrix_rotate (CoglMatrix *matrix, + float angle, + float x, + float y, + float z); + +void cogl_matrix_translate (CoglMatrix *matrix, + float x, + float y, + float z); + +void cogl_matrix_scale (CoglMatrix *matrix, + float sx, + float sy, + float sz); + +#endif /* __COGL_MATRIX_H */ +