There is a setRotateM
function in android.opengl.matrix
package and it
Converts Euler angles to a rotation matrix.
The principal part of the implementation is :
rm[rmOffset + 0] = cy * cz;
rm[rmOffset + 1] = -cy * sz;
rm[rmOffset + 2] = sy;
rm[rmOffset + 3] = 0.0f;
rm[rmOffset + 4] = cxsy * cz + cx * sz;
rm[rmOffset + 5] = -cxsy * sz + cx * cz;
rm[rmOffset + 6] = -sx * cy;
rm[rmOffset + 7] = 0.0f;
rm[rmOffset + 8] = -sxsy * cz + sx * sz;
rm[rmOffset + 9] = sxsy * sz + sx * cz;
rm[rmOffset + 10] = cx * cy;
rm[rmOffset + 11] = 0.0f;
rm[rmOffset + 12] = 0.0f;
rm[rmOffset + 13] = 0.0f;
rm[rmOffset + 14] = 0.0f;
rm[rmOffset + 15] = 1.0f;
where cx = cos(angleOnX), sz = sin(angleOnZ) etc.
This bunch of code will give a 4x4 matrix:
[ cy*cz, cx*sz + cx*cz*sy, sx*sz - cz*sx*sy, 0]
[ -cy*sz, cx*cz - cx*sy*sz, cz*sx + sx*sy*sz, 0]
[ sy, -cy*sx, cx*cy, 0]
[ 0, 0, 0, 1]
While, given rotation matrices around x, y, z axis respectively
Rx = [ 1, 0, 0, 0]
[ 0, cx, -sx, 0]
[ 0, sx, cx, 0]
[ 0, 0, 0, 1]
Ry = [ cy, 0, sy, 0]
[ 0, 1, 0, 0]
[ -sy, 0, cy, 0]
[ 0, 0, 0, 1]
Rz = [ cz, -sz, 0, 0]
[ sz, cz, 0, 0]
[ 0, 0, 1, 0]
[ 0, 0, 0, 1]
The most similar composition I could find is
(Rx * Ry * Rz)^T = Rz^T * Ry^T * Rx^T =
[ cy*cz, cx*sz + cz*sx*sy, sx*sz - cx*cz*sy, 0]
[ -cy*sz, cx*cz - sx*sy*sz, cz*sx + cx*sy*sz, 0]
[ sy, -cy*sx, cx*cy, 0]
[ 0, 0, 0, 1]
Between android's implementation R
and raw multiplication Rxyz^T
,
there are slight differences in R(1,2) R(1,3) R(2,2) R(2,3) components, where cx
and sx
are switched.
Considering android.opengl.matrix
is a widely-applied, time-tested package, I must have done something wrong.
I have two questions:
1. How this difference happens?
2. Why it is (Rx * Ry * Rz)^T
? I suppose it was Rz * Ry * Rx