Quaternion.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #include "Base.h"
  2. #include "Quaternion.h"
  3. namespace gameplay
  4. {
  5. Quaternion::Quaternion()
  6. : x(0.0f), y(0.0f), z(0.0f), w(1.0f)
  7. {
  8. }
  9. Quaternion::Quaternion(float x, float y, float z, float w)
  10. {
  11. set(x, y, z, w);
  12. }
  13. Quaternion::Quaternion(float* array)
  14. {
  15. set(array);
  16. }
  17. Quaternion::Quaternion(const Quaternion& copy)
  18. {
  19. set(copy);
  20. }
  21. Quaternion::~Quaternion()
  22. {
  23. }
  24. const Quaternion& Quaternion::identity()
  25. {
  26. static Quaternion* value = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
  27. return *value;
  28. }
  29. const Quaternion& Quaternion::zero()
  30. {
  31. static Quaternion* value = new Quaternion(0.0f, 0.0f, 0.0f, 0.0f);
  32. return *value;
  33. }
  34. bool Quaternion::isIdentity() const
  35. {
  36. return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f;
  37. }
  38. bool Quaternion::isZero() const
  39. {
  40. return x == 0.0f && y == 0.0f && z == 0.0f && z == 0.0f;
  41. }
  42. void Quaternion::createFromRotationMatrix(const Matrix& m, Quaternion* dst)
  43. {
  44. assert(dst);
  45. m.decompose(NULL, dst, NULL);
  46. }
  47. void Quaternion::createFromAxisAngle(const Vector3& axis, float angle, Quaternion* dst)
  48. {
  49. assert(dst);
  50. float halfAngle = angle * 0.5f;
  51. float sinHalfAngle = sinf(halfAngle);
  52. Vector3 normal(axis);
  53. normal.normalize();
  54. dst->x = normal.x * sinHalfAngle;
  55. dst->y = normal.y * sinHalfAngle;
  56. dst->z = normal.z * sinHalfAngle;
  57. dst->w = cosf(halfAngle);
  58. }
  59. void Quaternion::conjugate()
  60. {
  61. conjugate(this);
  62. }
  63. void Quaternion::conjugate(Quaternion* dst) const
  64. {
  65. dst->x = -x;
  66. dst->y = -y;
  67. dst->z = -z;
  68. dst->w = w;
  69. }
  70. bool Quaternion::inverse()
  71. {
  72. return inverse(this);
  73. }
  74. bool Quaternion::inverse(Quaternion* dst) const
  75. {
  76. float n = x * x + y * y + z * z + w * w;
  77. if (n == 1.0f)
  78. {
  79. dst->x = -x;
  80. dst->y = -y;
  81. dst->z = -z;
  82. dst->w = w;
  83. return true;
  84. }
  85. // too close to zero
  86. if (n < 0.000001f)
  87. return false;
  88. n = 1.0f / n;
  89. dst->x = -x * n;
  90. dst->y = -y * n;
  91. dst->z = -z * n;
  92. dst->w = w * n;
  93. return true;
  94. }
  95. void Quaternion::multiply(const Quaternion& q)
  96. {
  97. multiply(*this, q, this);
  98. }
  99. void Quaternion::multiply(const Quaternion& q1, const Quaternion& q2, Quaternion* dst)
  100. {
  101. float x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y;
  102. float y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x;
  103. float z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w;
  104. float w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z;
  105. dst->x = x;
  106. dst->y = y;
  107. dst->z = z;
  108. dst->w = w;
  109. }
  110. void Quaternion::normalize()
  111. {
  112. normalize(this);
  113. }
  114. void Quaternion::normalize(Quaternion* dst) const
  115. {
  116. assert(dst);
  117. if (this != dst)
  118. {
  119. dst->x = x;
  120. dst->y = y;
  121. dst->z = z;
  122. dst->w = w;
  123. }
  124. float n = x * x + y * y + z * z + w * w;
  125. // already normalized
  126. if (n == 1.0f)
  127. return;
  128. n = sqrt(n);
  129. // too close to zero
  130. if (n < 0.000001f)
  131. return;
  132. n = 1.0f / n;
  133. dst->x *= n;
  134. dst->y *= n;
  135. dst->z *= n;
  136. dst->w *= n;
  137. }
  138. void Quaternion::set(float x, float y, float z, float w)
  139. {
  140. this->x = x;
  141. this->y = y;
  142. this->z = z;
  143. this->w = w;
  144. }
  145. void Quaternion::set(float* array)
  146. {
  147. assert(array);
  148. x = array[0];
  149. y = array[1];
  150. z = array[2];
  151. w = array[3];
  152. }
  153. void Quaternion::set(const Quaternion& q)
  154. {
  155. this->x = q.x;
  156. this->y = q.y;
  157. this->z = q.z;
  158. this->w = q.w;
  159. }
  160. void Quaternion::setIdentity()
  161. {
  162. x = 0.0f;
  163. y = 0.0f;
  164. z = 0.0f;
  165. w = 1.0f;
  166. }
  167. float Quaternion::toAxisAngle(Vector3* axis) const
  168. {
  169. assert(axis);
  170. Quaternion q(x, y, z, w);
  171. q.normalize();
  172. axis->x = q.x;
  173. axis->y = q.y;
  174. axis->z = q.z;
  175. axis->normalize();
  176. return (2.0f * acos(q.w));
  177. }
  178. void Quaternion::lerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
  179. {
  180. assert(dst);
  181. assert(!(t < 0.0f || t > 1.0f));
  182. float t1 = 1.0f - t;
  183. dst->x = t1 * q1.x + t * q2.x;
  184. dst->y = t1 * q1.y + t * q2.y;
  185. dst->z = t1 * q1.z + t * q2.z;
  186. dst->w = t1 * q1.w + t * q2.w;
  187. }
  188. void Quaternion::slerp(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
  189. {
  190. // Fast slerp implementation by kwhatmough:
  191. // It contains no division operations, no trig, no inverse trig
  192. // and no sqrt. Not only does this code tolerate small constraint
  193. // errors in the input quaternions, it actually corrects for them.
  194. assert(dst);
  195. assert(!(t < 0.0f || t > 1.0f));
  196. float halfY, alpha, beta;
  197. float u, f1, f2a, f2b;
  198. float ratio1, ratio2;
  199. float halfSecHalfTheta, versHalfTheta;
  200. float sqNotU, sqU;
  201. float cosTheta = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;
  202. // As usual in all slerp implementations, we fold theta.
  203. alpha = cosTheta >= 0 ? 1.0f : -1.0f;
  204. halfY = 1.0f + alpha * cosTheta;
  205. // Here we bisect the interval, so we need to fold t as well.
  206. f2b = t - 0.5f;
  207. u = f2b >= 0 ? f2b : -f2b;
  208. f2a = u - f2b;
  209. f2b += u;
  210. u += u;
  211. f1 = 1.0f - u;
  212. // One iteration of Newton to get 1-cos(theta / 2) to good accuracy.
  213. halfSecHalfTheta = 1.09f - (0.476537f - 0.0903321f * halfY) * halfY;
  214. halfSecHalfTheta *= 1.5f - halfY * halfSecHalfTheta * halfSecHalfTheta;
  215. versHalfTheta = 1.0f - halfY * halfSecHalfTheta;
  216. // Evaluate series expansions of the coefficients.
  217. sqNotU = f1 * f1;
  218. ratio2 = 0.0000440917108f * versHalfTheta;
  219. ratio1 = -0.00158730159f + (sqNotU - 16.0f) * ratio2;
  220. ratio1 = 0.0333333333f + ratio1 * (sqNotU - 9.0f) * versHalfTheta;
  221. ratio1 = -0.333333333f + ratio1 * (sqNotU - 4.0f) * versHalfTheta;
  222. ratio1 = 1.0f + ratio1 * (sqNotU - 1.0f) * versHalfTheta;
  223. sqU = u * u;
  224. ratio2 = -0.00158730159f + (sqU - 16.0f) * ratio2;
  225. ratio2 = 0.0333333333f + ratio2 * (sqU - 9.0f) * versHalfTheta;
  226. ratio2 = -0.333333333f + ratio2 * (sqU - 4.0f) * versHalfTheta;
  227. ratio2 = 1.0f + ratio2 * (sqU - 1.0f) * versHalfTheta;
  228. // Perform the bisection and resolve the folding done earlier.
  229. f1 *= ratio1 * halfSecHalfTheta;
  230. f2a *= ratio2;
  231. f2b *= ratio2;
  232. alpha *= f1 + f2a;
  233. beta = f1 + f2b;
  234. // Apply final coefficients to a and b as usual.
  235. float w = alpha * q1.w + beta * q2.w;
  236. float x = alpha * q1.x + beta * q2.x;
  237. float y = alpha * q1.y + beta * q2.y;
  238. float z = alpha * q1.z + beta * q2.z;
  239. // This final adjustment to the quaternion's length corrects for
  240. // any small constraint error in the inputs q1 and q2. But as you
  241. // can see, it comes at the cost of 9 additional multiplication
  242. // operations. If this error-correcting feature is not required,
  243. // the following code may be removed.
  244. f1 = 1.5f - 0.5f * (w * w + x * x + y * y + z * z);
  245. dst->w = w * f1;
  246. dst->x = x * f1;
  247. dst->y = y * f1;
  248. dst->z = z * f1;
  249. }
  250. void Quaternion::squad(const Quaternion& q1, const Quaternion& q2, const Quaternion& s1, const Quaternion& s2, float t, Quaternion* dst)
  251. {
  252. assert(dst);
  253. assert(!(t < 0.0f || t > 1.0f));
  254. Quaternion dstQ(0.0f, 0.0f, 0.0f, 1.0f);
  255. Quaternion dstS(0.0f, 0.0f, 0.0f, 1.0f);
  256. slerpForSquad(q1, q2, t, &dstQ);
  257. slerpForSquad(s1, s2, t, &dstS);
  258. slerpForSquad(dstQ, dstS, 2.0f * t * (1.0f - t), dst);
  259. }
  260. void Quaternion::slerpForSquad(const Quaternion& q1, const Quaternion& q2, float t, Quaternion* dst)
  261. {
  262. // cos(omega) = q1 * q2;
  263. // slerp(q1, q2, t) = (q1*sin((1-t)*omega) + q2*sin(t*omega))/sin(omega);
  264. // q1 = +- q2, slerp(q1,q2,t) = q1.
  265. // This is a straight-foward implementation of the formula of slerp. It does not do any sign switching.
  266. float c = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w;
  267. if (fabs(c) >= 1.0f)
  268. {
  269. dst->x = q1.x;
  270. dst->y = q1.y;
  271. dst->z = q1.z;
  272. dst->w = q1.w;
  273. return;
  274. }
  275. float omega = acos(c);
  276. float s = sqrt(1.0f - c * c);
  277. if (fabs(s) <= 0.00001f)
  278. {
  279. dst->x = q1.x;
  280. dst->y = q1.y;
  281. dst->z = q1.z;
  282. dst->w = q1.w;
  283. return;
  284. }
  285. float r1 = sin((1 - t) * omega) / s;
  286. float r2 = sin(t * omega) / s;
  287. dst->x = (q1.x * r1 + q2.x * r2);
  288. dst->y = (q1.y * r1 + q2.y * r2);
  289. dst->z = (q1.z * r1 + q2.z * r2);
  290. dst->w = (q1.w * r1 + q2.w * r2);
  291. }
  292. }