1#include "../trigonometric.hpp" 2#include "../exponential.hpp" 3#include "../ext/quaternion_geometric.hpp" 4#include <limits> 5 6namespace glm{ 7namespace detail 8{ 9 template <typename T> 10 struct genTypeTrait<qua<T> > 11 { 12 static const genTypeEnum GENTYPE = GENTYPE_QUAT; 13 }; 14 15 template<typename T, qualifier Q, bool Aligned> 16 struct compute_dot<qua<T, Q>, T, Aligned> 17 { 18 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua<T, Q> const& a, qua<T, Q> const& b) 19 { 20 vec<4, T, Q> tmp(a.w * b.w, a.x * b.x, a.y * b.y, a.z * b.z); 21 return (tmp.x + tmp.y) + (tmp.z + tmp.w); 22 } 23 }; 24 25 template<typename T, qualifier Q, bool Aligned> 26 struct compute_quat_add 27 { 28 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p) 29 { 30 return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); 31 } 32 }; 33 34 template<typename T, qualifier Q, bool Aligned> 35 struct compute_quat_sub 36 { 37 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p) 38 { 39 return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); 40 } 41 }; 42 43 template<typename T, qualifier Q, bool Aligned> 44 struct compute_quat_mul_scalar 45 { 46 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s) 47 { 48 return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s); 49 } 50 }; 51 52 template<typename T, qualifier Q, bool Aligned> 53 struct compute_quat_div_scalar 54 { 55 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s) 56 { 57 return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s); 58 } 59 }; 60 61 template<typename T, qualifier Q, bool Aligned> 62 struct compute_quat_mul_vec4 63 { 64 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua<T, Q> const& q, vec<4, T, Q> const& v) 65 { 66 return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); 67 } 68 }; 69}//namespace detail 70 71 // -- Component accesses -- 72 73 template<typename T, qualifier Q> 74 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua<T, Q>::operator[](typename qua<T, Q>::length_type i) 75 { 76 assert(i >= 0 && i < this->length()); 77# ifdef GLM_FORCE_QUAT_DATA_WXYZ 78 return (&w)[i]; 79# else 80 return (&x)[i]; 81# endif 82 } 83 84 template<typename T, qualifier Q> 85 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua<T, Q>::operator[](typename qua<T, Q>::length_type i) const 86 { 87 assert(i >= 0 && i < this->length()); 88# ifdef GLM_FORCE_QUAT_DATA_WXYZ 89 return (&w)[i]; 90# else 91 return (&x)[i]; 92# endif 93 } 94 95 // -- Implicit basic constructors -- 96 97# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE 98 template<typename T, qualifier Q> 99 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua() 100# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE 101# ifdef GLM_FORCE_QUAT_DATA_WXYZ 102 : w(1), x(0), y(0), z(0) 103# else 104 : x(0), y(0), z(0), w(1) 105# endif 106# endif 107 {} 108 109 template<typename T, qualifier Q> 110 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, Q> const& q) 111# ifdef GLM_FORCE_QUAT_DATA_WXYZ 112 : w(q.w), x(q.x), y(q.y), z(q.z) 113# else 114 : x(q.x), y(q.y), z(q.z), w(q.w) 115# endif 116 {} 117# endif 118 119 template<typename T, qualifier Q> 120 template<qualifier P> 121 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, P> const& q) 122# ifdef GLM_FORCE_QUAT_DATA_WXYZ 123 : w(q.w), x(q.x), y(q.y), z(q.z) 124# else 125 : x(q.x), y(q.y), z(q.z), w(q.w) 126# endif 127 {} 128 129 // -- Explicit basic constructors -- 130 131 template<typename T, qualifier Q> 132 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T s, vec<3, T, Q> const& v) 133# ifdef GLM_FORCE_QUAT_DATA_WXYZ 134 : w(s), x(v.x), y(v.y), z(v.z) 135# else 136 : x(v.x), y(v.y), z(v.z), w(s) 137# endif 138 {} 139 140 template <typename T, qualifier Q> 141 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T _w, T _x, T _y, T _z) 142# ifdef GLM_FORCE_QUAT_DATA_WXYZ 143 : w(_w), x(_x), y(_y), z(_z) 144# else 145 : x(_x), y(_y), z(_z), w(_w) 146# endif 147 {} 148 149 // -- Conversion constructors -- 150 151 template<typename T, qualifier Q> 152 template<typename U, qualifier P> 153 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<U, P> const& q) 154# ifdef GLM_FORCE_QUAT_DATA_WXYZ 155 : w(static_cast<T>(q.w)), x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)) 156# else 157 : x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)), w(static_cast<T>(q.w)) 158# endif 159 {} 160 161 //template<typename valType> 162 //GLM_FUNC_QUALIFIER qua<valType>::qua 163 //( 164 // valType const& pitch, 165 // valType const& yaw, 166 // valType const& roll 167 //) 168 //{ 169 // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5)); 170 // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5)); 171 // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5)); 172 // 173 // this->w = c.x * c.y * c.z + s.x * s.y * s.z; 174 // this->x = s.x * c.y * c.z - c.x * s.y * s.z; 175 // this->y = c.x * s.y * c.z + s.x * c.y * s.z; 176 // this->z = c.x * c.y * s.z - s.x * s.y * c.z; 177 //} 178 179 template<typename T, qualifier Q> 180 GLM_FUNC_QUALIFIER qua<T, Q>::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v) 181 { 182 T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); 183 T real_part = norm_u_norm_v + dot(u, v); 184 vec<3, T, Q> t; 185 186 if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v) 187 { 188 // If u and v are exactly opposite, rotate 180 degrees 189 // around an arbitrary orthogonal axis. Axis normalisation 190 // can happen later, when we normalise the quaternion. 191 real_part = static_cast<T>(0); 192 t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast<T>(0)) : vec<3, T, Q>(static_cast<T>(0), -u.z, u.y); 193 } 194 else 195 { 196 // Otherwise, build quaternion the standard way. 197 t = cross(u, v); 198 } 199 200 *this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z)); 201 } 202 203 template<typename T, qualifier Q> 204 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(vec<3, T, Q> const& eulerAngle) 205 { 206 vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5)); 207 vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5)); 208 209 this->w = c.x * c.y * c.z + s.x * s.y * s.z; 210 this->x = s.x * c.y * c.z - c.x * s.y * s.z; 211 this->y = c.x * s.y * c.z + s.x * c.y * s.z; 212 this->z = c.x * c.y * s.z - s.x * s.y * c.z; 213 } 214 215 template<typename T, qualifier Q> 216 GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<3, 3, T, Q> const& m) 217 { 218 *this = quat_cast(m); 219 } 220 221 template<typename T, qualifier Q> 222 GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<4, 4, T, Q> const& m) 223 { 224 *this = quat_cast(m); 225 } 226 227# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS 228 template<typename T, qualifier Q> 229 GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<3, 3, T, Q>() const 230 { 231 return mat3_cast(*this); 232 } 233 234 template<typename T, qualifier Q> 235 GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<4, 4, T, Q>() const 236 { 237 return mat4_cast(*this); 238 } 239# endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS 240 241 // -- Unary arithmetic operators -- 242 243# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE 244 template<typename T, qualifier Q> 245 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<T, Q> const& q) 246 { 247 this->w = q.w; 248 this->x = q.x; 249 this->y = q.y; 250 this->z = q.z; 251 return *this; 252 } 253# endif 254 255 template<typename T, qualifier Q> 256 template<typename U> 257 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<U, Q> const& q) 258 { 259 this->w = static_cast<T>(q.w); 260 this->x = static_cast<T>(q.x); 261 this->y = static_cast<T>(q.y); 262 this->z = static_cast<T>(q.z); 263 return *this; 264 } 265 266 template<typename T, qualifier Q> 267 template<typename U> 268 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator+=(qua<U, Q> const& q) 269 { 270 return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q))); 271 } 272 273 template<typename T, qualifier Q> 274 template<typename U> 275 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator-=(qua<U, Q> const& q) 276 { 277 return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q))); 278 } 279 280 template<typename T, qualifier Q> 281 template<typename U> 282 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(qua<U, Q> const& r) 283 { 284 qua<T, Q> const p(*this); 285 qua<T, Q> const q(r); 286 287 this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; 288 this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; 289 this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; 290 this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; 291 return *this; 292 } 293 294 template<typename T, qualifier Q> 295 template<typename U> 296 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(U s) 297 { 298 return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s))); 299 } 300 301 template<typename T, qualifier Q> 302 template<typename U> 303 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator/=(U s) 304 { 305 return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s))); 306 } 307 308 // -- Unary bit operators -- 309 310 template<typename T, qualifier Q> 311 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q) 312 { 313 return q; 314 } 315 316 template<typename T, qualifier Q> 317 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q) 318 { 319 return qua<T, Q>(-q.w, -q.x, -q.y, -q.z); 320 } 321 322 // -- Binary operators -- 323 324 template<typename T, qualifier Q> 325 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p) 326 { 327 return qua<T, Q>(q) += p; 328 } 329 330 template<typename T, qualifier Q> 331 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p) 332 { 333 return qua<T, Q>(q) -= p; 334 } 335 336 template<typename T, qualifier Q> 337 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p) 338 { 339 return qua<T, Q>(q) *= p; 340 } 341 342 template<typename T, qualifier Q> 343 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v) 344 { 345 vec<3, T, Q> const QuatVector(q.x, q.y, q.z); 346 vec<3, T, Q> const uv(glm::cross(QuatVector, v)); 347 vec<3, T, Q> const uuv(glm::cross(QuatVector, uv)); 348 349 return v + ((uv * q.w) + uuv) * static_cast<T>(2); 350 } 351 352 template<typename T, qualifier Q> 353 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q) 354 { 355 return glm::inverse(q) * v; 356 } 357 358 template<typename T, qualifier Q> 359 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v) 360 { 361 return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v); 362 } 363 364 template<typename T, qualifier Q> 365 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q) 366 { 367 return glm::inverse(q) * v; 368 } 369 370 template<typename T, qualifier Q> 371 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s) 372 { 373 return qua<T, Q>( 374 q.w * s, q.x * s, q.y * s, q.z * s); 375 } 376 377 template<typename T, qualifier Q> 378 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(T const& s, qua<T, Q> const& q) 379 { 380 return q * s; 381 } 382 383 template<typename T, qualifier Q> 384 GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s) 385 { 386 return qua<T, Q>( 387 q.w / s, q.x / s, q.y / s, q.z / s); 388 } 389 390 // -- Boolean operators -- 391 392 template<typename T, qualifier Q> 393 GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2) 394 { 395 return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w; 396 } 397 398 template<typename T, qualifier Q> 399 GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> const& q2) 400 { 401 return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w; 402 } 403}//namespace glm 404 405#if GLM_CONFIG_SIMD == GLM_ENABLE 406# include "type_quat_simd.inl" 407#endif 408 409