| 1 | namespace glm |
| 2 | { |
| 3 | template<typename T, qualifier Q> |
| 4 | GLM_FUNC_QUALIFIER qua<T, Q> exp(qua<T, Q> const& q) |
| 5 | { |
| 6 | vec<3, T, Q> u(q.x, q.y, q.z); |
| 7 | T const Angle = glm::length(u); |
| 8 | if (Angle < epsilon<T>()) |
| 9 | return qua<T, Q>(); |
| 10 | |
| 11 | vec<3, T, Q> const v(u / Angle); |
| 12 | return qua<T, Q>(cos(Angle), sin(Angle) * v); |
| 13 | } |
| 14 | |
| 15 | template<typename T, qualifier Q> |
| 16 | GLM_FUNC_QUALIFIER qua<T, Q> log(qua<T, Q> const& q) |
| 17 | { |
| 18 | vec<3, T, Q> u(q.x, q.y, q.z); |
| 19 | T Vec3Len = length(u); |
| 20 | |
| 21 | if (Vec3Len < epsilon<T>()) |
| 22 | { |
| 23 | if(q.w > static_cast<T>(0)) |
| 24 | return qua<T, Q>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); |
| 25 | else if(q.w < static_cast<T>(0)) |
| 26 | return qua<T, Q>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0)); |
| 27 | else |
| 28 | return qua<T, Q>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()); |
| 29 | } |
| 30 | else |
| 31 | { |
| 32 | T t = atan(Vec3Len, T(q.w)) / Vec3Len; |
| 33 | T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w; |
| 34 | return qua<T, Q>(static_cast<T>(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | template<typename T, qualifier Q> |
| 39 | GLM_FUNC_QUALIFIER qua<T, Q> pow(qua<T, Q> const& x, T y) |
| 40 | { |
| 41 | //Raising to the power of 0 should yield 1 |
| 42 | //Needed to prevent a division by 0 error later on |
| 43 | if(y > -epsilon<T>() && y < epsilon<T>()) |
| 44 | return qua<T, Q>(1,0,0,0); |
| 45 | |
| 46 | //To deal with non-unit quaternions |
| 47 | T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w); |
| 48 | |
| 49 | //Equivalent to raising a real number to a power |
| 50 | //Needed to prevent a division by 0 error later on |
| 51 | if(abs(x.w / magnitude) > static_cast<T>(1) - epsilon<T>() && abs(x.w / magnitude) < static_cast<T>(1) + epsilon<T>()) |
| 52 | return qua<T, Q>(pow(x.w, y), 0, 0, 0); |
| 53 | |
| 54 | T Angle = acos(x.w / magnitude); |
| 55 | T NewAngle = Angle * y; |
| 56 | T Div = sin(NewAngle) / sin(Angle); |
| 57 | T Mag = pow(magnitude, y - static_cast<T>(1)); |
| 58 | |
| 59 | return qua<T, Q>(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); |
| 60 | } |
| 61 | |
| 62 | template<typename T, qualifier Q> |
| 63 | GLM_FUNC_QUALIFIER qua<T, Q> sqrt(qua<T, Q> const& x) |
| 64 | { |
| 65 | return pow(x, static_cast<T>(0.5)); |
| 66 | } |
| 67 | }//namespace glm |
| 68 | |
| 69 | |