Browse Source

Merge pull request #1148 from Vadmeme/master

Made GLM_FORCE_QUAT_DATA_XYZW be supported by most major functions #1148
Christophe 2 years ago
parent
commit
d46ce89c74

+ 2 - 0
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<T, Q> wxyz(T w, T x, T y, T z);
+
 		// -- Conversion constructors --
 
 		template<typename U, qualifier P>

+ 17 - 8
glm/detail/type_quat.inl

@@ -28,7 +28,7 @@ namespace detail
 	{
 		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
 		{
-			return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z);
+			return qua<T, Q>::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<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
 		{
-			return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z);
+			return qua<T, Q>::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<T, Q> call(qua<T, Q> const& q, T s)
 		{
-			return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s);
+			return qua<T, Q>::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<T, Q> call(qua<T, Q> const& q, T s)
 		{
-			return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s);
+			return qua<T, Q>::wxyz(q.w / s, q.x / s, q.y / s, q.z / s);
 		}
 	};
 
@@ -150,6 +150,15 @@ namespace detail
 #	endif
 	{}
 
+	template <typename T, qualifier Q>
+	GLM_CONSTEXPR qua<T, Q> qua<T, Q>::wxyz(T w, T x, T y, T z) {
+#	ifdef GLM_FORCE_QUAT_DATA_XYZW
+		return qua<T, Q>(x, y, z, w);
+#	else
+		return qua<T, Q>(w, x, y, z);
+#	endif
+	}
+	
 	// -- Conversion constructors --
 
 	template<typename T, qualifier Q>
@@ -201,7 +210,7 @@ namespace detail
 			t = cross(u, v);
 		}
 
-		*this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z));
+		*this = normalize(qua<T, Q>::wxyz(real_part, t.x, t.y, t.z));
 	}
 
 	template<typename T, qualifier Q>
@@ -320,7 +329,7 @@ namespace detail
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q)
 	{
-		return qua<T, Q>(-q.w, -q.x, -q.y, -q.z);
+		return qua<T, Q>::wxyz(-q.w, -q.x, -q.y, -q.z);
 	}
 
 	// -- Binary operators --
@@ -374,7 +383,7 @@ namespace detail
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s)
 	{
-		return qua<T, Q>(
+		return qua<T, Q>::wxyz(
 			q.w * s, q.x * s, q.y * s, q.z * s);
 	}
 
@@ -387,7 +396,7 @@ namespace detail
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s)
 	{
-		return qua<T, Q>(
+		return qua<T, Q>::wxyz(
 			q.w / s, q.x / s, q.y / s, q.z / s);
 	}
 

+ 39 - 18
glm/detail/type_quat_simd.inl

@@ -161,24 +161,45 @@ namespace detail
 	{
 		static vec<4, float, Q> call(qua<float, Q> 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));
-
-			__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;
+#			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 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;
+#			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

+ 4 - 4
glm/ext/quaternion_common.inl

@@ -11,7 +11,7 @@ namespace glm
 		if(cosTheta > static_cast<T>(1) - epsilon<T>())
 		{
 			// Linear interpolation
-			return qua<T, Q>(
+			return qua<T, Q>::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<T>(1) - epsilon<T>())
 		{
 			// Linear interpolation
-			return qua<T, Q>(
+			return qua<T, Q>::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<T>(1) - epsilon<T>())
         {
             // Linear interpolation
-            return qua<T, Q>(
+            return qua<T, Q>::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<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER qua<T, Q> conjugate(qua<T, Q> const& q)
 	{
-		return qua<T, Q>(q.w, -q.x, -q.y, -q.z);
+		return qua<T, Q>::wxyz(q.w, -q.x, -q.y, -q.z);
 	}
 
 	template<typename T, qualifier Q>

+ 7 - 7
glm/ext/quaternion_exponential.inl

@@ -23,17 +23,17 @@ namespace glm
 		if (Vec3Len < epsilon<T>())
 		{
 			if(q.w > static_cast<T>(0))
-				return qua<T, Q>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
+				return qua<T, Q>::wxyz(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
 			else if(q.w < static_cast<T>(0))
-				return qua<T, Q>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0));
+				return qua<T, Q>::wxyz(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0));
 			else
-				return qua<T, Q>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
+				return qua<T, Q>::wxyz(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
 		}
 		else
 		{
 			T t = atan(Vec3Len, T(q.w)) / Vec3Len;
 			T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w;
-			return qua<T, Q>(static_cast<T>(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z);
+			return qua<T, Q>::wxyz(static_cast<T>(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<T>() && y < epsilon<T>())
-			return qua<T, Q>(1,0,0,0);
+			return qua<T, Q>::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<T>::min()) {
 				//Equivalent to raising a real number to a power
-				return qua<T, Q>(pow(x.w, y), 0, 0, 0);
+				return qua<T, Q>::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<T>(1));
-		return qua<T, Q>(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag);
+		return qua<T, Q>::wxyz(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag);
 	}
 
 	template<typename T, qualifier Q>

+ 3 - 3
glm/ext/quaternion_geometric.inl

@@ -18,15 +18,15 @@ namespace glm
 	{
 		T len = length(q);
 		if(len <= static_cast<T>(0)) // Problem
-			return qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
+			return qua<T, Q>::wxyz(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
 		T oneOverLen = static_cast<T>(1) / len;
-		return qua<T, Q>(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen);
+		return qua<T, Q>::wxyz(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen);
 	}
 
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER qua<T, Q> cross(qua<T, Q> const& q1, qua<T, Q> const& q2)
 	{
-		return qua<T, Q>(
+		return qua<T, Q>::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,

+ 1 - 1
glm/ext/quaternion_transform.inl

@@ -18,7 +18,7 @@ namespace glm
 		T const AngleRad(angle);
 		T const Sin = sin(AngleRad * static_cast<T>(0.5));
 
-		return q * qua<T, Q>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
+		return q * qua<T, Q>::wxyz(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
 	}
 }//namespace glm
 

+ 5 - 5
glm/gtc/quaternion.inl

@@ -109,16 +109,16 @@ namespace glm
 		switch(biggestIndex)
 		{
 		case 0:
-			return qua<T, Q>(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult);
+			return qua<T, Q>::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<T, Q>((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult);
+			return qua<T, Q>::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<T, Q>((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult);
+			return qua<T, Q>::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<T, Q>((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal);
+			return qua<T, Q>::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<T, Q>(1, 0, 0, 0);
+			return qua<T, Q>::wxyz(1, 0, 0, 0);
 		}
 	}
 

+ 8 - 8
glm/gtx/dual_quaternion.inl

@@ -28,7 +28,7 @@ namespace glm
 		GLM_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat()
 #			if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE
 			: real(qua<T, Q>())
-			, dual(qua<T, Q>(0, 0, 0, 0))
+			, dual(qua<T, Q>::wxyz(0, 0, 0, 0))
 #			endif
 		{}
 
@@ -50,16 +50,16 @@ namespace glm
 
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(qua<T, Q> const& r)
-		: real(r), dual(qua<T, Q>(0, 0, 0, 0))
+		: real(r), dual(qua<T, Q>::wxyz(0, 0, 0, 0))
 	{}
 
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat<T, Q>::tdualquat(qua<T, Q> const& q, vec<3, T, Q> const& p)
-		: real(q), dual(
+		: real(q), dual(qua<T, Q>::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<typename T, qualifier Q>
@@ -219,8 +219,8 @@ namespace glm
 	GLM_FUNC_QUALIFIER tdualquat<T, Q> dual_quat_identity()
 	{
 		return tdualquat<T, Q>(
-			qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)),
-			qua<T, Q>(static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)));
+			qua<T, Q>::wxyz(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)),
+			qua<T, Q>::wxyz(static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)));
 	}
 
 	template<typename T, qualifier Q>
@@ -295,8 +295,8 @@ namespace glm
 	GLM_FUNC_QUALIFIER tdualquat<T, Q> dualquat_cast(mat<2, 4, T, Q> const& x)
 	{
 		return tdualquat<T, Q>(
-			qua<T, Q>( x[0].w, x[0].x, x[0].y, x[0].z ),
-			qua<T, Q>( x[1].w, x[1].x, x[1].y, x[1].z ));
+			qua<T, Q>::wxyz( x[0].w, x[0].x, x[0].y, x[0].z ),
+			qua<T, Q>::wxyz( x[1].w, x[1].x, x[1].y, x[1].z ));
 	}
 
 	template<typename T, qualifier Q>

+ 3 - 3
glm/gtx/quaternion.inl

@@ -8,7 +8,7 @@ namespace glm
 	template<typename T, qualifier Q>
 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> quat_identity()
 	{
-		return qua<T, Q>(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
+		return qua<T, Q>::wxyz(static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0));
 	}
 
 	template<typename T, qualifier Q>
@@ -105,7 +105,7 @@ namespace glm
 			k1 = sin((static_cast<T>(0) + a) * fAngle) * fOneOverSin;
 		}
 
-		return qua<T, Q>(
+		return qua<T, Q>::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<T>(2));
 		T invs = static_cast<T>(1) / s;
 
-		return qua<T, Q>(
+		return qua<T, Q>::wxyz(
 			s * static_cast<T>(0.5f),
 			rotationAxis.x * invs,
 			rotationAxis.y * invs,

+ 1 - 1
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<T, Q>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
+		return q * qua<T, Q>::wxyz(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin);
 		//return gtc::quaternion::cross(q, tquat<T, Q>(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin));
 	}
 }//namespace glm