diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp index 39b382a8d3..722f43c113 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/OrthographicCamera.cpp @@ -7,6 +7,7 @@ */ #include "OrthographicCamera.h" +#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp index a10f5fe80b..123ef00333 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/RotateManipulator.cpp @@ -8,7 +8,7 @@ #include "RotateManipulator.h" #include - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp index e1dd7e0563..65915aec65 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/ScaleManipulator.cpp @@ -7,7 +7,7 @@ */ #include "ScaleManipulator.h" - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp index b7c6b87fbf..e20ae5a77e 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/Common/TranslateManipulator.cpp @@ -7,7 +7,7 @@ */ #include "TranslateManipulator.h" - +#include namespace MCommon { diff --git a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp index 6bd8ab7b2f..02aad3aa04 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Rendering/OpenGL2/Source/GLSLShader.cpp @@ -7,6 +7,7 @@ */ #include +#include #include "GLSLShader.h" #include "GraphicsManager.h" #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 56d08760c3..973d8eb460 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp index e1a3e0bbfa..7e7a9ae1c2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Importer/ChunkProcessors.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h index 022a6d5bd7..1b40b3fa2a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/LogWindow/LogWindowPlugin.h @@ -10,6 +10,7 @@ #define __EMSTUDIO_LOGWINDOWPLUGIN_H #if !defined(Q_MOC_RUN) +#include #include "../StandardPluginsConfig.h" #include "../../../../EMStudioSDK/Source/DockWidgetPlugin.h" #endif diff --git a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h index 79e3ef9608..d185a804b8 100644 --- a/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h +++ b/Gems/EMotionFX/Code/MCore/Source/AzCoreConversions.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include // This file is "glue" code to convert math back-forward between MCore and AZ. It also has functions that MCore used to @@ -37,18 +37,6 @@ namespace MCore return RGBAColor(static_cast(azColor.GetR()), static_cast(azColor.GetG()), static_cast(azColor.GetB()), static_cast(azColor.GetA())); } - // Deprecated - AZ_FORCE_INLINE AZ::Quaternion EmfxQuatToAzQuat(const MCore::Quaternion& emfxQuat) - { - return AZ::Quaternion(emfxQuat.x, emfxQuat.y, emfxQuat.z, emfxQuat.w); - } - - // Deprecated - AZ_FORCE_INLINE MCore::Quaternion AzQuatToEmfxQuat(const AZ::Quaternion& azQuat) - { - return MCore::Quaternion(azQuat.GetX(), azQuat.GetY(), azQuat.GetZ(), azQuat.GetW()); - } - AZ_FORCE_INLINE AZ::Transform EmfxTransformToAzTransform(const EMotionFX::Transform& emfxTransform) { AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(emfxTransform.mRotation, emfxTransform.mPosition); @@ -530,91 +518,4 @@ namespace MCore AZ::Vector3ToVector4(m33.GetRow(2), translation.GetZ()), mat.GetRow(3)); } - - // Deprecated. Please use AZ::Transform instead of MCore::Matrix. - MCORE_INLINE AZ::Quaternion MCoreMatrixToQuaternion(const MCore::Matrix& m) - { - const float trace = MMAT(m, 0, 0) + MMAT(m, 1, 1) + MMAT(m, 2, 2); - if (trace > 0.0f /*Math::epsilon*/) - { - const float s = 0.5f / Math::Sqrt(trace + 1.0f); - return AZ::Quaternion((MMAT(m, 1, 2) - MMAT(m, 2, 1)) * s, - (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * s, - (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * s, - 0.25f / s); - } - else - { - if (MMAT(m, 0, 0) > MMAT(m, 1, 1) && MMAT(m, 0, 0) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 0, 0) - MMAT(m, 1, 1) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion(0.25f * s, - (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS, - (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS, - (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * oneOverS); - } - else if (MMAT(m, 1, 1) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 1, 1) - MMAT(m, 0, 0) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion((MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS, - 0.25f * s, - (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS, - (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * oneOverS); - } - else - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 2, 2) - MMAT(m, 0, 0) - MMAT(m, 1, 1)); - const float oneOverS = 1.0f / s; - return AZ::Quaternion((MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS, - (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS, - 0.25f * s, - (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * oneOverS); - } - } - - /* - const float trace = MMAT(m,0,0) + MMAT(m,1,1) + MMAT(m,2,2) + 1.0f; - if (trace > Math::epsilon) - { - const float s = 0.5f / Math::Sqrt(trace); - result.w = 0.25f / s; - result.x = ( MMAT(m,1,2) - MMAT(m,2,1) ) * s; - result.y = ( MMAT(m,2,0) - MMAT(m,0,2) ) * s; - result.z = ( MMAT(m,0,1) - MMAT(m,1,0) ) * s; - } - else - { - if (MMAT(m,0,0) > MMAT(m,1,1) && MMAT(m,0,0) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,0,0) - MMAT(m,1,1) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.z = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.w = (MMAT(m,2,1) - MMAT(m,1,2) ) * oneOverS; - } - else - if (MMAT(m,1,1) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,1,1) - MMAT(m,0,0) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.w = (MMAT(m,2,0) - MMAT(m,0,2) ) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,2,2) - MMAT(m,0,0) - MMAT(m,1,1) ); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.y = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m,1,0) - MMAT(m,0,1) ) * oneOverS; - } - } - */ - } } // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp index 7314e9fe9c..229f67ec0c 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.cpp @@ -2248,27 +2248,6 @@ namespace MCore } - - // simple decompose a matrix into translation and rotation - void Matrix::Decompose(AZ::Vector3* outTranslation, AZ::Quaternion* outRotation) const - { - // make a copy of the matrix - Matrix mat(*this); - - // normalize the basis vectors - mat.SetRight(SafeNormalize(mat.GetRight())); - mat.SetUp(SafeNormalize(mat.GetUp())); - mat.SetForward(SafeNormalize(mat.GetForward())); - - // extract the translation from the matrix - *outTranslation = mat.GetTranslation(); - - // convert the normalized 3x3 rotation part into a AZ::Quaternion - *outRotation = MCore::MCoreMatrixToQuaternion(*this); - } - - - // calculate a rotation matrix from two vectors void Matrix::SetRotationMatrixTwoVectors(const AZ::Vector3& from, const AZ::Vector3& to) { @@ -2365,30 +2344,6 @@ namespace MCore } - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale, AZ::Vector3& shear) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix, scale, shear); - rot = MCore::MCoreMatrixToQuaternion(*this); - } - - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix, scale); - rot = MCore::MCoreMatrixToQuaternion(rotMatrix); - } - - - // - void Matrix::DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot) const - { - Matrix rotMatrix; - DecomposeQRGramSchmidt(translation, rotMatrix); - rot = MCore::MCoreMatrixToQuaternion(rotMatrix); - } // diff --git a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h index 8cb09aa769..4be819bcc1 100644 --- a/Gems/EMotionFX/Code/MCore/Source/Matrix4.h +++ b/Gems/EMotionFX/Code/MCore/Source/Matrix4.h @@ -685,26 +685,11 @@ namespace MCore */ void Frustum(float left, float right, float top, float bottom, float znear, float zfar); - /** - * Decompose a transformation matrix into translation and rotation components. - * The translation part is just the translation part of the matrix. - * The rotation AZ::Quaternion is calculated by normalizing the basis vectors and converting the - * 3x3 rotation part of the matrix to a AZ::Quaternion. - * It is allowed for the matrix to contain scaling. - * The matrix where you call Decompose on remains unchanged. - * @param outTranslation A pointer to a vector where the translation will be written to. - * @param outRotation A pointer to a AZ::Quaternion where the rotation will be written to. - * @note Please keep in mind that nullptr values for the parameters are NOT allowed. - */ - void Decompose(AZ::Vector3* outTranslation, AZ::Quaternion* outRotation) const; // QR Gram-Schmidt decomposition - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale) const; void DecomposeQRGramSchmidt(AZ::Vector3& translation, Matrix& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale, AZ::Vector3& shear) const; - void DecomposeQRGramSchmidt(AZ::Vector3& translation, AZ::Quaternion& rot, AZ::Vector3& scale) const; static Matrix OuterProduct(const AZ::Vector4& column, const AZ::Vector4& row); diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp b/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp deleted file mode 100644 index 2f7db53d2c..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.cpp +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// include required headers -#include "Quaternion.h" -#include - -namespace MCore -{ - // spherical quadratic interpolation - Quaternion Quaternion::Squad(const Quaternion& p, const Quaternion& a, const Quaternion& b, const Quaternion& q, float t) - { - Quaternion q0(p.Slerp(q, t)); - Quaternion q1(a.Slerp(b, t)); - return q0.Slerp(q1, 2.0f * t * (1.0f - t)); - } - - - // returns the approximately normalized linear interpolated result [t must be between 0..1] - Quaternion Quaternion::NLerp(const Quaternion& to, float t) const - { - AZ_Assert(t > -MCore::Math::epsilon && t < (1 + MCore::Math::epsilon), "Expected t to be between 0..1"); - static const float weightCloseToOne = 1.0f - MCore::Math::epsilon; - - // Early out for boundaries (common cases) - if (t < MCore::Math::epsilon) - { - return *this; - } - else if (t > weightCloseToOne) - { - return to; - } - - #if AZ_TRAIT_USE_PLATFORM_SIMD_SSE - __m128 num1, num2, num3, num4, fromVec, toVec; - const float omt = 1.0f - t; - float dot; - - // perform dot product between this quat and the 'to' quat - num4 = _mm_setzero_ps(); // sets sum to zero - fromVec = _mm_loadu_ps(&x); // - toVec = _mm_loadu_ps(&to.x); // - num3 = _mm_mul_ps(fromVec, toVec); // performs multiplication num3 = a[3]*b[3] a[2]*b[2] a[1]*b[1] a[0]*b[0] - num3 = _mm_hadd_ps(num3, num3); // performs horizontal addition - num3= a[3]*b[3]+ a[2]*b[2] a[1]*b[1]+a[0]*b[0] a[3]*b[3]+ a[2]*b[2] a[1]*b[1]+a[0]*b[0] - num4 = _mm_add_ps(num4, num3); // performs vertical addition - num4 = _mm_hadd_ps(num4, num4); - _mm_store_ss(&dot, num4); // store the dot result - - if (dot < 0.0f) - { - t = -t; - } - - // calculate interpolated value - num2 = _mm_load_ps1(&omt); - num3 = _mm_load_ps1(&t); - num4 = _mm_mul_ps(fromVec, num2); // omt * xyzw - num1 = _mm_mul_ps(toVec, num3); // t * to.xyzw - num2 = _mm_add_ps(num1, num4); // interpolated value - - // calculate the square length - num4 = _mm_setzero_ps(); - num3 = _mm_mul_ps(num2, num2); // square length - num1 = _mm_hadd_ps(num3, num3); - num4 = _mm_add_ps(num4, num1); - num3 = _mm_hadd_ps(num4, num4); - //num4 = _mm_rsqrt_ps( num3 ); // length (argh, too inaccurate on some models) - - AZStd::aligned_storage::type numFloatStorage; - float* numFloat = reinterpret_cast(&numFloatStorage); - - _mm_store_ps(numFloat, num3); - const float invLen = Math::InvSqrt(numFloat[0]); - num4 = _mm_load_ps1(&invLen); - - // calc inverse length, which normalizes everything - num1 = _mm_mul_ps(num2, num4); - - _mm_store_ps(numFloat, num1); - return Quaternion(numFloat[0], numFloat[1], numFloat[2], numFloat[3]); - #else - const float omt = 1.0f - t; - const float dot = x * to.x + y * to.y + z * to.z + w * to.w; - if (dot < 0.0f) - { - t = -t; - } - - // calculate the interpolated values - const float newX = (omt * x + t * to.x); - const float newY = (omt * y + t * to.y); - const float newZ = (omt * z + t * to.z); - const float newW = (omt * w + t * to.w); - - // calculate the inverse length - // const float invLen = 1.0f / Math::FastSqrt( newX*newX + newY*newY + newZ*newZ + newW*newW ); - // const float invLen = Math::FastInvSqrt( newX*newX + newY*newY + newZ*newZ + newW*newW ); - const float invLen = Math::InvSqrt(newX * newX + newY * newY + newZ * newZ + newW * newW); - - // return the normalized linear interpolation - return Quaternion(newX * invLen, - newY * invLen, - newZ * invLen, - newW * invLen); - #endif - } - - - - // returns the linear interpolated result [t must be between 0..1] - Quaternion Quaternion::Lerp(const Quaternion& to, float t) const - { - const float omt = 1.0f - t; - const float cosom = x * to.x + y * to.y + z * to.z + w * to.w; - if (cosom < 0.0f) - { - t = -t; - } - - // return the linear interpolation - return Quaternion(omt * x + t * to.x, - omt * y + t * to.y, - omt * z + t * to.z, - omt * w + t * to.w); - } - - - - // quaternion from an axis and angle - Quaternion::Quaternion(const AZ::Vector3& axis, float angle) - { - const float squaredLength = axis.GetLengthSq(); - if (squaredLength > 0.0f) - { - const float halfAngle = angle * 0.5f; - const float sinScale = Math::Sin(halfAngle) / Math::Sqrt(squaredLength); - x = axis.GetX() * sinScale; - y = axis.GetY() * sinScale; - z = axis.GetZ() * sinScale; - w = Math::Cos(halfAngle); - } - else - { - x = y = z = 0.0f; - w = 1.0f; - } - } - - - - // quaternion from a spherical rotation - Quaternion::Quaternion(const AZ::Vector2& spherical, float angle) - { - const float latitude = spherical.GetX(); - const float longitude = spherical.GetY(); - - const float s = Math::Sin(angle / 2.0f); - const float c = Math::Cos(angle / 2.0f); - - const float sin_lat = Math::Sin(latitude); - const float cos_lat = Math::Cos(latitude); - - const float sin_lon = Math::Sin(longitude); - const float cos_lon = Math::Cos(longitude); - - x = s * cos_lat * sin_lon; - y = s * sin_lat; - z = s * sin_lat * cos_lon; - w = c; - } - - - // convert to an axis and angle - void Quaternion::ToAxisAngle(AZ::Vector3* axis, float* angle) const - { - *angle = 2.0f * Math::ACos(w); - - const float sinHalfAngle = Math::Sin(*angle * 0.5f); - if (sinHalfAngle > 0.0f) - { - const float invS = 1.0f / sinHalfAngle; - axis->Set(x * invS, y * invS, z * invS); - } - else - { - axis->Set(0.0f, 1.0f, 0.0f); - *angle = 0.0f; - } - } - - - // converts from unit quaternion to spherical rotation angles - void Quaternion::ToSpherical(AZ::Vector2* spherical, float* angle) const - { - AZ::Vector3 axis; - ToAxisAngle(&axis, angle); - - float longitude; - if (axis.GetX() * axis.GetX() + axis.GetZ() * axis.GetZ() < 0.0001f) - { - longitude = 0.0f; - } - else - { - longitude = Math::ATan2(axis.GetX(), axis.GetZ()); - if (longitude < 0.0f) - { - longitude += Math::twoPi; - } - } - - spherical->SetX(-Math::ASin(axis.GetY())); - spherical->SetY(longitude); - } - - - - // setup the quaternion from a roll, pitch and yaw - Quaternion& Quaternion::SetEuler(float pitch, float yaw, float roll) - { - // METHOD #1: - const float halfYaw = yaw * 0.5f; - const float halfPitch = pitch * 0.5f; - const float halfRoll = roll * 0.5f; - - const float cY = Math::Cos(halfYaw); - const float sY = Math::Sin(halfYaw); - const float cP = Math::Cos(halfPitch); - const float sP = Math::Sin(halfPitch); - const float cR = Math::Cos(halfRoll); - const float sR = Math::Sin(halfRoll); - - x = cY * sP * cR - sY * cP * sR; - y = cY * sP * sR + sY * cP * cR; - z = cY * cP * sR - sY * sP * cR; - w = cY * cP * cR + sY * sP * sR; - - // Normalize(); // we might be able to leave the normalize away, but better safe than not, this is more robust :) - - return *this; - - /* - - // METHOD #2: - Quaternion Qx(Vector3(sP, 0, 0), cP); - Quaternion Qy(Vector3(0, sY, 0), cY); - Quaternion Qz(Vector3(0, 0, sR), cR); - - Quaternion result = Qx * Qy * Qz; - - x = result.x; - y = result.y; - z = result.z; - w = result.w; - - return *this; - */ - } - - - - // convert the quaternion to a matrix - Matrix Quaternion::ToMatrix() const - { - Matrix m; - - const float xx = x * x; - const float xy = x * y, yy = y * y; - const float xz = x * z, yz = y * z, zz = z * z; - const float xw = x * w, yw = y * w, zw = z * w, ww = w * w; - - MMAT(m, 0, 0) = +xx - yy - zz + ww; - MMAT(m, 0, 1) = +xy + zw + xy + zw; - MMAT(m, 0, 2) = +xz - yw + xz - yw; - MMAT(m, 0, 3) = 0.0f; - MMAT(m, 1, 0) = +xy - zw + xy - zw; - MMAT(m, 1, 1) = -xx + yy - zz + ww; - MMAT(m, 1, 2) = +yz + xw + yz + xw; - MMAT(m, 1, 3) = 0.0f; - MMAT(m, 2, 0) = +xz + yw + xz + yw; - MMAT(m, 2, 1) = +yz - xw + yz - xw; - MMAT(m, 2, 2) = -xx - yy + zz + ww; - MMAT(m, 2, 3) = 0.0f; - MMAT(m, 3, 0) = 0.0f; - MMAT(m, 3, 1) = 0.0f; - MMAT(m, 3, 2) = 0.0f; - MMAT(m, 3, 3) = 1.0f; - - return m; - } - - - - // construct the quaternion from a given rotation matrix - Quaternion Quaternion::ConvertFromMatrix(const Matrix& m) - { - Quaternion result; - - const float trace = MMAT(m, 0, 0) + MMAT(m, 1, 1) + MMAT(m, 2, 2); - if (trace > 0.0f /*Math::epsilon*/) - { - const float s = 0.5f / Math::Sqrt(trace + 1.0f); - result.w = 0.25f / s; - result.x = (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * s; - result.y = (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * s; - result.z = (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * s; - } - else - { - if (MMAT(m, 0, 0) > MMAT(m, 1, 1) && MMAT(m, 0, 0) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 0, 0) - MMAT(m, 1, 1) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS; - result.z = (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS; - result.w = (MMAT(m, 1, 2) - MMAT(m, 2, 1)) * oneOverS; - } - else - if (MMAT(m, 1, 1) > MMAT(m, 2, 2)) - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 1, 1) - MMAT(m, 0, 0) - MMAT(m, 2, 2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m, 1, 0) + MMAT(m, 0, 1)) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS; - result.w = (MMAT(m, 2, 0) - MMAT(m, 0, 2)) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt(1.0f + MMAT(m, 2, 2) - MMAT(m, 0, 0) - MMAT(m, 1, 1)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m, 2, 0) + MMAT(m, 0, 2)) * oneOverS; - result.y = (MMAT(m, 2, 1) + MMAT(m, 1, 2)) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m, 0, 1) - MMAT(m, 1, 0)) * oneOverS; - } - } - - /* - const float trace = MMAT(m,0,0) + MMAT(m,1,1) + MMAT(m,2,2) + 1.0f; - if (trace > Math::epsilon) - { - const float s = 0.5f / Math::Sqrt(trace); - result.w = 0.25f / s; - result.x = ( MMAT(m,1,2) - MMAT(m,2,1) ) * s; - result.y = ( MMAT(m,2,0) - MMAT(m,0,2) ) * s; - result.z = ( MMAT(m,0,1) - MMAT(m,1,0) ) * s; - } - else - { - if (MMAT(m,0,0) > MMAT(m,1,1) && MMAT(m,0,0) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,0,0) - MMAT(m,1,1) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = 0.25f * s; - result.y = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.z = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.w = (MMAT(m,2,1) - MMAT(m,1,2) ) * oneOverS; - } - else - if (MMAT(m,1,1) > MMAT(m,2,2)) - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,1,1) - MMAT(m,0,0) - MMAT(m,2,2)); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,1,0) + MMAT(m,0,1) ) * oneOverS; - result.y = 0.25f * s; - result.z = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.w = (MMAT(m,2,0) - MMAT(m,0,2) ) * oneOverS; - } - else - { - const float s = 2.0f * Math::Sqrt( 1.0f + MMAT(m,2,2) - MMAT(m,0,0) - MMAT(m,1,1) ); - const float oneOverS = 1.0f / s; - result.x = (MMAT(m,2,0) + MMAT(m,0,2) ) * oneOverS; - result.y = (MMAT(m,2,1) + MMAT(m,1,2) ) * oneOverS; - result.z = 0.25f * s; - result.w = (MMAT(m,1,0) - MMAT(m,0,1) ) * oneOverS; - } - } - */ - return result; - } - - - // convert a quaternion to euler angles (in degrees) - AZ::Vector3 Quaternion::ToEuler() const - { - /* - // METHOD #1: - - Vector3 euler; - - float matrix[3][3]; - float cx,sx; - float cy,sy,yr; - float cz,sz; - - matrix[0][0] = 1.0 - (2.0 * y * y) - (2.0 * z * z); - matrix[1][0] = (2.0 * x * y) + (2.0 * w * z); - matrix[2][0] = (2.0 * x * z) - (2.0 * w * y); - matrix[2][1] = (2.0 * y * z) + (2.0 * w * x); - matrix[2][2] = 1.0 - (2.0 * x * x) - (2.0 * y * y); - - sy = -matrix[2][0]; - cy = Math::Sqrt(1 - (sy * sy)); - yr = Math::ATan2(sy,cy); - euler.y = yr; - - // avoid divide by zero only where y ~90 or ~270 - if (sy != 1.0 && sy != -1.0) - { - cx = matrix[2][2] / cy; - sx = matrix[2][1] / cy; - euler.x = Math::ATan2(sx,cx); - - cz = matrix[0][0] / cy; - sz = matrix[1][0] / cy; - euler.z = Math::ATan2(sz,cz); - } - else - { - matrix[1][1] = 1.0 - (2.0 * x * x) - (2.0 * z * z); - matrix[1][2] = (2.0 * y * z) - (2.0 * w * x); - cx = matrix[1][1]; - sx = -matrix[1][2]; - euler.x = Math::ATan2(sx,cx); - - cz = 1.0; - sz = 0.0; - euler.z = Math::ATan2(sz,cz); - } - - return euler; - */ - - /* - // METHOD #2: - Matrix mat = ToMatrix(); - - // - float cy = Math::Sqrt(mat.m44[0][0]*mat.m44[0][0] + mat.m44[0][1]*mat.m44[0][1]); - if (cy > 16.0*Math::epsilon) - { - result.x = -atan2(mat.m44[1][2], mat.m44[2][2]); - result.y = -atan2(-mat.m44[0][2], cy); - result.z = -atan2(mat.m44[0][1], mat.m44[0][0]); - } - else - { - result.x = -atan2(-mat.m44[2][1], mat.m44[1][1]); - result.y = -atan2(-mat.m44[0][2], cy); - result.z = 0.0; - } - - return result; - */ - - // METHOD #3 (without conversion to matrix first): - // TODO: safety checks? - float m00 = 1.0f - (2.0f * ((y * y) + z * z)); - float m01 = 2.0f * (x * y + w * z); - - AZ::Vector3 result( - Math::ATan2(2.0f * (y * z + w * x), 1.0f - (2.0f * ((x * x) + (y * y)))), - Math::ATan2(-2.0f * (x * z - w * y), Math::Sqrt((m00 * m00) + (m01 * m01))), - Math::ATan2(m01, m00) - ); - - return result; - } - - float Quaternion::GetEulerZ() const - { - float m00 = 1.0f - (2.0f * ((y * y) + z * z)); - float m01 = 2.0f * (x * y + w * z); - return Math::ATan2(m01, m00); - } - - // returns the spherical interpolated result [t must be between 0..1] - Quaternion Quaternion::Slerp(const Quaternion& to, float t) const - { - float cosom = (x * to.x) + (y * to.y) + (z * to.z) + (w * to.w); - float scale0, scale1, scale1sign = 1.0f; - - if (cosom < 0.0f) - { - scale1sign = -1.0f; - cosom *= -1.0f; - } - - if ((1.0 - cosom) > Math::epsilon) - { - const float omega = Math::ACos(cosom); - const float sinOmega = Math::Sin(omega); - const float oosinom = 1.0f / sinOmega; - scale0 = Math::Sin((1.0f - t) * omega) * oosinom; - scale1 = Math::Sin(t * omega) * oosinom; - } - else - { - scale0 = 1.0f - t; - scale1 = t; - } - - scale1 *= scale1sign; - - return Quaternion(scale0 * x + scale1 * to.x, - scale0 * y + scale1 * to.y, - scale0 * z + scale1 * to.z, - scale0 * w + scale1 * to.w); - } - - - // set as delta rotation - Quaternion Quaternion::CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - Quaternion q; - q.SetAsDeltaRotation(fromVector, toVector); - return q; - } - - - // set as delta rotation but limited - Quaternion Quaternion::CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians) - { - Quaternion q; - q.SetAsDeltaRotation(fromVector, toVector, maxAngleRadians); - return q; - } - - - // set as delta rotation - void Quaternion::SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - // check if we are in parallel or not - const float dot = fromVector.Dot(toVector); - if (dot < 0.99999f) // we have rotated compared to the forward direction - { - const float angleRadians = Math::ACos(dot); - const AZ::Vector3 rotAxis = fromVector.Cross(toVector); - *this = Quaternion(rotAxis, angleRadians); - } - else - { - Identity(); - } - } - - - // set as delta rotation, but limited - void Quaternion::SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians) - { - // check if we are in parallel or not - const float dot = fromVector.Dot(toVector); - if (dot < 0.99999f) // we have rotated compared to the forward direction - { - const float angleRadians = Math::ACos(dot); - const float rotAngle = Min(angleRadians, maxAngleRadians); - const AZ::Vector3 rotAxis = fromVector.Cross(toVector); - *this = Quaternion(rotAxis, rotAngle); - } - else - { - Identity(); - } - } - - - /* - Decompose the rotation on to 2 parts. - 1. Twist - rotation around the "direction" vector - 2. Swing - rotation around axis that is perpendicular to "direction" vector - The rotation can be composed back by - rotation = swing * twist - - has singularity in case of swing_rotation close to 180 degrees rotation. - if the input quaternion is of non-unit length, the outputs are non-unit as well - otherwise, outputs are both unit - */ - void Quaternion::DecomposeSwingTwist(const AZ::Vector3& direction, Quaternion* outSwing, Quaternion* outTwist) const - { - AZ::Vector3 rotAxis(x, y, z); - AZ::Vector3 p = Projected(rotAxis, direction); // return projection v1 on to v2 (parallel component) - outTwist->Set(p.GetX(), p.GetY(), p.GetZ(), w); - outTwist->Normalize(); - *outSwing = *this * outTwist->Conjugated(); - } - - - // rotate the current quaternion and renormalize it - void Quaternion::RotateFromTo(const AZ::Vector3& fromVector, const AZ::Vector3& toVector) - { - *this = CreateDeltaRotation(fromVector, toVector) * *this; - Normalize(); - } -} // namespace MCore - diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.h b/Gems/EMotionFX/Code/MCore/Source/Quaternion.h deleted file mode 100644 index bbee1d8265..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -#pragma once - -// include required headers -#include -#include -#include "StandardHeaders.h" -#include "FastMath.h" -#include "Vector.h" -#include "Matrix4.h" -#include "Algorithms.h" - - -namespace MCore -{ - /** - * Depracated. Please use AZ::Quaternion instead. - * The quaternion class in MCore. - * Quaternions are mostly used to represent rotations in 3D applications. - * The advantages of quaternions over matrices are that they take up less space and that interpolation between - * two quaternions is easier to perform. Instead of a 3x3 rotation matrix, which is 9 floats or doubles, a quaternion - * only uses 4 floats or doubles. This template/class provides you with methods to perform all kind of operations on - * these quaternions, from interpolation to conversion to matrices and other rotation representations. - */ - class MCORE_API Quaternion - { - public: - AZ_TYPE_INFO(MCore::Quaternion, "{1807CD22-EBB5-45E8-8113-3B1DABB53F12}") - - /** - * Default constructor. Sets x, y and z to 0 and w to 1. - */ - MCORE_INLINE Quaternion() - : x(0.0f) - , y(0.0f) - , z(0.0f) - , w(1.0f) {} - - /** - * Constructor which sets the x, y, z and w. - * @param xVal The value of x. - * @param yVal The value of y. - * @param zVal The value of z. - * @param wVal The value of w. - */ - MCORE_INLINE Quaternion(float xVal, float yVal, float zVal, float wVal) - : x(xVal) - , y(yVal) - , z(zVal) - , w(wVal) {} - - /** - * Copy constructor. Copies the x, y, z, w values from the other quaternion. - * @param other The quaternion to copy the attributes from. - */ - MCORE_INLINE Quaternion(const Quaternion& other) - : x(other.x) - , y(other.y) - , z(other.z) - , w(other.w) {} - - /** - * Constructor which creates a quaternion from a pitch, yaw and roll. - * @param pitch Rotation around the x-axis, in radians. - * @param yaw Rotation around the y-axis, in radians. - * @param roll Rotation around the z-axis, in radians. - */ - MCORE_INLINE Quaternion(float pitch, float yaw, float roll) { SetEuler(pitch, yaw, roll); } - - /** - * Constructor which takes a matrix as input parameter. - * This converts the rotation of the specified matrix into a quaternion. Please keep in mind that the matrix may NOT contain - * any scaling, so if it does, please normalize your matrix first! - * @param matrix The matrix to initialize the quaternion from. - */ - MCORE_INLINE Quaternion(const Matrix& matrix) { FromMatrix(matrix); } - - /** - * Constructor which creates a quaternion from a spherical rotation. - * @param spherical The spherical coordinates in radians, which creates an axis to rotate around. - * @param angle The angle to rotate around this axis. - */ - Quaternion(const AZ::Vector2& spherical, float angle); - - /** - * Constructor which creates a quaternion from an axis and angle. - * @param axis The axis to rotate around. - * @param angle The angle in radians to rotate around the given axis. - */ - Quaternion(const AZ::Vector3& axis, float angle); - - /** - * Set the quaternion x/y/z/w component values. - * @param vx The value of x. - * @param vy The value of y. - * @param vz The value of z. - * @param vw The value of w. - */ - MCORE_INLINE void Set(float vx, float vy, float vz, float vw) { x = vx; y = vy; z = vz; w = vw; } - - /** - * Calculates the square length of the quaternion. - * @result The square length (length*length). - */ - MCORE_INLINE float SquareLength() const { return (x * x + y * y + z * z + w * w); } - - /** - * Calculates the length of the quaternion. - * It's safe, since it prevents a division by 0. - * @result The length of the quaternion. - */ - MCORE_INLINE float Length() const; - - /** - * Performs a dot product on the quaternions. - * @param q The quaternion to multiply (dot product) this quaternion with. - * @result The quaternion which is the result of the dot product. - */ - MCORE_INLINE float Dot(const Quaternion& q) const { return (x * q.x + y * q.y + z * q.z + w * q.w); } - - /** - * Normalize the quaternion. - * @result The normalized quaternion. It modifies itself, so no new quaternion is returned. - */ - MCORE_INLINE Quaternion& Normalize(); - - /** - * Sets the quaternion to identity. Where x, y and z are set to 0 and w is set to 1. - * @result The quaternion, now set to identity. - */ - MCORE_INLINE Quaternion& Identity() { x = 0.0f; y = 0.0f; z = 0.0f; w = 1.0f; return *this; } - - /** - * Calculate the inversed version of this quaternion. - * @result The inversed version of this quaternion. - */ - MCORE_INLINE Quaternion& Inverse() { const float len = 1.0f / SquareLength(); x = -x * len; y = -y * len; z = -z * len; w = w * len; return *this; } - - /** - * Conjugate this quaternion. - * @result Returns itself Conjugated. - */ - MCORE_INLINE Quaternion& Conjugate() { x = -x; y = -y; z = -z; return *this; } - - /** - * Calculate the inversed version of this quaternion. - * @result The inversed version of this quaternion. - */ - MCORE_INLINE Quaternion Inversed() const { const float len = 1.0f / SquareLength(); return Quaternion(-x * len, -y * len, -z * len, w * len); } - - /** - * Returns the normalized version of this quaternion. - * @result The normalized version of this quaternion. - */ - MCORE_INLINE Quaternion Normalized() const { Quaternion result(*this); result.Normalize(); return result; } - - /** - * Return the conjugated version of this quaternion. - * @result The conjugated version of this quaternion. - */ - MCORE_INLINE Quaternion Conjugated() const { return Quaternion(-x, -y, -z, w); } - - /** - * Calculate the exponent of this quaternion. - * @result The resulting quaternion of the exp. - */ - MCORE_INLINE Quaternion Exp() const { const float r = Math::Sqrt(x * x + y * y + z * z); const float expW = Math::Exp(w); const float s = (r >= 0.00001f) ? expW* Math::Sin(r) / r : 0.0f; return Quaternion(s * x, s * y, s * z, expW * Math::Cos(r)); } - - /** - * Calculate the log of the quaternion. - * @result The resulting quaternion of the log. - */ - MCORE_INLINE Quaternion LogN() const { const float r = Math::Sqrt(x * x + y * y + z * z); float t = (r > 0.00001f) ? Math::ATan2(r, w) / r : 0.0f; return Quaternion(t * x, t * y, t * z, 0.5f * Math::Log(SquareLength())); } - - /** - * Calculate and get the right basis vector. - * @result The basis vector pointing to the right. This assumes x+ points to the right. - */ - MCORE_INLINE AZ::Vector3 CalcRightAxis() const; - - /** - * Calculate and get the up basis vector. - * @result The basis vector pointing upwards. This assumes z+ points up. - */ - MCORE_INLINE AZ::Vector3 CalcUpAxis() const; - - /** - * Calculate and get the forward basis vector. - * @result The basis vector pointing forward. This assumes y+ points forward, into the depth. - */ - MCORE_INLINE AZ::Vector3 CalcForwardAxis() const; - - /** - * Initialize the current quaternion from a specified matrix. - * Please note that the matrix may not contain any scaling! - * So make sure the matrix has been normalized before, if it contains any scale. - * @param m The matrix to initialize the quaternion from. - */ - MCORE_INLINE void FromMatrix(const Matrix& m) { *this = Quaternion::ConvertFromMatrix(m); } - - /** - * Setup the quaternion from a pitch, yaw and roll. - * @param pitch The rotation around the x-axis, in radians. - * @param yaw The rotation around the y-axis, in radians. - * @param roll The rotation around the z-axis in radians. - * @result The quaternion, now initialized with the given pitch, yaw, roll rotation. - */ - Quaternion& SetEuler(float pitch, float yaw, float roll); - - /** - * Convert the quaternion to an axis and angle. Which represents a rotation of the resulting angle around the resulting axis. - * @param axis Pointer to the vector to store the axis in. - * @param angle Pointer to the variable to store the angle in (will be in radians). - */ - void ToAxisAngle(AZ::Vector3* axis, float* angle) const; - - /** - * Convert the quaternion to a spherical rotation. - * @param spherical A pointer to the 2D vector to store the spherical coordinates in radians, which build the axis. - * @param angle The pointer to the variable to store the angle around this axis in radians. - */ - void ToSpherical(AZ::Vector2* spherical, float* angle) const; - - /** - * Extract the euler angles in radians. - * The x component of the resulting vector represents the rotation around the x-axis (pitch). - * The y component results the rotation around the y-axis (yaw) and the z component represents - * the rotation around the z-axis (roll). - * @result The 3D vector containing the euler angles in radians, around each axis. - */ - AZ::Vector3 ToEuler() const; - - /** - * Returns the angle of rotation about the z axis. This is same as - * the z component of the vector returned by the ToEuler method. It - * is just more efficient to call this when one is interested only in rotation about the z axis. - * @result The angle of rotation about z axis in radians. - */ - float GetEulerZ() const; - - /** - * Convert this quaternion into a matrix. - * @result The matrix representing the rotation of this quaternion. - */ - Matrix ToMatrix() const; - - /** - * Convert a matrix into a quaternion. - * Please keep in mind that the specified matrix may NOT contain any scaling! - * So make sure the matrix has been normalized before, if it contains any scale. - * @param m The matrix to extract the rotation from. - * @result The quaternion, now containing the rotation of the given matrix, in quaternion form. - */ - static Quaternion ConvertFromMatrix(const Matrix& m); - - /** - * Create a delta rotation that rotates one vector onto another vector. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @result The delta rotation quaternion. - */ - static Quaternion CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Create a delta rotation that rotates one vector onto another vector. - * If the angle is bigger than the max allowed angle that is specified it will rotate with an angle of the maximum specified angle. - * So if the angle between the vectors is 40 degrees and you maxAngleRadians equals 10 degrees (in radians) it will only rotate 10 degrees. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @param maxAngleRadians The maximum rotation angle on the plane defined by the two vectors. This cannot be more than Math::pi (180 degrees). - * @result The delta rotation quaternion. - */ - static Quaternion CreateDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians); - - /** - * Init this quaternion as a delta rotation that rotates one vector onto another vector. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - */ - void SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Init this quaternion as a delta rotation that rotates one vector onto another vector. - * If the angle is bigger than the max allowed angle that is specified it will rotate with an angle of the maximum specified angle. - * So if the angle between the vectors is 40 degrees and you maxAngleRadians equals 10 degrees (in radians) it will only rotate 10 degrees. - * @param fromVector The normalized vector to start from. This must be normalized! - * @param toVector The normalized vector to rotate towards. This must be normalized as well! - * @param maxAngleRadians The maximum rotation angle on the plane defined by the two vectors. This cannot be more than Math::pi (180 degrees). - */ - void SetAsDeltaRotation(const AZ::Vector3& fromVector, const AZ::Vector3& toVector, float maxAngleRadians); - - /** - * Rotate this current quaternion using a given delta that is calculated from two vectors. - * The rotation axis used is the cross product between the from and to vector. The rotation angle is the angle between these two vectors. - * @param fromVector The current direction vector, must be normalized. - * @param toVector The desired new direction vector, must be normalized. - */ - void RotateFromTo(const AZ::Vector3& fromVector, const AZ::Vector3& toVector); - - /** - * Decompose into swing and twist. - * The original rotation quat can be reassembled by doing swing * twist. - * @param direction The direction vector to get the twist from. - * @param outSwing This will contain the swing quaternion. - * @param outTwist This will contain the twist quaternion. - */ - void DecomposeSwingTwist(const AZ::Vector3& direction, Quaternion* outSwing, Quaternion* outTwist) const; - - /** - * Linear interpolate between this and another quaternion. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - Quaternion Lerp(const Quaternion& to, float t) const; - - /** - * Linear interpolate between this and another quaternion, and normalize afterwards. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The normalized quaternion at the given time in the interpolation process. - */ - Quaternion NLerp(const Quaternion& to, float t) const; - - /** - * Spherical Linear interpolate between this and another quaternion. - * @param to The quaternion to interpolate towards. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - Quaternion Slerp(const Quaternion& to, float t) const; - - /** - * Spherical cubic interpolate. - * @param p The first quaternion. - * @param a The second quaternion. - * @param b The third quaternion. - * @param q The fourth quaternion. - * @param t The time value, between 0 and 1. - * @result The quaternion at the given time in the interpolation process. - */ - static Quaternion Squad(const Quaternion& p, const Quaternion& a, const Quaternion& b, const Quaternion& q, float t); - - // operators - MCORE_INLINE const Quaternion& operator=(const Matrix& m) { FromMatrix(m); return *this; } - MCORE_INLINE const Quaternion& operator=(const Quaternion& other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; } - MCORE_INLINE Quaternion operator-() const { return Quaternion(-x, -y, -z, -w); } - MCORE_INLINE const Quaternion& operator+=(const Quaternion& q) { x += q.x; y += q.y; z += q.z; w += q.w; return *this; } - MCORE_INLINE const Quaternion& operator-=(const Quaternion& q) { x -= q.x; y -= q.y; z -= q.z; w -= q.w; return *this; } - MCORE_INLINE const Quaternion& operator*=(const Quaternion& q); - MCORE_INLINE const Quaternion& operator*=(float f) { x *= f; y *= f; z *= f; w *= f; return *this; } - //MCORE_INLINE const Quaternion& operator*=(double f) { x*=f; y*=f; z*=f; w*=f; return *this; } - MCORE_INLINE bool operator==(const Quaternion& q) const { return ((q.x == x) && (q.y == y) && (q.z == z) && (q.w == w)); } - MCORE_INLINE bool operator!=(const Quaternion& q) const { return ((q.x != x) || (q.y != y) || (q.z != z) || (q.w != w)); } - - //MCORE_INLINE float& operator[](int32 row) { return ((float*)&x)[row]; } - MCORE_INLINE operator float*() { return (float*)&x; } - MCORE_INLINE operator const float*() const { return (const float*)&x; } - - MCORE_INLINE AZ::Vector3 operator*(const AZ::Vector3& p) const; // multiply a vector by a quaternion - MCORE_INLINE Quaternion operator/(const Quaternion& q) const; // returns the ratio of two quaternions - - // attributes - float x, y, z, w; - }; - - - // operators - MCORE_INLINE Quaternion operator*(const Quaternion& a, float f) { return Quaternion(a.x * f, a.y * f, a.z * f, a.w * f); } - MCORE_INLINE Quaternion operator*(float f, const Quaternion& b) { return Quaternion(f * b.x, f * b.y, f * b.z, f * b.w); } - //MCORE_INLINE Quaternion operator*(const Quaternion& a, double f) { return Quaternion(a.x*f, a.y*f, a.z*f, a.w*f); } - //MCORE_INLINE Quaternion operator*(double f, const Quaternion& b) { return Quaternion(f*b.x, f*b.y, f*b.z, f*b.w); } - MCORE_INLINE Quaternion operator+(const Quaternion& a, const Quaternion& b) { return Quaternion(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); } - MCORE_INLINE Quaternion operator-(const Quaternion& a, const Quaternion& b) { return Quaternion(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); } - MCORE_INLINE Quaternion operator*(const Quaternion& a, const Quaternion& b) { return Quaternion(a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y, a.w * b.y + a.y * b.w + a.z * b.x - a.x * b.z, a.w * b.z + a.z * b.w + a.x * b.y - a.y * b.x, a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z); } - - // include the inline code -#include "Quaternion.inl" -} // namespace MCore diff --git a/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl b/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl deleted file mode 100644 index c89f497a1e..0000000000 --- a/Gems/EMotionFX/Code/MCore/Source/Quaternion.inl +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) Contributors to the Open 3D Engine Project. - * For complete copyright and license terms please see the LICENSE at the root of this distribution. - * - * SPDX-License-Identifier: Apache-2.0 OR MIT - * - */ - -// multiply a vector by a quaternion -MCORE_INLINE AZ::Vector3 Quaternion::operator * (const AZ::Vector3& p) const -{ - Quaternion v(p.GetX(), p.GetY(), p.GetZ(), 0.0f); - v = *this* v* this->Conjugated(); - return AZ::Vector3(v.x, v.y, v.z); -} - - - -// returns the ratio of two quaternions -MCORE_INLINE Quaternion Quaternion::operator / (const Quaternion& q) const -{ - Quaternion t((*this) * -q); - Quaternion s((-q) * (-q)); - t *= (1.0f / s.w); - return t; -} - - - -// calculates the length of the quaternion -MCORE_INLINE float Quaternion::Length() const -{ - const float sqLen = SquareLength(); - return Math::SafeSqrt(sqLen); -} - - -// normalizes the quaternion using approximation -MCORE_INLINE Quaternion& Quaternion::Normalize() -{ - // calculate 1.0 / length - // const float ooLen = 1.0f / Math::FastSqrt(x*x + y*y + z*z + w*w); - // const float ooLen = Math::FastInvSqrt(x*x + y*y + z*z + w*w); - const float squareValue = x * x + y * y + z * z + w * w; - const float ooLen = Math::InvSqrt(squareValue); - - x *= ooLen; - y *= ooLen; - z *= ooLen; - w *= ooLen; - - return *this; -} - - -// get the right axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcRightAxis() const -{ - return AZ::Vector3(1.0f - 2.0f * y * y - 2.0f * z * z, - 2.0f * x * y + 2.0f * z * w, - 2.0f * x * z - 2.0f * y * w); -} - - -// get the forward axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcForwardAxis() const -{ - return AZ::Vector3(2.0f * x * y - 2.0f * z * w, - 1.0f - 2.0f * x * x - 2.0f * z * z, - 2.0f * y * z + 2.0f * x * w); -} - - -// get the up axis -MCORE_INLINE AZ::Vector3 Quaternion::CalcUpAxis() const -{ - return AZ::Vector3(2.0f * x * z + 2.0f * y * w, - 2.0f * y * z - 2.0f * x * w, - 1.0f - 2.0f * x * x - 2.0f * y * y); -} - - -// multiply by a quaternion -MCORE_INLINE const Quaternion& Quaternion::operator*=(const Quaternion& q) -{ - const float vx = w * q.x + x * q.w + y * q.z - z * q.y; - const float vy = w * q.y + y * q.w + z * q.x - x * q.z; - const float vz = w * q.z + z * q.w + x * q.y - y * q.x; - const float vw = w * q.w - x * q.x - y * q.y - z * q.z; - x = vx; - y = vy; - z = vz; - w = vw; - return *this; -} - diff --git a/Gems/EMotionFX/Code/MCore/mcore_files.cmake b/Gems/EMotionFX/Code/MCore/mcore_files.cmake index b63c9e1bae..b0d8a67ccd 100644 --- a/Gems/EMotionFX/Code/MCore/mcore_files.cmake +++ b/Gems/EMotionFX/Code/MCore/mcore_files.cmake @@ -107,9 +107,6 @@ set(FILES Source/PlaneEq.cpp Source/PlaneEq.h Source/PlaneEq.inl - Source/Quaternion.cpp - Source/Quaternion.h - Source/Quaternion.inl Source/Random.cpp Source/Random.h Source/Ray.cpp diff --git a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp index 43422dd654..041cc9e862 100644 --- a/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp +++ b/Gems/EMotionFX/Code/Tests/EmotionFXMathLibTests.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -25,7 +24,6 @@ protected: { m_azNormalizedVector3_a = AZ::Vector3(s_x1, s_y1, s_z1); m_azNormalizedVector3_a.Normalize(); - m_emQuaternion_a = MCore::Quaternion(m_azNormalizedVector3_a, s_angle_a); m_azQuaternion_a = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3_a, s_angle_a); } @@ -55,26 +53,6 @@ protected: return true; } - bool EmfxQuaternionCompareExact(MCore::Quaternion& quaternion, float x, float y, float z, float w) - { - if (quaternion.x != x) - { - return false; - } - if (quaternion.y != y) - { - return false; - } - if (quaternion.z != z) - { - return false; - } - if (quaternion.w != w) - { - return false; - } - return true; - } bool AZQuaternionCompareClose(AZ::Quaternion& quaternion, float x, float y, float z, float w, float tolerance) { @@ -131,26 +109,6 @@ protected: return true; } - bool AZEMQuaternionsAreEqual(AZ::Quaternion& azQuaternion, const MCore::Quaternion& emQuaternion) - { - if (AZQuaternionCompareExact(azQuaternion, emQuaternion.x, emQuaternion.y, - emQuaternion.z, emQuaternion.w)) - { - return true; - } - return false; - } - - bool AZEMQuaternionsAreClose(AZ::Quaternion& azQuaternion, const MCore::Quaternion& emQuaternion, const float tolerance) - { - if (AZQuaternionCompareClose(azQuaternion, emQuaternion.x, emQuaternion.y, - emQuaternion.z, emQuaternion.w, tolerance)) - { - return true; - } - return false; - } - static const float s_toleranceHigh; static const float s_toleranceMedium; static const float s_toleranceLow; @@ -161,7 +119,6 @@ protected: static const float s_angle_a; AZ::Vector3 m_azNormalizedVector3_a; AZ::Quaternion m_azQuaternion_a; - MCore::Quaternion m_emQuaternion_a; }; const float EmotionFXMathLibTests::s_toleranceHigh = 0.00001f; @@ -174,18 +131,6 @@ const float EmotionFXMathLibTests::s_y1 = 0.3f; const float EmotionFXMathLibTests::s_z1 = 0.4f; const float EmotionFXMathLibTests::s_angle_a = 0.5f; - -/////////////////////////////////////////////////////////////////////////////// - - -// MCore::Quaternion: Test identity values -TEST_F(EmotionFXMathLibTests, QuaternionIdentity_Identity_Success) -{ - MCore::Quaternion test(0.1f, 0.2f, 0.3f, 0.4f); - test.Identity(); - ASSERT_TRUE(test == MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); -} - ////////////////////////////////////////////////////////////////// //Getting and setting of Quaternions ////////////////////////////////////////////////////////////////// @@ -196,52 +141,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionGet_Elements_Success) ASSERT_TRUE(AZQuaternionCompareExact(test, 0.1f, 0.2f, 0.3f, 0.4f)); } -// Compare equivalent normalized quaternions between systems -TEST_F(EmotionFXMathLibTests, AZEMQuaternionNormalizeEquivalent_Success) -{ - AZ::Quaternion azTest(0.1f, 0.2f, 0.3f, 0.4f); - MCore::Quaternion emTest(0.1f, 0.2f, 0.3f, 0.4f); - azTest.Normalize(); - emTest.Normalize(); - - ASSERT_TRUE(AZQuaternionCompareClose(azTest, emTest.x, emTest.y, emTest.z, emTest.w, s_toleranceMedium)); -} - -/////////////////////////////////////////////////////////////////////////////// -// Axis Angle -/////////////////////////////////////////////////////////////////////////////// - -// Compare setting a quaternion using axis and angle -TEST_F(EmotionFXMathLibTests, AZEMQuaternionConversion_SetToAxisAngleEquivalent_Success) -{ - MCore::Quaternion emQuaternion(m_azNormalizedVector3_a, s_angle_a); - AZ::Quaternion azQuaternion = AZ::Quaternion::CreateFromAxisAngle(m_azNormalizedVector3_a, s_angle_a); - - ASSERT_TRUE(AZQuaternionCompareClose(azQuaternion, emQuaternion.x, emQuaternion.y, emQuaternion.z, emQuaternion.w, s_toleranceLow)); -} - -// Compare equivalent conversions quaternions -> (axis, angle) between systems -TEST_F(EmotionFXMathLibTests, AZEMQuaternionConversion_ToAxisAngleEquivalent_Success) -{ - //populate Quaternions with same data - MCore::Quaternion emTest = m_emQuaternion_a; - AZ::Quaternion azTest(emTest.x, emTest.y, emTest.z, emTest.w); - - AZ::Vector3 emAxis; - float emAngle; - emTest.ToAxisAngle(&emAxis, &emAngle); - - AZ::Vector3 azAxis; - float azAngle; - AZ::ConvertQuaternionToAxisAngle(azTest, azAxis, azAngle); - - bool same = AZ::IsClose(azAngle, emAngle, s_toleranceLow) && - AZVector3CompareClose(azAxis, emAxis, s_toleranceLow); - - ASSERT_TRUE(same); -} - - /////////////////////////////////////////////////////////////////////////////// //Basic rotations /////////////////////////////////////////////////////////////////////////////// @@ -420,18 +319,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternion_EulerGetSet3ComponentAxisCompareTrans ASSERT_TRUE(same); } - -// EM Quaternion to Euler test -TEST_F(EmotionFXMathLibTests, EMQuaternionConversion_ToEulerEquivalent_Success) -{ - AZ::Vector3 eulerIn(0.1f, 0.2f, 0.3f); - MCore::Quaternion test; - test.SetEuler(eulerIn.GetX(), eulerIn.GetY(), eulerIn.GetZ()); - AZ::Vector3 eulerOut = test.ToEuler(); - - ASSERT_TRUE(AZVector3CompareClose(eulerOut, 0.1f, 0.2f, 0.3f, s_toleranceHigh)); -} - // AZ Quaternion to Euler test //only way to test Quaternions sameness is to apply it to a vector and measure result TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToEulerEquivalent_Success) @@ -456,41 +343,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToEulerEquivalent_Success) ASSERT_TRUE(AZVector3CompareClose(eulerOut1, eulerOut2, s_toleranceReallyLow)); } -/////////////////////////////////////////////////////////////////////////////// -//Quaternion order test -//determines that ordering is same between systems. -/////////////////////////////////////////////////////////////////////////////// -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_OrderTest_Success) -{ - AZ::Vector3 axis = AZ::Vector3(1.0f, 0.7f, 0.3f); - axis.Normalize(); - AZ::Quaternion azQuaternion1 = AZ::Quaternion::CreateFromAxisAngle(axis, AZ::Constants::HalfPi); - - AZ::Vector3 axis2 = AZ::Vector3(0.2f, 0.5f, 0.9f); - axis2.Normalize(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion::CreateFromAxisAngle(axis2, AZ::Constants::HalfPi); - - MCore::Quaternion emQuaternion1(azQuaternion1.GetX(), azQuaternion1.GetY(), azQuaternion1.GetZ(), azQuaternion1.GetW()); - MCore::Quaternion emQuaternion2(azQuaternion2.GetX(), azQuaternion2.GetY(), azQuaternion2.GetZ(), azQuaternion2.GetW()); - - AZ::Quaternion azQuaterionOut = azQuaternion1 * azQuaternion2; - AZ::Quaternion azQuaterionOut2 = azQuaternion2 * azQuaternion1; - MCore::Quaternion emQuaterionOut = emQuaternion1 * emQuaternion2; - - AZ::Vector3 azVertexIn(0.1f, 0.2f, 0.3f); - - AZ::Vector3 azVertexOut, azVertexOut2; - AZ::Vector3 emVertexOut; - - azVertexOut = azQuaterionOut.TransformVector(azVertexIn); - azVertexOut2 = azQuaterionOut2.TransformVector(azVertexIn); - emVertexOut = emQuaterionOut * azVertexIn; - - bool same = AZVector3CompareClose(emVertexOut, azVertexOut.GetX(), azVertexOut.GetY(), azVertexOut.GetZ(), s_toleranceMedium); - ASSERT_TRUE(same); -} - - /////////////////////////////////////////////////////////////////////////////// // Quaternion Matrix /////////////////////////////////////////////////////////////////////////////// @@ -616,225 +468,6 @@ TEST_F(EmotionFXMathLibTests, AZQuaternionConversion_ToMatrix_Success) ASSERT_TRUE(AZ::IsClose(azMatrix.GetElement(3, 3), 1.0f, s_toleranceReallyLow)); } -/////////////////////////////////////////////////////////////////////////////// -// AZEMQuaternion Compare Output tests -// Determines the AZ and MCore quaternion outputs are same/close after same math operations. -/////////////////////////////////////////////////////////////////////////////// -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorAddEquivalent_Success) -{ - // Quaternion test: operator '+' and operator '+=' - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion = azQuaternion + azQuaternion2; - azQuaternion2 += azQuaternion; - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion = emQuaternion + emQuaternion2; - emQuaternion2 += emQuaternion; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '+'"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '+='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorSubtractEquivalent_Success) -{ - // Quaternion test: operator '-' and operator '-=' - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion = azQuaternion - azQuaternion2; - azQuaternion2 -= azQuaternion; - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion = emQuaternion - emQuaternion2; - emQuaternion2 -= emQuaternion; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '-'"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '-='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_CompareOperatorMultiplyHasSimilarOutput_Success) -{ - // Quaternion test: operator '*' and operator '*=' with another quaternion, vector3 and float - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - AZ::Quaternion azQuaternion3 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - azQuaternion.Normalize(); - azQuaternion2.Normalize(); - azQuaternion3.Normalize(); - azQuaternion = azQuaternion * azQuaternion2; - azQuaternion2 *= azQuaternion; - azQuaternion3 *= 0.5f; - AZ::Vector3 aztestVec3 = azQuaternion2.TransformVector(m_azNormalizedVector3_a); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f); - MCore::Quaternion emQuaternion3 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f); - emQuaternion.Normalize(); - emQuaternion2.Normalize(); - emQuaternion3.Normalize(); - emQuaternion = emQuaternion * emQuaternion2; - emQuaternion2 *= emQuaternion; - emQuaternion3 *= 0.5f; - AZ::Vector3 emtestVec3 = emQuaternion2 * m_azNormalizedVector3_a; - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*' with another quaternion"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*=' with another quaternion"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion3, emQuaternion3, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*=' with a float value"; - EXPECT_TRUE(AZVector3CompareClose(aztestVec3, emtestVec3, s_toleranceLow)) << "AZ/MCore Quaternions should have similar output with operator '*' with a vector3"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_EquivalentOperatorsHasSameOutput_Success) -{ - // Testing Quaternion == Quaternion and operator!= - bool azCheck = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() == AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - bool azCheck2 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() == AZ::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).GetNormalized(); - bool azCheck3 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() != AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - bool azCheck4 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized() != AZ::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).GetNormalized(); - - bool emCheck = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() == MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - bool emCheck2 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() == MCore::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).Normalized(); - bool emCheck3 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() != MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - bool emCheck4 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized() != MCore::Quaternion(0.1000001f, 0.2000001f, 0.3000001f, 1.0f).Normalized(); - - EXPECT_TRUE(azCheck == emCheck) << "AZ/MCore Quaternions should have same output of 'true' with operator '=='"; - EXPECT_TRUE(azCheck2 == emCheck2) << "AZ/MCore Quaternions should have same output of 'false' with operator '=='"; - EXPECT_TRUE(azCheck3 == emCheck3) << "AZ/MCore Quaternions should have same output of 'false' with operator '!='"; - EXPECT_TRUE(azCheck4 == emCheck4) << "AZ/MCore Quaternions should have same output of 'true' with operator '!='"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_InverseHasSimilarOutput_Success) -{ - // Test quaternions inverse method - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetInverseFull(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetInverseFull(); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Inverse(); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Inverse(); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Inverse output"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar Inverse output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_ConjugateHasSimilarOutput_Success) -{ - // Test quaternion conjugate method - AZ::Quaternion azQuaternion = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetConjugate(); - AZ::Quaternion azQuaternion2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetConjugate(); - - MCore::Quaternion emQuaternion = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Conjugate(); - MCore::Quaternion emQuaternion2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Conjugate(); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion, emQuaternion, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Conjugate output"; - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternion2, emQuaternion2, s_toleranceLow)) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar Conjugate output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameSquareLengthOutput_Success) -{ - // Test AZ and MCore quaternions to have similar square length - float azTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetLengthSq(); - float azTest2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetLengthSq(); - - float emTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().SquareLength(); - float emTest2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().SquareLength(); - - EXPECT_TRUE(AZ::GetAbs(azTest - emTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar square length output"; - EXPECT_TRUE(AZ::GetAbs(azTest2 - emTest2) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar square length output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameLengthOutput_Success) -{ - // Test AZ and MCore quaternions to have similar length - // AZ GetLength, GetLengthApprox, GetLength all returns sqrtf(Dot(*this)) - float azTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().GetLength(); - float azTest2 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().GetLength(); - - float emTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Length(); - float emTest2 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Length(); - - EXPECT_TRUE(AZ::GetAbs(azTest - emTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar length output"; - EXPECT_TRUE(AZ::GetAbs(azTest2 - emTest2) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar length output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSameDotProductOutput_Success) -{ - // Test AZ and MCore quaternions to have similar dot product - float azDotTest = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f)); - float azDotTest2 = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - float azDotTest3 = AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).GetNormalized().Dot(AZ::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - - float emDotTest = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Dot(MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f)); - float emDotTest2 = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized().Dot(MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - float emDotTest3 = MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f).Normalized().Dot(MCore::Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); - - EXPECT_TRUE(AZ::GetAbs(azDotTest - emDotTest) < s_toleranceLow) << "AZ/MCore Quaternions should have similar dot product output"; - EXPECT_TRUE(AZ::GetAbs(azDotTest2 - emDotTest2) < s_toleranceLow) << "AZ/MCore Quaternions should have similar dot product output"; - EXPECT_TRUE(AZ::GetAbs(azDotTest3 - emDotTest3) < s_toleranceLow) << "AZ/MCore Quaternion(0.0f, 0.0f, 0.0f, 1.0f) should have similar dot product output"; -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar Linear Interpolated quaternions - float testCases[6] = { 0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f }; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.Lerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.Lerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Lerp output with given float: " << testVal; - } -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarNLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar Linear Interpolated and then normalized quaternions - float testCases[6] = {0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f}; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.NLerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.NLerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar NLerp output with given float: " << testVal; - } -} - -TEST_F(EmotionFXMathLibTests, AZEMQuaternion_HasSimilarSLerpOutput_Success) -{ - // Test AZ and MCore quaternions to have similar spherical Linear Interpolated quaternions - float testCases[6] = { 0.0f, 0.1f, 0.25f, 0.5f, 0.8f, 1.0f }; - for (float testVal : testCases) - { - AZ::Quaternion azQuaternionA = AZ::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionB = AZ::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).GetNormalized(); - AZ::Quaternion azQuaternionC = azQuaternionA.Slerp(azQuaternionB, testVal); - - MCore::Quaternion emQuaternionA = MCore::Quaternion(0.1f, 0.2f, 0.3f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionB = MCore::Quaternion(0.8f, 0.7f, 0.6f, 1.0f).Normalized(); - MCore::Quaternion emQuaternionC = emQuaternionA.Slerp(emQuaternionB, testVal); - - EXPECT_TRUE(AZEMQuaternionsAreClose(azQuaternionA, emQuaternionA, s_toleranceLow)) << "AZ/MCore Quaternions should have similar Slerp output with given float: " << testVal; - } -} - ////////////////////////////////////////////////////////////////// // Skinning ////////////////////////////////////////////////////////////////// diff --git a/Gems/EMotionFX/Code/Tests/Matchers.h b/Gems/EMotionFX/Code/Tests/Matchers.h index 64200e84f2..ad3c204f72 100644 --- a/Gems/EMotionFX/Code/Tests/Matchers.h +++ b/Gems/EMotionFX/Code/Tests/Matchers.h @@ -13,8 +13,8 @@ #include #include #include -#include #include +#include #include #include @@ -76,37 +76,6 @@ inline bool IsCloseMatcherP::gmock_Impl:: return false; } -template<> -template<> -inline bool IsCloseMatcherP::gmock_Impl::MatchAndExplain(const MCore::Quaternion& arg, ::testing::MatchResultListener* result_listener) const -{ - const MCore::Quaternion compareQuat = (expected.Dot(arg) < 0.0f) ? -arg : arg; - const AZ::Vector4 compareVec4(compareQuat.x, compareQuat.y, compareQuat.z, compareQuat.w); - - if (::testing::ExplainMatchResult(IsClose(AZ::Vector4(expected.x, expected.y, expected.z, expected.w)), compareVec4, result_listener)) - { - return true; - } - - AZ::Vector3 gotAxis; - AZ::Vector3 expectedAxis; - float gotAngle; - float expectedAngle; - - // convert to an axis and angle representation - expected.ToAxisAngle(&expectedAxis, &expectedAngle); - compareQuat.ToAxisAngle(&gotAxis, &gotAngle); - - *result_listener << "\n Got Axis: "; - PrintTo(gotAxis, result_listener->stream()); - *result_listener << ", Got Angle: " << gotAngle << "\n"; - *result_listener << "Expected Axis: "; - PrintTo(expectedAxis, result_listener->stream()); - *result_listener << ", Expected Angle: " << expectedAngle; - - return false; -} - template<> template<> inline bool IsCloseMatcherP::gmock_Impl::MatchAndExplain(const EMotionFX::Transform& arg, ::testing::MatchResultListener* result_listener) const diff --git a/Gems/EMotionFX/Code/Tests/Printers.cpp b/Gems/EMotionFX/Code/Tests/Printers.cpp index 8fd196fda0..ebf5167508 100644 --- a/Gems/EMotionFX/Code/Tests/Printers.cpp +++ b/Gems/EMotionFX/Code/Tests/Printers.cpp @@ -34,18 +34,6 @@ namespace AZStd } } // namespace AZStd -namespace MCore -{ - void PrintTo(const Quaternion& quaternion, ::std::ostream* os) - { - *os << "(x: " << quaternion.x - << ", y: " << quaternion.y - << ", z: " << quaternion.z - << ", w: " << quaternion.w - << ")"; - } -} // namespace MCore - namespace EMotionFX { void PrintTo(const Transform& transform, ::std::ostream* os) diff --git a/Gems/EMotionFX/Code/Tests/Printers.h b/Gems/EMotionFX/Code/Tests/Printers.h index c262cb2bed..afa8ea4b7b 100644 --- a/Gems/EMotionFX/Code/Tests/Printers.h +++ b/Gems/EMotionFX/Code/Tests/Printers.h @@ -11,7 +11,6 @@ #include #include #include -#include #include namespace AZ @@ -25,11 +24,6 @@ namespace AZStd void PrintTo(const string& string, ::std::ostream* os); } // namespace AZStd -namespace MCore -{ - void PrintTo(const Quaternion& quaternion, ::std::ostream* os); -} // namespace MCore - namespace EMotionFX { void PrintTo(const Transform& transform, ::std::ostream* os);