|
@@ -71,6 +71,60 @@ Quat Quat::operator * (QuatArg inRHS) const
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+Quat Quat::sMultiplyImaginary(Vec3Arg inLHS, QuatArg inRHS)
|
|
|
+{
|
|
|
+#if defined(JPH_USE_SSE4_1)
|
|
|
+ __m128 abc0 = inLHS.mValue;
|
|
|
+ __m128 xyzw = inRHS.mValue.mValue;
|
|
|
+
|
|
|
+ // [a,a,a,a] * [w,y,z,x] = [aw,ay,az,ax]
|
|
|
+ __m128 aaaa = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(0, 0, 0, 0));
|
|
|
+ __m128 xzyw = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(3, 1, 2, 0));
|
|
|
+ __m128 axazayaw = _mm_mul_ps(aaaa, xzyw);
|
|
|
+
|
|
|
+ // [b,b,b,b] * [z,x,w,y] = [bz,bx,bw,by]
|
|
|
+ __m128 bbbb = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(1, 1, 1, 1));
|
|
|
+ __m128 ywxz = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(2, 0, 3, 1));
|
|
|
+ __m128 bybwbxbz = _mm_mul_ps(bbbb, ywxz);
|
|
|
+
|
|
|
+ // [c,c,c,c] * [w,z,x,y] = [cw,cz,cx,cy]
|
|
|
+ __m128 cccc = _mm_shuffle_ps(abc0, abc0, _MM_SHUFFLE(2, 2, 2, 2));
|
|
|
+ __m128 yxzw = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(3, 2, 0, 1));
|
|
|
+ __m128 cycxczcw = _mm_mul_ps(cccc, yxzw);
|
|
|
+
|
|
|
+ // [+aw,+ay,-az,-ax]
|
|
|
+ __m128 e = _mm_xor_ps(axazayaw, _mm_set_ps(0.0f, 0.0f, -0.0f, -0.0f));
|
|
|
+
|
|
|
+ // [+aw,+ay,-az,-ax] + -[bz,bx,bw,by] = [+aw+bz,+ay-bx,-az+bw,-ax-by]
|
|
|
+ e = _mm_addsub_ps(e, bybwbxbz);
|
|
|
+
|
|
|
+ // [+ay-bx,-ax-by,-az+bw,+aw+bz]
|
|
|
+ e = _mm_shuffle_ps(e, e, _MM_SHUFFLE(2, 0, 1, 3));
|
|
|
+
|
|
|
+ // [+ay-bx,-ax-by,-az+bw,+aw+bz] + -[cw,cz,cx,cy] = [+ay-bx+cw,-ax-by-cz,-az+bw+cx,+aw+bz-cy]
|
|
|
+ e = _mm_addsub_ps(e, cycxczcw);
|
|
|
+
|
|
|
+ // [-ax-by-cz,+ay-bx+cw,-az+bw+cx,+aw+bz-cy]
|
|
|
+ return Quat(Vec4(_mm_shuffle_ps(e, e, _MM_SHUFFLE(2, 3, 1, 0))));
|
|
|
+#else
|
|
|
+ float lx = inLHS.GetX();
|
|
|
+ float ly = inLHS.GetY();
|
|
|
+ float lz = inLHS.GetZ();
|
|
|
+
|
|
|
+ float rx = inRHS.mValue.GetX();
|
|
|
+ float ry = inRHS.mValue.GetY();
|
|
|
+ float rz = inRHS.mValue.GetZ();
|
|
|
+ float rw = inRHS.mValue.GetW();
|
|
|
+
|
|
|
+ float x = (lx * rw) + ly * rz - lz * ry;
|
|
|
+ float y = -(lx * rz) + ly * rw + lz * rx;
|
|
|
+ float z = (lx * ry) - ly * rx + lz * rw;
|
|
|
+ float w = -(lx * rx) - ly * ry - lz * rz;
|
|
|
+
|
|
|
+ return Quat(x, y, z, w);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
Quat Quat::sRotation(Vec3Arg inAxis, float inAngle)
|
|
|
{
|
|
|
// returns [inAxis * sin(0.5f * inAngle), cos(0.5f * inAngle)]
|
|
@@ -276,13 +330,13 @@ Vec3 Quat::operator * (Vec3Arg inValue) const
|
|
|
{
|
|
|
// Rotating a vector by a quaternion is done by: p' = q * p * q^-1 (q^-1 = conjugated(q) for a unit quaternion)
|
|
|
JPH_ASSERT(IsNormalized());
|
|
|
- return Vec3((*this * Quat(Vec4(inValue, 0)) * Conjugated()).mValue);
|
|
|
+ return Vec3((*this * Quat::sMultiplyImaginary(inValue, Conjugated())).mValue);
|
|
|
}
|
|
|
|
|
|
Vec3 Quat::InverseRotate(Vec3Arg inValue) const
|
|
|
{
|
|
|
JPH_ASSERT(IsNormalized());
|
|
|
- return Vec3((Conjugated() * Quat(Vec4(inValue, 0)) * *this).mValue);
|
|
|
+ return Vec3((Conjugated() * Quat::sMultiplyImaginary(inValue, *this)).mValue);
|
|
|
}
|
|
|
|
|
|
Vec3 Quat::RotateAxisX() const
|