diff --git a/glm/detail/type_quat.hpp b/glm/detail/type_quat.hpp index 67a84742..d3726743 100644 --- a/glm/detail/type_quat.hpp +++ b/glm/detail/type_quat.hpp @@ -95,6 +95,8 @@ namespace glm GLM_FUNC_DECL GLM_CONSTEXPR qua(T w, T x, T y, T z); # endif + GLM_FUNC_DECL static GLM_CONSTEXPR qua wxyz(T w, T x, T y, T z); + // -- Conversion constructors -- template diff --git a/glm/detail/type_quat.inl b/glm/detail/type_quat.inl index 4b1e84d9..ed297368 100644 --- a/glm/detail/type_quat.inl +++ b/glm/detail/type_quat.inl @@ -28,7 +28,7 @@ namespace detail { GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) { - return qua(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); + return qua::wxyz(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); } }; @@ -37,7 +37,7 @@ namespace detail { GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) { - return qua(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); + return qua::wxyz(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); } }; @@ -46,7 +46,7 @@ namespace detail { GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) { - return qua(q.w * s, q.x * s, q.y * s, q.z * s); + return qua::wxyz(q.w * s, q.x * s, q.y * s, q.z * s); } }; @@ -55,7 +55,7 @@ namespace detail { GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) { - return qua(q.w / s, q.x / s, q.y / s, q.z / s); + return qua::wxyz(q.w / s, q.x / s, q.y / s, q.z / s); } }; @@ -150,6 +150,15 @@ namespace detail # endif {} + template + GLM_CONSTEXPR qua qua::wxyz(T w, T x, T y, T z) { +# ifdef GLM_FORCE_QUAT_DATA_XYZW + return qua(x, y, z, w); +# else + return qua(w, x, y, z); +# endif + } + // -- Conversion constructors -- template @@ -201,7 +210,7 @@ namespace detail t = cross(u, v); } - *this = normalize(qua(real_part, t.x, t.y, t.z)); + *this = normalize(qua::wxyz(real_part, t.x, t.y, t.z)); } template @@ -320,7 +329,7 @@ namespace detail template GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator-(qua const& q) { - return qua(-q.w, -q.x, -q.y, -q.z); + return qua::wxyz(-q.w, -q.x, -q.y, -q.z); } // -- Binary operators -- @@ -374,7 +383,7 @@ namespace detail template GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(qua const& q, T const& s) { - return qua( + return qua::wxyz( q.w * s, q.x * s, q.y * s, q.z * s); } @@ -387,7 +396,7 @@ namespace detail template GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator/(qua const& q, T const& s) { - return qua( + return qua::wxyz( q.w / s, q.x / s, q.y / s, q.z / s); } diff --git a/glm/detail/type_quat_simd.inl b/glm/detail/type_quat_simd.inl index a77b56c5..35b0f7f8 100644 --- a/glm/detail/type_quat_simd.inl +++ b/glm/detail/type_quat_simd.inl @@ -161,24 +161,45 @@ namespace detail { static vec<4, float, Q> call(qua const& q, vec<4, float, Q> const& v) { - __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 3, 3, 3)); - __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 0, 2, 1)); - __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 1, 0, 2)); - __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); - __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); +# ifdef GLM_FORCE_QUAT_DATA_XYZW + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); - __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); - __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); - __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); - __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); - __m128 const two = _mm_set1_ps(2.0f); - uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); - uuv = _mm_mul_ps(uuv, two); + __m128 const two = _mm_set1_ps(2.0f); + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); - vec<4, float, Q> Result; - Result.data = _mm_add_ps(v.data, _mm_add_ps(uv, uuv)); - return Result; + vec<4, float, Q> Result; + Result.data = _mm_add_ps(v.data, _mm_add_ps(uv, uuv)); + return Result; +# else + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 1, 3, 2)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 2, 1, 3)); + __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); + + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + + __m128 const two = _mm_set1_ps(2.0f); + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); + + vec<4, float, Q> Result; + Result.data = _mm_add_ps(v.data, _mm_add_ps(uv, uuv)); + return Result; +# endif } }; }//namespace detail diff --git a/glm/ext/quaternion_common.inl b/glm/ext/quaternion_common.inl index 6f99f52d..014a7ae1 100644 --- a/glm/ext/quaternion_common.inl +++ b/glm/ext/quaternion_common.inl @@ -11,7 +11,7 @@ namespace glm if(cosTheta > static_cast(1) - epsilon()) { // Linear interpolation - return qua( + return qua::wxyz( mix(x.w, y.w, a), mix(x.x, y.x, a), mix(x.y, y.y, a), @@ -58,7 +58,7 @@ namespace glm if(cosTheta > static_cast(1) - epsilon()) { // Linear interpolation - return qua( + return qua::wxyz( mix(x.w, z.w, a), mix(x.x, z.x, a), mix(x.y, z.y, a), @@ -94,7 +94,7 @@ namespace glm if (cosTheta > static_cast(1) - epsilon()) { // Linear interpolation - return qua( + return qua::wxyz( mix(x.w, z.w, a), mix(x.x, z.x, a), mix(x.y, z.y, a), @@ -112,7 +112,7 @@ namespace glm template GLM_FUNC_QUALIFIER qua conjugate(qua const& q) { - return qua(q.w, -q.x, -q.y, -q.z); + return qua::wxyz(q.w, -q.x, -q.y, -q.z); } template diff --git a/glm/ext/quaternion_exponential.inl b/glm/ext/quaternion_exponential.inl index dd24b6cb..8a9d774b 100644 --- a/glm/ext/quaternion_exponential.inl +++ b/glm/ext/quaternion_exponential.inl @@ -23,17 +23,17 @@ namespace glm if (Vec3Len < epsilon()) { if(q.w > static_cast(0)) - return qua(log(q.w), static_cast(0), static_cast(0), static_cast(0)); + return qua::wxyz(log(q.w), static_cast(0), static_cast(0), static_cast(0)); else if(q.w < static_cast(0)) - return qua(log(-q.w), pi(), static_cast(0), static_cast(0)); + return qua::wxyz(log(-q.w), pi(), static_cast(0), static_cast(0)); else - return qua(std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()); + return qua::wxyz(std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()); } else { T t = atan(Vec3Len, T(q.w)) / Vec3Len; T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w; - return qua(static_cast(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); + return qua::wxyz(static_cast(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); } } @@ -43,7 +43,7 @@ namespace glm //Raising to the power of 0 should yield 1 //Needed to prevent a division by 0 error later on if(y > -epsilon() && y < epsilon()) - return qua(1,0,0,0); + return qua::wxyz(1,0,0,0); //To deal with non-unit quaternions T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w); @@ -62,7 +62,7 @@ namespace glm //always false, even when VectorMagnitude is 0. if (VectorMagnitude < std::numeric_limits::min()) { //Equivalent to raising a real number to a power - return qua(pow(x.w, y), 0, 0, 0); + return qua::wxyz(pow(x.w, y), 0, 0, 0); } Angle = asin(sqrt(VectorMagnitude) / magnitude); @@ -76,7 +76,7 @@ namespace glm T NewAngle = Angle * y; T Div = sin(NewAngle) / sin(Angle); T Mag = pow(magnitude, y - static_cast(1)); - return qua(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); + return qua::wxyz(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); } template diff --git a/glm/ext/quaternion_geometric.inl b/glm/ext/quaternion_geometric.inl index e155ac52..93bb6b9d 100644 --- a/glm/ext/quaternion_geometric.inl +++ b/glm/ext/quaternion_geometric.inl @@ -18,15 +18,15 @@ namespace glm { T len = length(q); if(len <= static_cast(0)) // Problem - return qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + return qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); T oneOverLen = static_cast(1) / len; - return qua(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + return qua::wxyz(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); } template GLM_FUNC_QUALIFIER qua cross(qua const& q1, qua const& q2) { - return qua( + return qua::wxyz( q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, diff --git a/glm/ext/quaternion_transform.inl b/glm/ext/quaternion_transform.inl index b87ecb65..7e773fbd 100644 --- a/glm/ext/quaternion_transform.inl +++ b/glm/ext/quaternion_transform.inl @@ -18,7 +18,7 @@ namespace glm T const AngleRad(angle); T const Sin = sin(AngleRad * static_cast(0.5)); - return q * qua(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + return q * qua::wxyz(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); } }//namespace glm diff --git a/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl index e1ef0321..702ebabd 100644 --- a/glm/gtc/quaternion.inl +++ b/glm/gtc/quaternion.inl @@ -109,16 +109,16 @@ namespace glm switch(biggestIndex) { case 0: - return qua(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult); + return qua::wxyz(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult); case 1: - return qua((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult); + return qua::wxyz((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult); case 2: - return qua((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult); + return qua::wxyz((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult); case 3: - return qua((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal); + return qua::wxyz((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal); default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity. assert(false); - return qua(1, 0, 0, 0); + return qua::wxyz(1, 0, 0, 0); } } diff --git a/glm/gtx/dual_quaternion.inl b/glm/gtx/dual_quaternion.inl index 7f990b3c..3a04160e 100644 --- a/glm/gtx/dual_quaternion.inl +++ b/glm/gtx/dual_quaternion.inl @@ -28,7 +28,7 @@ namespace glm GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat() # if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE : real(qua()) - , dual(qua(0, 0, 0, 0)) + , dual(qua::wxyz(0, 0, 0, 0)) # endif {} @@ -50,16 +50,16 @@ namespace glm template GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& r) - : real(r), dual(qua(0, 0, 0, 0)) + : real(r), dual(qua::wxyz(0, 0, 0, 0)) {} template GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& q, vec<3, T, Q> const& p) - : real(q), dual( + : real(q), dual(qua::wxyz( T(-0.5) * ( p.x*q.x + p.y*q.y + p.z*q.z), T(+0.5) * ( p.x*q.w + p.y*q.z - p.z*q.y), T(+0.5) * (-p.x*q.z + p.y*q.w + p.z*q.x), - T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w)) + T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w))) {} template @@ -219,8 +219,8 @@ namespace glm GLM_FUNC_QUALIFIER tdualquat dual_quat_identity() { return tdualquat( - qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)), - qua(static_cast(0), static_cast(0), static_cast(0), static_cast(0))); + qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)), + qua::wxyz(static_cast(0), static_cast(0), static_cast(0), static_cast(0))); } template @@ -295,8 +295,8 @@ namespace glm GLM_FUNC_QUALIFIER tdualquat dualquat_cast(mat<2, 4, T, Q> const& x) { return tdualquat( - qua( x[0].w, x[0].x, x[0].y, x[0].z ), - qua( x[1].w, x[1].x, x[1].y, x[1].z )); + qua::wxyz( x[0].w, x[0].x, x[0].y, x[0].z ), + qua::wxyz( x[1].w, x[1].x, x[1].y, x[1].z )); } template diff --git a/glm/gtx/quaternion.inl b/glm/gtx/quaternion.inl index d125bccc..838126e9 100644 --- a/glm/gtx/quaternion.inl +++ b/glm/gtx/quaternion.inl @@ -8,7 +8,7 @@ namespace glm template GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua quat_identity() { - return qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + return qua::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); } template @@ -105,7 +105,7 @@ namespace glm k1 = sin((static_cast(0) + a) * fAngle) * fOneOverSin; } - return qua( + return qua::wxyz( k0 * x.w + k1 * y2.w, k0 * x.x + k1 * y2.x, k0 * x.y + k1 * y2.y, @@ -150,7 +150,7 @@ namespace glm T s = sqrt((T(1) + cosTheta) * static_cast(2)); T invs = static_cast(1) / s; - return qua( + return qua::wxyz( s * static_cast(0.5f), rotationAxis.x * invs, rotationAxis.y * invs, diff --git a/glm/gtx/rotate_normalized_axis.inl b/glm/gtx/rotate_normalized_axis.inl index b2e9278c..352a56cb 100644 --- a/glm/gtx/rotate_normalized_axis.inl +++ b/glm/gtx/rotate_normalized_axis.inl @@ -52,7 +52,7 @@ namespace glm T const AngleRad(angle); T const Sin = sin(AngleRad * T(0.5)); - return q * qua(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + return q * qua::wxyz(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); //return gtc::quaternion::cross(q, tquat(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); } }//namespace glm