quaternion.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "vec3.h"
  5. #include "vec4.h"
  6. #include "transcendental.h"
  7. namespace embree
  8. {
  9. ////////////////////////////////////////////////////////////////
  10. // Quaternion Struct
  11. ////////////////////////////////////////////////////////////////
  12. template<typename T>
  13. struct QuaternionT
  14. {
  15. typedef Vec3<T> Vector;
  16. ////////////////////////////////////////////////////////////////////////////////
  17. /// Construction
  18. ////////////////////////////////////////////////////////////////////////////////
  19. __forceinline QuaternionT () { }
  20. __forceinline QuaternionT ( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; }
  21. __forceinline QuaternionT& operator=( const QuaternionT& other ) { r = other.r; i = other.i; j = other.j; k = other.k; return *this; }
  22. __forceinline QuaternionT( const T& r ) : r(r), i(zero), j(zero), k(zero) {}
  23. __forceinline explicit QuaternionT( const Vec3<T>& v ) : r(zero), i(v.x), j(v.y), k(v.z) {}
  24. __forceinline explicit QuaternionT( const Vec4<T>& v ) : r(v.x), i(v.y), j(v.z), k(v.w) {}
  25. __forceinline QuaternionT( const T& r, const T& i, const T& j, const T& k ) : r(r), i(i), j(j), k(k) {}
  26. __forceinline QuaternionT( const T& r, const Vec3<T>& v ) : r(r), i(v.x), j(v.y), k(v.z) {}
  27. __inline QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz );
  28. __inline QuaternionT( const T& yaw, const T& pitch, const T& roll );
  29. ////////////////////////////////////////////////////////////////////////////////
  30. /// Constants
  31. ////////////////////////////////////////////////////////////////////////////////
  32. __forceinline QuaternionT( ZeroTy ) : r(zero), i(zero), j(zero), k(zero) {}
  33. __forceinline QuaternionT( OneTy ) : r( one), i(zero), j(zero), k(zero) {}
  34. /*! return quaternion for rotation around arbitrary axis */
  35. static __forceinline QuaternionT rotate(const Vec3<T>& u, const T& r) {
  36. return QuaternionT<T>(cos(T(0.5)*r),sin(T(0.5)*r)*normalize(u));
  37. }
  38. /*! returns the rotation axis of the quaternion as a vector */
  39. __forceinline Vec3<T> v( ) const { return Vec3<T>(i, j, k); }
  40. public:
  41. T r, i, j, k;
  42. };
  43. template<typename T> __forceinline QuaternionT<T> operator *( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a * b.r, a * b.i, a * b.j, a * b.k); }
  44. template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r * b, a.i * b, a.j * b, a.k * b); }
  45. ////////////////////////////////////////////////////////////////
  46. // Unary Operators
  47. ////////////////////////////////////////////////////////////////
  48. template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a ) { return QuaternionT<T>(+a.r, +a.i, +a.j, +a.k); }
  49. template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a ) { return QuaternionT<T>(-a.r, -a.i, -a.j, -a.k); }
  50. template<typename T> __forceinline QuaternionT<T> conj ( const QuaternionT<T>& a ) { return QuaternionT<T>(a.r, -a.i, -a.j, -a.k); }
  51. template<typename T> __forceinline T abs ( const QuaternionT<T>& a ) { return sqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
  52. template<typename T> __forceinline QuaternionT<T> rcp ( const QuaternionT<T>& a ) { return conj(a)*rcp(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
  53. template<typename T> __forceinline QuaternionT<T> normalize ( const QuaternionT<T>& a ) { return a*rsqrt(a.r*a.r + a.i*a.i + a.j*a.j + a.k*a.k); }
  54. // evaluates a*q-r
  55. template<typename T> __forceinline QuaternionT<T>
  56. msub(const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
  57. {
  58. return QuaternionT<T>(msub(a, q.r, p.r),
  59. msub(a, q.i, p.i),
  60. msub(a, q.j, p.j),
  61. msub(a, q.k, p.k));
  62. }
  63. // evaluates a*q-r
  64. template<typename T> __forceinline QuaternionT<T>
  65. madd (const T& a, const QuaternionT<T>& q, const QuaternionT<T>& p)
  66. {
  67. return QuaternionT<T>(madd(a, q.r, p.r),
  68. madd(a, q.i, p.i),
  69. madd(a, q.j, p.j),
  70. madd(a, q.k, p.k));
  71. }
  72. ////////////////////////////////////////////////////////////////
  73. // Binary Operators
  74. ////////////////////////////////////////////////////////////////
  75. template<typename T> __forceinline QuaternionT<T> operator +( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a + b.r, b.i, b.j, b.k); }
  76. template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r + b, a.i, a.j, a.k); }
  77. template<typename T> __forceinline QuaternionT<T> operator +( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r + b.r, a.i + b.i, a.j + b.j, a.k + b.k); }
  78. template<typename T> __forceinline QuaternionT<T> operator -( const T & a, const QuaternionT<T>& b ) { return QuaternionT<T>(a - b.r, -b.i, -b.j, -b.k); }
  79. template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const T & b ) { return QuaternionT<T>(a.r - b, a.i, a.j, a.k); }
  80. template<typename T> __forceinline QuaternionT<T> operator -( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return QuaternionT<T>(a.r - b.r, a.i - b.i, a.j - b.j, a.k - b.k); }
  81. template<typename T> __forceinline Vec3<T> operator *( const QuaternionT<T>& a, const Vec3<T> & b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
  82. template<typename T> __forceinline QuaternionT<T> operator *( const QuaternionT<T>& a, const QuaternionT<T>& b ) {
  83. return QuaternionT<T>(a.r*b.r - a.i*b.i - a.j*b.j - a.k*b.k,
  84. a.r*b.i + a.i*b.r + a.j*b.k - a.k*b.j,
  85. a.r*b.j - a.i*b.k + a.j*b.r + a.k*b.i,
  86. a.r*b.k + a.i*b.j - a.j*b.i + a.k*b.r);
  87. }
  88. template<typename T> __forceinline QuaternionT<T> operator /( const T & a, const QuaternionT<T>& b ) { return a*rcp(b); }
  89. template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const T & b ) { return a*rcp(b); }
  90. template<typename T> __forceinline QuaternionT<T> operator /( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a*rcp(b); }
  91. template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const T & b ) { return a = a+b; }
  92. template<typename T> __forceinline QuaternionT<T>& operator +=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a+b; }
  93. template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const T & b ) { return a = a-b; }
  94. template<typename T> __forceinline QuaternionT<T>& operator -=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a-b; }
  95. template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const T & b ) { return a = a*b; }
  96. template<typename T> __forceinline QuaternionT<T>& operator *=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*b; }
  97. template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const T & b ) { return a = a*rcp(b); }
  98. template<typename T> __forceinline QuaternionT<T>& operator /=( QuaternionT<T>& a, const QuaternionT<T>& b ) { return a = a*rcp(b); }
  99. template<typename T, typename M> __forceinline QuaternionT<T>
  100. select(const M& m, const QuaternionT<T>& q, const QuaternionT<T>& p)
  101. {
  102. return QuaternionT<T>(select(m, q.r, p.r),
  103. select(m, q.i, p.i),
  104. select(m, q.j, p.j),
  105. select(m, q.k, p.k));
  106. }
  107. template<typename T> __forceinline Vec3<T> xfmPoint ( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
  108. template<typename T> __forceinline Vec3<T> xfmVector( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
  109. template<typename T> __forceinline Vec3<T> xfmNormal( const QuaternionT<T>& a, const Vec3<T>& b ) { return (a*QuaternionT<T>(b)*conj(a)).v(); }
  110. template<typename T> __forceinline T dot(const QuaternionT<T>& a, const QuaternionT<T>& b) { return a.r*b.r + a.i*b.i + a.j*b.j + a.k*b.k; }
  111. ////////////////////////////////////////////////////////////////////////////////
  112. /// Comparison Operators
  113. ////////////////////////////////////////////////////////////////////////////////
  114. template<typename T> __forceinline bool operator ==( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r == b.r && a.i == b.i && a.j == b.j && a.k == b.k; }
  115. template<typename T> __forceinline bool operator !=( const QuaternionT<T>& a, const QuaternionT<T>& b ) { return a.r != b.r || a.i != b.i || a.j != b.j || a.k != b.k; }
  116. ////////////////////////////////////////////////////////////////////////////////
  117. /// Orientation Functions
  118. ////////////////////////////////////////////////////////////////////////////////
  119. template<typename T> QuaternionT<T>::QuaternionT( const Vec3<T>& vx, const Vec3<T>& vy, const Vec3<T>& vz )
  120. {
  121. if ( vx.x + vy.y + vz.z >= T(zero) )
  122. {
  123. const T t = T(one) + (vx.x + vy.y + vz.z);
  124. const T s = rsqrt(t)*T(0.5f);
  125. r = t*s;
  126. i = (vy.z - vz.y)*s;
  127. j = (vz.x - vx.z)*s;
  128. k = (vx.y - vy.x)*s;
  129. }
  130. else if ( vx.x >= max(vy.y, vz.z) )
  131. {
  132. const T t = (T(one) + vx.x) - (vy.y + vz.z);
  133. const T s = rsqrt(t)*T(0.5f);
  134. r = (vy.z - vz.y)*s;
  135. i = t*s;
  136. j = (vx.y + vy.x)*s;
  137. k = (vz.x + vx.z)*s;
  138. }
  139. else if ( vy.y >= vz.z ) // if ( vy.y >= max(vz.z, vx.x) )
  140. {
  141. const T t = (T(one) + vy.y) - (vz.z + vx.x);
  142. const T s = rsqrt(t)*T(0.5f);
  143. r = (vz.x - vx.z)*s;
  144. i = (vx.y + vy.x)*s;
  145. j = t*s;
  146. k = (vy.z + vz.y)*s;
  147. }
  148. else //if ( vz.z >= max(vy.y, vx.x) )
  149. {
  150. const T t = (T(one) + vz.z) - (vx.x + vy.y);
  151. const T s = rsqrt(t)*T(0.5f);
  152. r = (vx.y - vy.x)*s;
  153. i = (vz.x + vx.z)*s;
  154. j = (vy.z + vz.y)*s;
  155. k = t*s;
  156. }
  157. }
  158. template<typename T> QuaternionT<T>::QuaternionT( const T& yaw, const T& pitch, const T& roll )
  159. {
  160. const T cya = cos(yaw *T(0.5f));
  161. const T cpi = cos(pitch*T(0.5f));
  162. const T cro = cos(roll *T(0.5f));
  163. const T sya = sin(yaw *T(0.5f));
  164. const T spi = sin(pitch*T(0.5f));
  165. const T sro = sin(roll *T(0.5f));
  166. r = cro*cya*cpi + sro*sya*spi;
  167. i = cro*cya*spi + sro*sya*cpi;
  168. j = cro*sya*cpi - sro*cya*spi;
  169. k = sro*cya*cpi - cro*sya*spi;
  170. }
  171. //////////////////////////////////////////////////////////////////////////////
  172. /// Output Operators
  173. //////////////////////////////////////////////////////////////////////////////
  174. template<typename T> static embree_ostream operator<<(embree_ostream cout, const QuaternionT<T>& q) {
  175. return cout << "{ r = " << q.r << ", i = " << q.i << ", j = " << q.j << ", k = " << q.k << " }";
  176. }
  177. /*! default template instantiations */
  178. typedef QuaternionT<float> Quaternion3f;
  179. typedef QuaternionT<double> Quaternion3d;
  180. template<int N> using Quaternion3vf = QuaternionT<vfloat<N>>;
  181. typedef QuaternionT<vfloat<4>> Quaternion3vf4;
  182. typedef QuaternionT<vfloat<8>> Quaternion3vf8;
  183. typedef QuaternionT<vfloat<16>> Quaternion3vf16;
  184. //////////////////////////////////////////////////////////////////////////////
  185. /// Interpolation
  186. //////////////////////////////////////////////////////////////////////////////
  187. template<typename T>
  188. __forceinline QuaternionT<T>lerp(const QuaternionT<T>& q0,
  189. const QuaternionT<T>& q1,
  190. const T& factor)
  191. {
  192. QuaternionT<T> q;
  193. q.r = lerp(q0.r, q1.r, factor);
  194. q.i = lerp(q0.i, q1.i, factor);
  195. q.j = lerp(q0.j, q1.j, factor);
  196. q.k = lerp(q0.k, q1.k, factor);
  197. return q;
  198. }
  199. template<typename T>
  200. __forceinline QuaternionT<T> slerp(const QuaternionT<T>& q0,
  201. const QuaternionT<T>& q1_,
  202. const T& t)
  203. {
  204. T cosTheta = dot(q0, q1_);
  205. QuaternionT<T> q1 = select(cosTheta < 0.f, -q1_, q1_);
  206. cosTheta = select(cosTheta < 0.f, -cosTheta, cosTheta);
  207. // spherical linear interpolation
  208. const T phi = t * fastapprox::acos(cosTheta);
  209. T sinPhi, cosPhi;
  210. fastapprox::sincos(phi, sinPhi, cosPhi);
  211. QuaternionT<T> qperp = sinPhi * normalize(msub(cosTheta, q0, q1));
  212. QuaternionT<T> qslerp = msub(cosPhi, q0, qperp);
  213. // regular linear interpolation as fallback
  214. QuaternionT<T> qlerp = normalize(lerp(q0, q1, t));
  215. return select(cosTheta > 0.9995f, qlerp, qslerp);
  216. }
  217. }