At least I think it is. I have the following functions:
- kmQuaternionRotationAxis - Constructs a Quaternion from an axis and angle
- kmMat4RotationQuaternion - Constructs a 4x4 matrix from a quaternion
- kmMat4RotationAxisAngle - Constructs a 4x4 matrix from an axis and angle
My problem is, when I run the following code:
kmQuaternion q; kmMat4 initialized; kmMat4 quaternion_rotated; kmQuaternionRotationAxis(&q, &KM_VEC3_POS_Z, kmDegreesToRadians(90)); kmMat4RotationAxisAngle(&initialized, &KM_VEC3_POS_Z, kmDegreesToRadians(90)); kmMat4RotationQuaternion(&quaternion_rotated, &q); I would expect *quaternion_rotated* to match initialized, but they don't.
Initialized:
| 0 -1 0 0 | | 1 0 0 0 | | 0 0 1 0 | | 0 0 0 1 | quaternion_rotated:
| 0 1 0 0 | | -1 0 0 0 | | 0 0 1 0 | | 0 0 0 1 | The contents of initialized looks like I would expect, but I can't figure out how quaternion_rotated is wrong. I've included all the code below, where is my conversion code wrong?
kmQuaternion* kmQuaternionRotationAxis(kmQuaternion* pOut, const kmVec3* pV, kmScalar angle) { kmScalar rad = angle * 0.5f; kmScalar scale = sinf(rad); pOut->w = cosf(rad); pOut->x = pV->x * scale; pOut->y = pV->y * scale; pOut->z = pV->z * scale; kmQuaternionNormalize(pOut, pOut); return pOut; } kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const kmVec3* axis, kmScalar radians) { kmScalar rcos = cosf(radians); kmScalar rsin = sinf(radians); kmVec3 normalizedAxis; kmVec3Normalize(&normalizedAxis, axis); pOut->mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos); pOut->mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos); pOut->mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos); pOut->mat[3] = 0.0f; pOut->mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos); pOut->mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos); pOut->mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos); pOut->mat[7] = 0.0f; pOut->mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos); pOut->mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos); pOut->mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos); pOut->mat[11] = 0.0f; pOut->mat[12] = 0.0f; pOut->mat[13] = 0.0f; pOut->mat[14] = 0.0f; pOut->mat[15] = 1.0f; return pOut; } kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const kmQuaternion* pQ) { double xx = pQ->x * pQ->x; double xy = pQ->x * pQ->y; double xz = pQ->x * pQ->z; double xw = pQ->x * pQ->w; double yy = pQ->y * pQ->y; double yz = pQ->y * pQ->z; double yw = pQ->y * pQ->w; double zz = pQ->z * pQ->z; double zw = pQ->z * pQ->w; pOut->mat[0] = 1 - 2 * (yy + zz); pOut->mat[1] = 2 * (xy - zw); pOut->mat[2] = 2 * (xz + yw); pOut->mat[3] = 0; pOut->mat[4] = 2 * (xy + zw); pOut->mat[5] = 1 - 2 * (xx + zz); pOut->mat[6] = 2 * (yz - xw); pOut->mat[7] = 0.0; pOut->mat[8] = 2 * (xz - yw); pOut->mat[9] = 2 * (yz + xw); pOut->mat[10] = 1 - 2 * (xx + yy); pOut->mat[11] = 0.0; pOut->mat[12] = 0.0; pOut->mat[13] = 0.0; pOut->mat[14] = 0.0; pOut->mat[15] = 1.0; return pOut; }