不过是比Vector 3D多加了一个GLfloat,经常把它当成w字段。所以对我们来说一个四元数就象这样:typedef struct { GLfloat x; GLfloat y; GLfloat z; GLfloat w;} Quaternion3D;Normalizing a Quaternion 四元数归一化这个十分简单。四元数代表空间里的一个方向,就像Vector3Ds,实际距离的值并不在意,并且在进行一些计算之前/之后使他们正常下降到1.0。完成这些我们可以这样做:static inline void Quaternion3DNormalize(Quaternion3D
*quaternion){ GLfloat magnitude; magnitude =
sqrtf((quaternion->x * quaternion->x) + (quaternion->y * quaternion->y) + (quaternion->z * quaternion->z) + (quaternion->w * quaternion->w)); quaternion->x /= magnitude; quaternion->y /= magnitude; quaternion->z /= magnitude;
quaternion->w /= magnitude;}Creating a Quaternion from a Rotation matrix 从一个旋转矩阵中创建一个四元数 如果我们没法在四元数同其他的对象转换过程中保存旋转角度信息的话,四元数对我们来说还是没用的。首先我们从一个旋转矩阵中创建一个四元数。代码如下: static inline Quaternion3D Quaternion3DMakeWithMatrix3D(Matrix3D matrix){ Quaternion3D quat; GLfloat trace, s; trace
= matrix[0] + matrix[5] + matrix[10]; if (trace > 0.0f) { s = sqrtf(trace + 1.0f); quat.w = s * 0.5f; s = 0.5f / s; quat.x = (matrix[9] - matrix[6]) * s; quat.y = (matrix[2] - matrix[8]) * s; quat.z = (matrix[4] - matrix[1]) * s; } else { NSInteger biggest; enum {A,E,I}; if (matrix[0] > matrix[5]) if (matrix[10] > matrix[0]) biggest = I; else biggest = A; else if (matrix[10] > matrix[0]) biggest = I; else biggest = E; switch (biggest) { case A: s = sqrtf(matrix[0] - (matrix[5] + matrix[10]) + 1.0f);
if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.x = s * 0.5f; s = 0.5f / s; quat.w = (matrix[9] - matrix[6]) * s; quat.y = (matrix[1] + matrix[4]) * s; quat.z = (matrix[2] +
matrix[8]) * s; break; } s = sqrtf(matrix[10] - (matrix[0] + matrix[5]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.z = s * 0.5f; s = 0.5f / s; quat.w = (matrix[4] -
matrix[1]) * s; quat.x = (matrix[8] + matrix[2]) * s; quat.y = (matrix[9] +
matrix[6]) * s; break; } s = sqrtf(matrix[5] - (matrix[10] + matrix[0]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.y = s * 0.5f; s = 0.5f / s; quat.w = (matrix[2] - matrix[8]) * s; quat.z = (matrix[6] + matrix[9]) * s; quat.x = (matrix[4] +
matrix[1]) * s; break; break; case E: = sqrtf(matrix[5] - (matrix[10] + matrix[0]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.y = s * 0.5f; s = 0.5f / s; quat.w = (matrix[2] - matrix[8]) * s; quat.z = (matrix[6] + matrix[9]) * s; quat.x = (matrix[4] +
matrix[1]) * s; break; s = sqrtf(matrix[10] - (matrix[0] + matrix[5]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.z = s * 0.5f; s = 0.5f / s; quat.w = (matrix[4] -
} s } matrix[1]) * s; quat.x = (matrix[8] + matrix[2]) * s; quat.y = (matrix[9] +
matrix[6]) * s; break; } s = sqrtf(matrix[0] - (matrix[5] + matrix[10]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.x = s * 0.5f; s = 0.5f / s; quat.w = (matrix[9] - matrix[6]) * s; quat.y = (matrix[1] + matrix[4]) * s; quat.z = (matrix[2] +
matrix[8]) * s; break; break; case I: = sqrtf(matrix[10] - (matrix[0] + matrix[5]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.z = s * 0.5f; s = 0.5f / s; quat.w = (matrix[4] - matrix[1]) * s; quat.x = (matrix[8] + matrix[2]) * s; quat.y = (matrix[9] +
matrix[6]) * s; break; s = sqrtf(matrix[0] - (matrix[5] + matrix[10]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.x = s * 0.5f; s = 0.5f / s; quat.w = (matrix[9] -
} s } matrix[6]) * s; quat.y = (matrix[1] + matrix[4]) * s; quat.z = (matrix[2] +
matrix[8]) * s; break; } s = sqrtf(matrix[5] - (matrix[10] + matrix[0]) + 1.0f); if (s > QUATERNION_TRACE_ZERO_TOLERANCE) { quat.y = s * 0.5f; s = 0.5f / s; quat.w = (matrix[2] - matrix[8]) * s; quat.z = (matrix[6] + matrix[9]) * s; quat.x = (matrix[4] +
matrix[1]) * s; break; } break; default: break; } } return quat;}好的,如果你想真正知道这里是怎么工作的。你需要了解矩阵运算、欧拉旋转理论、特征值和纹理。更不用说理解旋转在矩阵里的表示方法。当你完成你的数学博士学位,你可以回过头用它来解释剩余的usl。你会发现这个函数中使用的算法都是Matrix的FAQ上用伪代码列出来的。Creating a Rotation Matrix from a Quaternion 从一个四元数中创建旋转矩阵这另外的一个方法相对简单些。并且这个基本算法来自于Matrix FAQ,虽然我需要把它转换成行优先的顺序。static inline void Matrix3DSetUsingQuaternion3D(Matrix3D matrix,
Quaternion3D quat){ matrix[0] = (1.0f - (2.0f * ((quat.y *