From 8fa8eeb09468f1ae577a30fa74c58d2dea81e865 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 20 Feb 2024 17:51:48 +0100 Subject: [PATCH] Optimize `Matrix` decomposition to use `Matrix3x3` for rotation --- .../Viewport/Previews/AnimatedModelPreview.cs | 2 +- Source/Engine/Core/Math/BoundingBox.cs | 2 +- Source/Engine/Core/Math/Matrix.cpp | 16 ++++-- Source/Engine/Core/Math/Matrix.cs | 50 ++++++++++++++++--- Source/Engine/Core/Math/Matrix.h | 3 +- Source/Engine/Core/Math/Matrix3x3.cs | 17 +++++++ Source/Engine/Core/Math/Transform.h | 9 ++-- 7 files changed, 83 insertions(+), 16 deletions(-) diff --git a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs index d96d7a8f9..c8f37df15 100644 --- a/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs +++ b/Source/Editor/Viewport/Previews/AnimatedModelPreview.cs @@ -342,7 +342,7 @@ namespace FlaxEditor.Viewport.Previews if (nodesMask != null && !nodesMask[nodeIndex]) continue; var transform = pose[nodeIndex]; - transform.Decompose(out var scale, out Matrix _, out _); + transform.Decompose(out var scale, out Matrix3x3 _, out _); transform = Matrix.Invert(Matrix.Scaling(scale)) * transform; var box = localBox * transform; DebugDraw.DrawWireBox(box, Color.Green, 0, false); diff --git a/Source/Engine/Core/Math/BoundingBox.cs b/Source/Engine/Core/Math/BoundingBox.cs index 51225d775..f2ae8d64b 100644 --- a/Source/Engine/Core/Math/BoundingBox.cs +++ b/Source/Engine/Core/Math/BoundingBox.cs @@ -171,7 +171,7 @@ namespace FlaxEngine /// The ray to test. /// When the method completes, contains the distance of the intersection, or 0 if there was no intersection. /// Whether the two objects intersected. - [Obsolete("Deprecated in 1.4")] + [Obsolete("Deprecated in v1.4")] public bool Intersects(ref Ray ray, out float distance) { var result = CollisionsHelper.RayIntersectsBox(ref ray, ref this, out Real dst); diff --git a/Source/Engine/Core/Math/Matrix.cpp b/Source/Engine/Core/Math/Matrix.cpp index 058936d61..7269d4e68 100644 --- a/Source/Engine/Core/Math/Matrix.cpp +++ b/Source/Engine/Core/Math/Matrix.cpp @@ -101,7 +101,7 @@ void Matrix::Decompose(Float3& scale, Float3& translation) const void Matrix::Decompose(Transform& transform) const { - Matrix rotationMatrix; + Matrix3x3 rotationMatrix; Float3 translation; Decompose(transform.Scale, rotationMatrix, translation); transform.Translation = translation; @@ -110,12 +110,12 @@ void Matrix::Decompose(Transform& transform) const void Matrix::Decompose(Float3& scale, Quaternion& rotation, Float3& translation) const { - Matrix rotationMatrix; + Matrix3x3 rotationMatrix; Decompose(scale, rotationMatrix, translation); Quaternion::RotationMatrix(rotationMatrix, rotation); } -void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) const +void Matrix::Decompose(Float3& scale, Matrix3x3& rotation, Float3& translation) const { // Get the translation translation = Float3(M41, M42, M43); @@ -127,7 +127,7 @@ void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) con Math::Sqrt(M31 * M31 + M32 * M32 + M33 * M33)); // If any of the scaling factors are zero, than the rotation matrix can not exist - rotation = Identity; + rotation = Matrix3x3::Identity; if (scale.IsAnyZero()) return; @@ -145,6 +145,14 @@ void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) con scale.Z = Float3::Dot(at, GetBackward()) > 0.0f ? scale.Z : -scale.Z; } +void Matrix::Decompose(Float3& scale, Matrix& rotation, Float3& translation) const +{ + // [Deprecated on 20.02.2024, expires on 20.02.2026] + Matrix3x3 r; + Decompose(scale, r, translation); + rotation = Matrix(r); +} + Matrix Matrix::Transpose(const Matrix& value) { Matrix result; diff --git a/Source/Engine/Core/Math/Matrix.cs b/Source/Engine/Core/Math/Matrix.cs index 6344b008a..4bee98574 100644 --- a/Source/Engine/Core/Math/Matrix.cs +++ b/Source/Engine/Core/Math/Matrix.cs @@ -330,6 +330,30 @@ namespace FlaxEngine M44 = values[15]; } + /// + /// Initializes a new instance of the struct. + /// + /// The rotation/scale matrix. + public Matrix(Matrix3x3 m) + { + M11 = m.M11; + M12 = m.M12; + M13 = m.M13; + M14 = 0; + M21 = m.M21; + M22 = m.M22; + M23 = m.M23; + M24 = 0; + M31 = m.M31; + M32 = m.M32; + M33 = m.M33; + M34 = 0; + M41 = 0; + M42 = 0; + M43 = 0; + M44 = 1; + } + /// /// Gets or sets the first row in the matrix; that is M11, M12, M13, and M14. /// @@ -747,7 +771,7 @@ namespace FlaxEngine /// This method is designed to decompose an SRT transformation matrix only. public void Decompose(out Transform transform) { - Decompose(out transform.Scale, out Matrix rotationMatrix, out Float3 translation); + Decompose(out transform.Scale, out Matrix3x3 rotationMatrix, out Float3 translation); Quaternion.RotationMatrix(ref rotationMatrix, out transform.Orientation); transform.Translation = translation; } @@ -759,7 +783,7 @@ namespace FlaxEngine /// When the method completes, contains the rotation component of the decomposed matrix. /// When the method completes, contains the translation component of the decomposed matrix. /// This method is designed to decompose an SRT transformation matrix only. - public void Decompose(out Float3 scale, out Matrix rotation, out Float3 translation) + public void Decompose(out Float3 scale, out Matrix3x3 rotation, out Float3 translation) { // Get the translation translation.X = M41; @@ -774,12 +798,12 @@ namespace FlaxEngine // If any of the scaling factors are zero, than the rotation matrix can not exist if (Mathf.IsZero(scale.X) || Mathf.IsZero(scale.Y) || Mathf.IsZero(scale.Z)) { - rotation = Identity; + rotation = Matrix3x3.Identity; return; } // The rotation is the left over matrix after dividing out the scaling - rotation = new Matrix + rotation = new Matrix3x3 { M11 = M11 / scale.X, M12 = M12 / scale.X, @@ -790,10 +814,24 @@ namespace FlaxEngine M31 = M31 / scale.Z, M32 = M32 / scale.Z, M33 = M33 / scale.Z, - M44 = 1f }; } + /// + /// Decomposes a matrix into a scale, rotation, and translation. + /// [Deprecated on 20.02.2024, expires on 20.02.2026] + /// + /// When the method completes, contains the scaling component of the decomposed matrix. + /// When the method completes, contains the rotation component of the decomposed matrix. + /// When the method completes, contains the translation component of the decomposed matrix. + /// This method is designed to decompose an SRT transformation matrix only. + [Obsolete("Deprecated in v1.8")] + public void Decompose(out Float3 scale, out Matrix rotation, out Float3 translation) + { + Decompose(out scale, out Matrix3x3 r, out translation); + rotation = new Matrix(r); + } + /// /// Decomposes a matrix into a scale, rotation, and translation. /// @@ -803,7 +841,7 @@ namespace FlaxEngine /// This method is designed to decompose an SRT transformation matrix only. public void Decompose(out Float3 scale, out Quaternion rotation, out Float3 translation) { - Decompose(out scale, out Matrix rotationMatrix, out translation); + Decompose(out scale, out Matrix3x3 rotationMatrix, out translation); Quaternion.RotationMatrix(ref rotationMatrix, out rotation); } diff --git a/Source/Engine/Core/Math/Matrix.h b/Source/Engine/Core/Math/Matrix.h index aed2ead8d..11fbe1e78 100644 --- a/Source/Engine/Core/Math/Matrix.h +++ b/Source/Engine/Core/Math/Matrix.h @@ -480,7 +480,8 @@ public: /// When the method completes, contains the rotation component of the decomposed matrix. /// When the method completes, contains the translation component of the decomposed matrix. /// This method is designed to decompose an SRT transformation matrix only. - void Decompose(Float3& scale, Matrix& rotation, Float3& translation) const; + void Decompose(Float3& scale, Matrix3x3& rotation, Float3& translation) const; + DEPRECATED void Decompose(Float3& scale, Matrix& rotation, Float3& translation) const; public: Matrix operator*(const float scale) const diff --git a/Source/Engine/Core/Math/Matrix3x3.cs b/Source/Engine/Core/Math/Matrix3x3.cs index 44af4542b..33e69d6e1 100644 --- a/Source/Engine/Core/Math/Matrix3x3.cs +++ b/Source/Engine/Core/Math/Matrix3x3.cs @@ -185,6 +185,23 @@ namespace FlaxEngine M33 = values[8]; } + /// + /// Initializes a new instance of the struct. + /// + /// The rotation/scale matrix. + public Matrix3x3(Matrix m) + { + M11 = m.M11; + M12 = m.M12; + M13 = m.M13; + M21 = m.M21; + M22 = m.M22; + M23 = m.M23; + M31 = m.M31; + M32 = m.M32; + M33 = m.M33; + } + /// /// Gets or sets the first row in the Matrix3x3; that is M11, M12, M13 /// diff --git a/Source/Engine/Core/Math/Transform.h b/Source/Engine/Core/Math/Transform.h index 1079b4c23..f61ce8b9c 100644 --- a/Source/Engine/Core/Math/Transform.h +++ b/Source/Engine/Core/Math/Transform.h @@ -18,17 +18,20 @@ API_STRUCT() struct FLAXENGINE_API Transform /// /// The translation vector of the transform. /// - API_FIELD(Attributes="EditorOrder(10), EditorDisplay(null, \"Position\")") Vector3 Translation; + API_FIELD(Attributes="EditorOrder(10), EditorDisplay(null, \"Position\")") + Vector3 Translation; /// /// The rotation of the transform. /// - API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Rotation\")") Quaternion Orientation; + API_FIELD(Attributes="EditorOrder(20), EditorDisplay(null, \"Rotation\")") + Quaternion Orientation; /// /// The scale vector of the transform. /// - API_FIELD(Attributes="EditorOrder(30), Limit(float.MinValue, float.MaxValue, 0.01f)") Float3 Scale; + API_FIELD(Attributes="EditorOrder(30), Limit(float.MinValue, float.MaxValue, 0.01f)") + Float3 Scale; public: ///