Quaternion4.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #pragma once
  2. struct Quaternion4f
  3. {
  4. float x, y, z, w;
  5. };
  6. static Quaternion4f gQuatRot[4] =
  7. { // { x*sin(theta/2), y*sin(theta/2), z*sin(theta/2), cos(theta/2) }
  8. // => { 0, 0, sin(theta/2), cos(theta/2) } (since <vec> = { 0, 0, +/-1})
  9. { 0.f, 0.f, 0.f /*sin(0)*/, 1.f /*cos(0)*/}, // ROTATION_0, theta = 0 rad
  10. { 0.f, 0.f, (float)sqrt(2) * 0.5f /*sin(pi/4)*/, -(float)sqrt(2) * 0.5f /*cos(pi/4)*/}, // ROTATION_90, theta = pi/4 rad
  11. { 0.f, 0.f, 1.f /*sin(pi/2)*/, 0.f /*cos(pi/2)*/}, // ROTATION_180, theta = pi rad
  12. { 0.f, 0.f, -(float)sqrt(2) * 0.5f /*sin(3pi/4)*/, -(float)sqrt(2) * 0.5f /*cos(3pi/4)*/} // ROTATION_270, theta = 3pi/2 rad
  13. };
  14. inline void QuatMultiply(Quaternion4f& result, const Quaternion4f& lhs, const Quaternion4f& rhs)
  15. {
  16. result.x = lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y;
  17. result.y = lhs.w * rhs.y + lhs.y * rhs.w + lhs.z * rhs.x - lhs.x * rhs.z;
  18. result.z = lhs.w * rhs.z + lhs.z * rhs.w + lhs.x * rhs.y - lhs.y * rhs.x;
  19. result.w = lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z;
  20. }
  21. inline Quaternion4f QuatMultiply(const Quaternion4f& lhs, const Quaternion4f& rhs)
  22. {
  23. Quaternion4f output;
  24. QuatMultiply(output, lhs, rhs);
  25. return output;
  26. }
  27. inline Quaternion4f QuatMake(float x, float y, float z, float w)
  28. {
  29. Quaternion4f q = {x, y, z, w};
  30. return q;
  31. }
  32. inline Quaternion4f QuatIdentity()
  33. {
  34. return gQuatRot[0];
  35. }
  36. inline Quaternion4f QuatScale(const Quaternion4f& q, float s)
  37. {
  38. return QuatMake(s * q.x, s * q.y, s * q.z, s * q.w);
  39. }
  40. inline float QuatNormSquared(const Quaternion4f& q)
  41. {
  42. return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
  43. }
  44. inline Quaternion4f QuatConjugate(const Quaternion4f& q)
  45. {
  46. return QuatMake(-q.x, -q.y, -q.z, q.w);
  47. }
  48. inline Quaternion4f QuatInverse(const Quaternion4f& q)
  49. {
  50. return QuatScale(QuatConjugate(q), 1.0f / QuatNormSquared(q));
  51. }
  52. inline Vector3f QuatToEuler(const Quaternion4f& q)
  53. {
  54. return VecMake(
  55. atan2f(2.0f * (q.w * q.y + q.x * q.z),
  56. 1.0f - 2.0f * (q.y * q.y + q.x * q.x)),
  57. asinf(2.0f * (q.w * q.x - q.z * q.y)),
  58. atan2f(2.0f * (q.w * q.z + q.y * q.x),
  59. 1.0f - 2.0f * (q.x * q.x + q.z * q.z)));
  60. }
  61. inline float QuatNorm(const Quaternion4f& q)
  62. {
  63. return sqrtf(QuatNormSquared(q));
  64. }
  65. inline Quaternion4f QuatNormalize(const Quaternion4f& q)
  66. {
  67. return QuatScale(q, 1.0f / QuatNorm(q));
  68. }
  69. inline Quaternion4f QuatDifference(const Quaternion4f& a, const Quaternion4f& b)
  70. {
  71. return QuatMultiply(QuatInverse(b), a);
  72. }
  73. inline Quaternion4f QuatRotationFromTo(const Vector3f& src, const Vector3f& dest)
  74. {
  75. // Based on Stan Melax's article in Game Programming Gems
  76. float mag0 = VecMagnitude(src);
  77. if (mag0 < FLT_EPSILON)
  78. return QuatIdentity();
  79. float mag1 = VecMagnitude(dest);
  80. if (mag1 < FLT_EPSILON)
  81. return QuatIdentity();
  82. Vector3f v0 = VecScale(1.0f / mag0, src);
  83. Vector3f v1 = VecScale(1.0f / mag1, dest);
  84. float d = VecDotProduct(v0, v1);
  85. // If dot == 1, vectors are the same
  86. if (d >= (1.0f - 1e-6f))
  87. return QuatIdentity();
  88. if (d < (1e-6f - 1.0f))
  89. return gQuatRot[2];
  90. float s = sqrtf((1.0f + d) * 2.0f);
  91. float i = 1.0f / s;
  92. Vector3f c = VecCrossProduct(v0, v1);
  93. return QuatNormalize(QuatMake(
  94. c.x * i, c.y * i, c.z * i, s * 0.5f));
  95. }