mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 09:30:45 -05:00
cogl/matrix: Rotate using graphene
This commit is contained in:
parent
d0590de9e8
commit
1aac180e8d
@ -98,20 +98,6 @@ static float identity[16] = {
|
|||||||
0.0, 0.0, 0.0, 1.0
|
0.0, 0.0, 0.0, 1.0
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
matrix_multiply_array_with_flags (CoglMatrix *result,
|
|
||||||
const float *array)
|
|
||||||
{
|
|
||||||
graphene_matrix_t m1, m2, res;
|
|
||||||
|
|
||||||
cogl_matrix_to_graphene_matrix (result, &m1);
|
|
||||||
graphene_matrix_init_from_float (&m2, array);
|
|
||||||
|
|
||||||
graphene_matrix_multiply (&m2, &m1, &res);
|
|
||||||
graphene_matrix_to_cogl_matrix (&res, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_multiply (CoglMatrix *result,
|
cogl_matrix_multiply (CoglMatrix *result,
|
||||||
const CoglMatrix *a,
|
const CoglMatrix *a,
|
||||||
@ -166,201 +152,6 @@ cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate a 4x4 transformation matrix from glRotate parameters, and
|
|
||||||
* post-multiply the input matrix by it.
|
|
||||||
*
|
|
||||||
* \author
|
|
||||||
* This function was contributed by Erich Boleyn (erich@uruk.org).
|
|
||||||
* Optimizations contributed by Rudolf Opalla (rudi@khm.de).
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
_cogl_matrix_rotate (CoglMatrix *matrix,
|
|
||||||
float angle,
|
|
||||||
float x,
|
|
||||||
float y,
|
|
||||||
float z)
|
|
||||||
{
|
|
||||||
float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
|
|
||||||
float m[16];
|
|
||||||
gboolean optimized;
|
|
||||||
|
|
||||||
s = sinf (angle * DEG2RAD);
|
|
||||||
c = cosf (angle * DEG2RAD);
|
|
||||||
|
|
||||||
memcpy (m, identity, 16 * sizeof (float));
|
|
||||||
optimized = FALSE;
|
|
||||||
|
|
||||||
#define M(row,col) m[col*4+row]
|
|
||||||
|
|
||||||
if (x == 0.0f)
|
|
||||||
{
|
|
||||||
if (y == 0.0f)
|
|
||||||
{
|
|
||||||
if (z != 0.0f)
|
|
||||||
{
|
|
||||||
optimized = TRUE;
|
|
||||||
/* rotate only around z-axis */
|
|
||||||
M (0,0) = c;
|
|
||||||
M (1,1) = c;
|
|
||||||
if (z < 0.0f)
|
|
||||||
{
|
|
||||||
M (0,1) = s;
|
|
||||||
M (1,0) = -s;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
M (0,1) = -s;
|
|
||||||
M (1,0) = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (z == 0.0f)
|
|
||||||
{
|
|
||||||
optimized = TRUE;
|
|
||||||
/* rotate only around y-axis */
|
|
||||||
M (0,0) = c;
|
|
||||||
M (2,2) = c;
|
|
||||||
if (y < 0.0f)
|
|
||||||
{
|
|
||||||
M (0,2) = -s;
|
|
||||||
M (2,0) = s;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
M (0,2) = s;
|
|
||||||
M (2,0) = -s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (y == 0.0f)
|
|
||||||
{
|
|
||||||
if (z == 0.0f)
|
|
||||||
{
|
|
||||||
optimized = TRUE;
|
|
||||||
/* rotate only around x-axis */
|
|
||||||
M (1,1) = c;
|
|
||||||
M (2,2) = c;
|
|
||||||
if (x < 0.0f)
|
|
||||||
{
|
|
||||||
M (1,2) = s;
|
|
||||||
M (2,1) = -s;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
M (1,2) = -s;
|
|
||||||
M (2,1) = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!optimized)
|
|
||||||
{
|
|
||||||
const float mag = sqrtf (x * x + y * y + z * z);
|
|
||||||
|
|
||||||
if (mag <= 1.0e-4)
|
|
||||||
{
|
|
||||||
/* no rotation, leave mat as-is */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
x /= mag;
|
|
||||||
y /= mag;
|
|
||||||
z /= mag;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Arbitrary axis rotation matrix.
|
|
||||||
*
|
|
||||||
* This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
|
|
||||||
* like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
|
|
||||||
* (which is about the X-axis), and the two composite transforms
|
|
||||||
* Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
|
|
||||||
* from the arbitrary axis to the X-axis then back. They are
|
|
||||||
* all elementary rotations.
|
|
||||||
*
|
|
||||||
* Rz' is a rotation about the Z-axis, to bring the axis vector
|
|
||||||
* into the x-z plane. Then Ry' is applied, rotating about the
|
|
||||||
* Y-axis to bring the axis vector parallel with the X-axis. The
|
|
||||||
* rotation about the X-axis is then performed. Ry and Rz are
|
|
||||||
* simply the respective inverse transforms to bring the arbitrary
|
|
||||||
* axis back to it's original orientation. The first transforms
|
|
||||||
* Rz' and Ry' are considered inverses, since the data from the
|
|
||||||
* arbitrary axis gives you info on how to get to it, not how
|
|
||||||
* to get away from it, and an inverse must be applied.
|
|
||||||
*
|
|
||||||
* The basic calculation used is to recognize that the arbitrary
|
|
||||||
* axis vector (x, y, z), since it is of unit length, actually
|
|
||||||
* represents the sines and cosines of the angles to rotate the
|
|
||||||
* X-axis to the same orientation, with theta being the angle about
|
|
||||||
* Z and phi the angle about Y (in the order described above)
|
|
||||||
* as follows:
|
|
||||||
*
|
|
||||||
* cos ( theta ) = x / sqrt ( 1 - z^2 )
|
|
||||||
* sin ( theta ) = y / sqrt ( 1 - z^2 )
|
|
||||||
*
|
|
||||||
* cos ( phi ) = sqrt ( 1 - z^2 )
|
|
||||||
* sin ( phi ) = z
|
|
||||||
*
|
|
||||||
* Note that cos ( phi ) can further be inserted to the above
|
|
||||||
* formulas:
|
|
||||||
*
|
|
||||||
* cos ( theta ) = x / cos ( phi )
|
|
||||||
* sin ( theta ) = y / sin ( phi )
|
|
||||||
*
|
|
||||||
* ...etc. Because of those relations and the standard trigonometric
|
|
||||||
* relations, it is pssible to reduce the transforms down to what
|
|
||||||
* is used below. It may be that any primary axis chosen will give the
|
|
||||||
* same results (modulo a sign convention) using thie method.
|
|
||||||
*
|
|
||||||
* Particularly nice is to notice that all divisions that might
|
|
||||||
* have caused trouble when parallel to certain planes or
|
|
||||||
* axis go away with care paid to reducing the expressions.
|
|
||||||
* After checking, it does perform correctly under all cases, since
|
|
||||||
* in all the cases of division where the denominator would have
|
|
||||||
* been zero, the numerator would have been zero as well, giving
|
|
||||||
* the expected result.
|
|
||||||
*/
|
|
||||||
|
|
||||||
xx = x * x;
|
|
||||||
yy = y * y;
|
|
||||||
zz = z * z;
|
|
||||||
xy = x * y;
|
|
||||||
yz = y * z;
|
|
||||||
zx = z * x;
|
|
||||||
xs = x * s;
|
|
||||||
ys = y * s;
|
|
||||||
zs = z * s;
|
|
||||||
one_c = 1.0f - c;
|
|
||||||
|
|
||||||
/* We already hold the identity-matrix so we can skip some statements */
|
|
||||||
M (0,0) = (one_c * xx) + c;
|
|
||||||
M (0,1) = (one_c * xy) - zs;
|
|
||||||
M (0,2) = (one_c * zx) + ys;
|
|
||||||
/* M (0,3) = 0.0f; */
|
|
||||||
|
|
||||||
M (1,0) = (one_c * xy) + zs;
|
|
||||||
M (1,1) = (one_c * yy) + c;
|
|
||||||
M (1,2) = (one_c * yz) - xs;
|
|
||||||
/* M (1,3) = 0.0f; */
|
|
||||||
|
|
||||||
M (2,0) = (one_c * zx) - ys;
|
|
||||||
M (2,1) = (one_c * yz) + xs;
|
|
||||||
M (2,2) = (one_c * zz) + c;
|
|
||||||
/* M (2,3) = 0.0f; */
|
|
||||||
|
|
||||||
/*
|
|
||||||
M (3,0) = 0.0f;
|
|
||||||
M (3,1) = 0.0f;
|
|
||||||
M (3,2) = 0.0f;
|
|
||||||
M (3,3) = 1.0f;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#undef M
|
|
||||||
|
|
||||||
matrix_multiply_array_with_flags (matrix, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cogl_matrix_rotate (CoglMatrix *matrix,
|
cogl_matrix_rotate (CoglMatrix *matrix,
|
||||||
float angle,
|
float angle,
|
||||||
@ -368,7 +159,17 @@ cogl_matrix_rotate (CoglMatrix *matrix,
|
|||||||
float y,
|
float y,
|
||||||
float z)
|
float z)
|
||||||
{
|
{
|
||||||
_cogl_matrix_rotate (matrix, angle, x, y, z);
|
graphene_matrix_t rotation, m;
|
||||||
|
graphene_vec3_t r;
|
||||||
|
|
||||||
|
cogl_matrix_to_graphene_matrix (matrix, &m);
|
||||||
|
graphene_matrix_transpose (&m, &m);
|
||||||
|
|
||||||
|
graphene_matrix_init_rotate (&rotation, angle, graphene_vec3_init (&r, x, y, z));
|
||||||
|
graphene_matrix_multiply (&rotation, &m, &m);
|
||||||
|
|
||||||
|
graphene_matrix_to_cogl_matrix (&m, matrix);
|
||||||
|
|
||||||
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
_COGL_MATRIX_DEBUG_PRINT (matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user