2
0

PolyQuaternion.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * PolyQuaternion.h
  3. * TAU
  4. *
  5. * Created by Ivan Safrin on 3/26/08.
  6. * Copyright 2008 __MyCompanyName__. All rights reserved.
  7. *
  8. */
  9. #pragma once
  10. #include "PolyGlobals.h"
  11. #include "PolyBasics.h"
  12. #include "PolyMatrix4.h"
  13. #include <math.h>
  14. // @package Math
  15. namespace Polycode {
  16. class _PolyExport Quaternion {
  17. public:
  18. Quaternion(float w, float x, float y, float z) {
  19. set(w,x,y,z);
  20. }
  21. Quaternion();
  22. ~Quaternion();
  23. inline void setFromMatrix(const Matrix4 &kRot) {
  24. float fTrace = kRot.m[0][0]+kRot.m[1][1]+kRot.m[2][2];
  25. float fRoot;
  26. if ( fTrace > 0.0 )
  27. {
  28. // |w| > 1/2, may as well choose w > 1/2
  29. fRoot = sqrtf(fTrace + 1.0); // 2w
  30. w = 0.5*fRoot;
  31. fRoot = 0.5/fRoot; // 1/(4w)
  32. x = (kRot.m[2][1]-kRot.m[1][2])*fRoot;
  33. y = (kRot.m[0][2]-kRot.m[2][0])*fRoot;
  34. z = (kRot.m[1][0]-kRot.m[0][1])*fRoot;
  35. }
  36. else
  37. {
  38. // |w| <= 1/2
  39. static size_t s_iNext[3] = { 1, 2, 0 };
  40. size_t i = 0;
  41. if ( kRot.m[1][1] > kRot.m[0][0] )
  42. i = 1;
  43. if ( kRot.m[2][2] > kRot.m[i][i] )
  44. i = 2;
  45. size_t j = s_iNext[i];
  46. size_t k = s_iNext[j];
  47. fRoot = sqrtf(kRot.m[i][i]-kRot.m[j][j]-kRot.m[k][k] + 1.0);
  48. float* apkQuat[3] = { &x, &y, &z };
  49. *apkQuat[i] = 0.5*fRoot;
  50. fRoot = 0.5/fRoot;
  51. w = (kRot.m[k][j]-kRot.m[j][k])*fRoot;
  52. *apkQuat[j] = (kRot.m[j][i]+kRot.m[i][j])*fRoot;
  53. *apkQuat[k] = (kRot.m[k][i]+kRot.m[i][k])*fRoot;
  54. }
  55. }
  56. static Quaternion Slerp(float fT, const Quaternion& rkP, const Quaternion& rkQ, bool shortestPath=false);
  57. float Dot(const Quaternion& rkQ) const;
  58. Quaternion Log () const;
  59. Quaternion Exp () const;
  60. float Norm () const;
  61. float normalise(void);
  62. Quaternion operator+ (const Quaternion& rkQ) const;
  63. Quaternion operator* (const Quaternion& rkQ) const;
  64. Quaternion operator* (float fScalar) const;
  65. inline void lookAt(const Vector3 &D, const Vector3 &upVector) {
  66. /*
  67. Vector3 D;
  68. Vector3 back = D * -1;
  69. back.Normalize();
  70. Vector3 right = back.crossProduct(upVector) ;
  71. right.Normalize();
  72. right = right * -1;
  73. Vector3 up = back.crossProduct(right);
  74. set( y.z - z.y , z.x - x.z, x.y - y.x, tr + 1.0f );
  75. */
  76. }
  77. void createFromMatrix(Matrix4 matrix) {
  78. float tr, s, q[4];
  79. int i, j, k;
  80. static const int nxt[3] = {1, 2, 0};
  81. tr = matrix.m[0][0] + matrix.m[1][1] + matrix.m[2][2];
  82. // check the diagonal
  83. if (tr > 0.0f)
  84. {
  85. s = sqrtf(tr + 1.0f);
  86. w = s / 2.0f;
  87. s = 0.5f / s;
  88. x = (matrix.m[1][2] - matrix.m[2][1]) * s;
  89. y = (matrix.m[2][0] - matrix.m[0][2]) * s;
  90. z = (matrix.m[0][1] - matrix.m[1][0]) * s;
  91. }
  92. else
  93. {
  94. // diagonal is negative
  95. i = 0;
  96. if (matrix.m[1][1] > matrix.m[0][0]) i = 1;
  97. if (matrix.m[2][2] > matrix.m[i][i]) i = 2;
  98. j = nxt[i];
  99. k = nxt[j];
  100. s = sqrtf((matrix.m[i][i] - (matrix.m[j][j] + matrix.m[k][k])) + 1.0f);
  101. q[i] = s * 0.5f;
  102. if (s != 0.0f) s = 0.5f / s;
  103. q[3] = (matrix.m[j][k] - matrix.m[k][j]) * s;
  104. q[j] = (matrix.m[i][j] + matrix.m[j][i]) * s;
  105. q[k] = (matrix.m[i][k] + matrix.m[k][i]) * s;
  106. x = q[0];
  107. y = q[1];
  108. z = q[2];
  109. w = q[3];
  110. }
  111. }
  112. inline bool operator== (const Quaternion& rhs) const
  113. {
  114. return (rhs.x == x) && (rhs.y == y) &&
  115. (rhs.z == z) && (rhs.w == w);
  116. }
  117. inline bool operator!= (const Quaternion& rhs) const
  118. {
  119. return (rhs.x != x) && (rhs.y != y) &&
  120. (rhs.z != z) && (rhs.w != w);
  121. }
  122. static Quaternion Squad(float fT, const Quaternion& rkP, const Quaternion& rkA, const Quaternion& rkB, const Quaternion& rkQ, bool shortestPath);
  123. Quaternion Inverse () const;
  124. Quaternion operator- () const
  125. {
  126. return Quaternion(-w,-x,-y,-z);
  127. }
  128. void set(float w, float x, float y, float z) {
  129. this->w = w;
  130. this->x = x;
  131. this->y = y;
  132. this->z = z;
  133. }
  134. Quaternion inverse() {
  135. float fNorm = w*w+x*x+y*y+z*z;
  136. float fInvNorm = 1.0/fNorm;
  137. return Quaternion(w*fInvNorm,-x*fInvNorm,-y*fInvNorm,-z*fInvNorm);
  138. }
  139. float InvSqrt(float x){
  140. float xhalf = 0.5f * x;
  141. int i = *(int*)&x; // store floating-point bits in integer
  142. i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
  143. x = *(float*)&i; // convert new bits into float
  144. x = x*(1.5f - xhalf*x*x); // One round of Newton's method
  145. return x;
  146. }
  147. inline void fromAxes(float az, float ay, float ax) {
  148. ax *= TORADIANS;
  149. ay *= TORADIANS;
  150. az *= TORADIANS;
  151. float c1 = cos(ay / 2.0f);
  152. float c2 = cos(ax / 2.0f);
  153. float c3 = cos(az / 2.0f);
  154. float s1 = sin(ay / 2.0f);
  155. float s2 = sin(ax / 2.0f);
  156. float s3 = sin(az / 2.0f);
  157. w = (c1*c2*c3) - (s1*s2*s3);
  158. x = (s1*s2*c3) + (c1*c2*s3);
  159. y = (s1*c2*c3) + (c1*s2*s3);
  160. z = (c1*s2*c3) - (s1*c2*s3);
  161. }
  162. void FromAngleAxis (const float& rfAngle,
  163. const Vector3& rkAxis)
  164. {
  165. float fHalfAngle ( 0.5*rfAngle );
  166. float fSin = sin(fHalfAngle);
  167. w = cos(fHalfAngle);
  168. x = fSin*rkAxis.x;
  169. y = fSin*rkAxis.y;
  170. z = fSin*rkAxis.z;
  171. }
  172. //-----------------------------------------------------------------------
  173. void ToAngleAxis (float& rfAngle, Vector3& rkAxis)
  174. {
  175. // The quaternion representing the rotation is
  176. // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
  177. float fSqrLength = x*x+y*y+z*z;
  178. if ( fSqrLength > 0.0 )
  179. {
  180. rfAngle = 2.0*acos(w);
  181. float fInvLength = InvSqrt(fSqrLength);
  182. rkAxis.x = x*fInvLength;
  183. rkAxis.y = y*fInvLength;
  184. rkAxis.z = z*fInvLength;
  185. }
  186. else
  187. {
  188. // angle is 0 (mod 2*pi), so any axis will do
  189. rfAngle = float(0.0);
  190. rkAxis.x = 1.0;
  191. rkAxis.y = 0.0;
  192. rkAxis.z = 0.0;
  193. }
  194. }
  195. void createFromAxisAngle(float x, float y, float z, float degrees);
  196. Matrix4 createMatrix();
  197. Quaternion operator *(Quaternion q);
  198. float x;
  199. float y;
  200. float z;
  201. float w;
  202. protected:
  203. };
  204. }