Quat.inl.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #include <iostream>
  2. #include "MathDfltHeader.h"
  3. #define ME (*this)
  4. namespace M {
  5. // constructor []
  6. inline Quat::Quat()
  7. : x(0.0), y(0.0), z(0.0), w(1.0)
  8. {}
  9. // constructor [float]
  10. inline Quat::Quat(float f)
  11. : x(f), y(f), z(f), w(f)
  12. {}
  13. // constructor [float, float, float, float]
  14. inline Quat::Quat(float x_, float y_, float z_, float w_)
  15. : x(x_), y(y_), z(z_), w(w_)
  16. {}
  17. // constructor [vec2, float, float]
  18. inline Quat::Quat(const Vec2& v2, float z_, float w_)
  19. : x(v2.x), y(v2.y), z(z_), w(w_)
  20. {}
  21. // constructor [vec3, float]
  22. inline Quat::Quat(const Vec3& v3, float w_)
  23. : x(v3.x), y(v3.y), z(v3.z), w(w_)
  24. {}
  25. // constructor [vec4]
  26. inline Quat::Quat(const Vec4& v4)
  27. : x(v4.x), y(v4.y), z(v4.z), w(v4.w)
  28. {}
  29. // constructor [quat]
  30. inline Quat::Quat(const Quat& b)
  31. : x(b.x), y(b.y), z(b.z), w(b.w)
  32. {}
  33. // constructor [mat3]
  34. inline Quat::Quat(const Mat3& m3)
  35. {
  36. float trace = m3(0, 0) + m3(1, 1) + m3(2, 2) + 1.0;
  37. if(trace > EPSILON)
  38. {
  39. float s = 0.5 * invSqrt(trace);
  40. w = 0.25 / s;
  41. x = (m3(2, 1) - m3(1, 2)) * s;
  42. y = (m3(0, 2) - m3(2, 0)) * s;
  43. z = (m3(1, 0) - m3(0, 1)) * s;
  44. }
  45. else
  46. {
  47. if(m3(0, 0) > m3(1, 1) && m3(0, 0) > m3(2, 2))
  48. {
  49. float s = 0.5 * invSqrt(1.0 + m3(0, 0) - m3(1, 1) - m3(2, 2));
  50. w = (m3(1, 2) - m3(2, 1)) * s;
  51. x = 0.25 / s;
  52. y = (m3(0, 1) + m3(1, 0)) * s;
  53. z = (m3(0, 2) + m3(2, 0)) * s;
  54. }
  55. else if(m3(1, 1) > m3(2, 2))
  56. {
  57. float s = 0.5 * invSqrt(1.0 + m3(1, 1) - m3(0, 0) - m3(2, 2));
  58. w = (m3(0, 2) - m3(2, 0)) * s;
  59. x = (m3(0, 1) + m3(1, 0)) * s;
  60. y = 0.25 / s;
  61. z = (m3(1, 2) + m3(2, 1)) * s;
  62. }
  63. else
  64. {
  65. float s = 0.5 * invSqrt(1.0 + m3(2, 2) - m3(0, 0) - m3(1, 1));
  66. w = (m3(0, 1) - m3(1, 0)) * s;
  67. x = (m3(0, 2) + m3(2, 0)) * s;
  68. y = (m3(1, 2) + m3(2, 1)) * s;
  69. z = 0.25 / s;
  70. }
  71. }
  72. }
  73. // constructor [euler]
  74. inline Quat::Quat(const Euler& eu)
  75. {
  76. float cx, sx;
  77. sinCos(eu.heading()*0.5, sx, cx);
  78. float cy, sy;
  79. sinCos(eu.attitude()*0.5, sy, cy);
  80. float cz, sz;
  81. sinCos(eu.bank()*0.5, sz, cz);
  82. float cxcy = cx*cy;
  83. float sxsy = sx*sy;
  84. x = cxcy*sz + sxsy*cz;
  85. y = sx*cy*cz + cx*sy*sz;
  86. z = cx*sy*cz - sx*cy*sz;
  87. w = cxcy*cz - sxsy*sz;
  88. }
  89. // constructor [euler]
  90. inline Quat::Quat(const Axisang& axisang)
  91. {
  92. float lengthsq = axisang.axis.getLengthSquared();
  93. if(isZero(lengthsq))
  94. {
  95. ME = getIdentity();
  96. return;
  97. }
  98. float rad = axisang.ang * 0.5;
  99. float sintheta, costheta;
  100. sinCos(rad, sintheta, costheta);
  101. float scalefactor = sintheta * invSqrt(lengthsq);
  102. x = scalefactor * axisang.axis.x;
  103. y = scalefactor * axisang.axis.y;
  104. z = scalefactor * axisang.axis.z;
  105. w = costheta;
  106. }
  107. // *
  108. inline Quat Quat::operator *(const Quat& b) const
  109. {
  110. return Quat(
  111. x * b.w + y * b.z - z * b.y + w * b.x,
  112. -x * b.z + y * b.w + z * b.x + w * b.y,
  113. x * b.y - y * b.x + z * b.w + w * b.z,
  114. -x * b.x - y * b.y - z * b.z + w * b.w
  115. );
  116. }
  117. // *=
  118. inline Quat& Quat::operator *=(const Quat& b)
  119. {
  120. ME = ME * b;
  121. return ME;
  122. }
  123. // ==
  124. inline bool Quat::operator ==(const Quat& b) const
  125. {
  126. return (isZero(x-b.x) && isZero(y-b.y) && isZero(z-b.z) && isZero(w-b.w)) ? true : false;
  127. }
  128. // !=
  129. inline bool Quat::operator !=(const Quat& b) const
  130. {
  131. return (isZero(x-b.x) && isZero(y-b.y) && isZero(z-b.z) && isZero(w-b.w)) ? false : true;
  132. }
  133. // conjugate
  134. inline void Quat::conjugate()
  135. {
  136. x = -x;
  137. y = -y;
  138. z = -z;
  139. }
  140. // getConjugated
  141. inline Quat Quat::getConjugated() const
  142. {
  143. return Quat(-x, -y, -z, w);
  144. }
  145. // Normalized
  146. inline Quat Quat::getNormalized() const
  147. {
  148. return Quat(Vec4(ME).getNormalized());
  149. }
  150. // normalize
  151. inline void Quat::normalize()
  152. {
  153. ME = getNormalized();
  154. }
  155. // getLength
  156. inline float Quat::getLength() const
  157. {
  158. return M::sqrt(w*w + x*x + y*y + z*z);
  159. }
  160. // getInverted
  161. inline Quat Quat::getInverted() const
  162. {
  163. float norm = w*w + x*x + y*y + z*z;
  164. DEBUG_ERR(isZero(norm)); // Norm is zero
  165. float normi = 1.0 / norm;
  166. return Quat(-normi*x, -normi*y, -normi*z, normi*w);
  167. }
  168. // invert
  169. inline void Quat::invert()
  170. {
  171. ME = getInverted();
  172. }
  173. // CalcFromVecVec
  174. inline void Quat::setFrom2Vec3(const Vec3& from, const Vec3& to)
  175. {
  176. Vec3 axis(from.cross(to));
  177. ME = Quat(axis.x, axis.y, axis.z, from.dot(to));
  178. normalize();
  179. w += 1.0;
  180. if(w <= EPSILON)
  181. {
  182. if(from.z*from.z > from.x*from.x)
  183. ME = Quat(0.0, from.z, -from.y, 0.0);
  184. else
  185. ME = Quat(from.y, -from.x, 0.0, 0.0);
  186. }
  187. normalize();
  188. }
  189. // getRotated
  190. inline Quat Quat::getRotated(const Quat& b) const
  191. {
  192. return ME * b;
  193. }
  194. // rotate
  195. inline void Quat::rotate(const Quat& b)
  196. {
  197. ME = getRotated(b);
  198. }
  199. // dot
  200. inline float Quat::dot(const Quat& b) const
  201. {
  202. return w*b.w + x*b.x + y*b.y + z*b.z;
  203. }
  204. // SLERP
  205. inline Quat Quat::slerp(const Quat& q1_, float t) const
  206. {
  207. const Quat& q0 = ME;
  208. Quat q1(q1_);
  209. float cosHalfTheta = q0.w*q1.w + q0.x*q1.x + q0.y*q1.y + q0.z*q1.z;
  210. if(cosHalfTheta < 0.0)
  211. {
  212. q1 = Quat(-Vec4(q1)); // quat changes
  213. cosHalfTheta = -cosHalfTheta;
  214. }
  215. if(fabs(cosHalfTheta) >= 1.0f)
  216. {
  217. return Quat(q0);
  218. }
  219. float halfTheta = acos(cosHalfTheta);
  220. float sinHalfTheta = M::sqrt(1.0 - cosHalfTheta*cosHalfTheta);
  221. if(fabs(sinHalfTheta) < 0.001)
  222. {
  223. return Quat((Vec4(q0) + Vec4(q1))*0.5);
  224. }
  225. float ratioA = sin((1.0 - t) * halfTheta) / sinHalfTheta;
  226. float ratio_b = sin(t * halfTheta) / sinHalfTheta;
  227. Vec4 tmp, tmp1, sum;
  228. tmp = Vec4(q0)*ratioA;
  229. tmp1 = Vec4(q1)*ratio_b;
  230. sum = tmp + tmp1;
  231. sum.normalize();
  232. return Quat(sum);
  233. }
  234. // setIdentity
  235. inline void Quat::setIdentity()
  236. {
  237. x = y = z = 0.0;
  238. w = 1.0;
  239. }
  240. // getIdentity
  241. inline const Quat::Quat& getIdentity()
  242. {
  243. static Quat ident(0.0, 0.0, 0.0, 1.0);
  244. return ident;
  245. }
  246. // print
  247. inline ostream& operator<<(ostream& s, const Quat& q)
  248. {
  249. s << q.w << ' ' << q.x << ' ' << q.y << ' ' << q.z;
  250. return s;
  251. }
  252. } // end namespace