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;
}