diff --git a/CHANGELOG-PRERELEASE.md b/CHANGELOG-PRERELEASE.md index 41000c53d..9b71dbaa0 100644 --- a/CHANGELOG-PRERELEASE.md +++ b/CHANGELOG-PRERELEASE.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog]. ### Fixed - Left eye disappears `#493` +- MergeBone will loose transform information with extreamly small parent scale `#495` ### Security diff --git a/Editor/Math/Matrix4x4.cs b/Editor/Math/Matrix4x4.cs index e17355c0d..d0cfe9058 100644 --- a/Editor/Math/Matrix4x4.cs +++ b/Editor/Math/Matrix4x4.cs @@ -18,23 +18,27 @@ struct Matrix4x4 : IEquatable // @formatter:off public float m00; - public float m01; - public float m02; - public float m03; public float m10; - public float m11; - public float m12; - public float m13; public float m20; - public float m21; - public float m22; - public float m23; public float m30; + public float m01; + public float m11; + public float m21; public float m31; + public float m02; + public float m12; + public float m22; public float m32; + public float m03; + public float m13; + public float m23; public float m33; // @formatter:on + public Vector3 offset => new Vector3(m03, m13, m23); + public Quaternion rotation => ToUnity().rotation; + public Vector3 lossyScale => ToUnity().lossyScale; + public Vector3 MultiplyPoint3x4(Vector3 point) { Vector3 vector3; @@ -156,5 +160,8 @@ public Matrix4x4(Vector4 column0, Vector4 column1, Vector4 column2, Vector4 colu public override bool Equals(object obj) => obj is Matrix4x4 other && Equals(other); public override int GetHashCode() => ToUnity().GetHashCode(); public override string ToString() => ToUnity().ToString(); + + public static Matrix4x4 TRS(Vector3 pos, Quaternion rot, Vector3 scale) => UnityMatrix4x4.TRS(pos, rot, scale); + public static Matrix4x4 TRS(Transform t) => UnityMatrix4x4.TRS(t.localPosition, t.localRotation, t.localScale); } } \ No newline at end of file diff --git a/Editor/Processors/MergeBoneProcessor.cs b/Editor/Processors/MergeBoneProcessor.cs index fe6a12c44..5b9e0e5d9 100644 --- a/Editor/Processors/MergeBoneProcessor.cs +++ b/Editor/Processors/MergeBoneProcessor.cs @@ -80,11 +80,15 @@ public void Process(OptimizerSession session) // if intermediate objects are inactive, moved bone should be initially inactive // animations are not performed correctly but if bones activity is animated, automatic // merge bone doesn't merge such bone so ignore that for manual merge bone. - var (activeSelf, namePrefix) = ActiveSelfAndNamePrefix(mapping, mapped); + var (activeSelf, namePrefix, matrix) = ComputeParentInformation(mapping, mapped); foreach (var child in mapping.DirectChildrenEnumerable().ToArray()) { if (mergeMapping.ContainsKey(child)) continue; + var mat = matrix * Matrix4x4.TRS(child); child.parent = mapped; + child.localPosition = mat.offset; + child.localRotation = mat.rotation; + child.localScale = mat.lossyScale; if (!activeSelf) child.gameObject.SetActive(false); if (avoidNameConflict) child.name = namePrefix + "$" + child.name + "$" + (counter++); @@ -95,19 +99,21 @@ public void Process(OptimizerSession session) if (pair) Object.DestroyImmediate(pair.gameObject); - (bool activeSelf, string namePrefix) ActiveSelfAndNamePrefix(Transform transform, Transform parent) + (bool activeSelf, string namePrefix, Matrix4x4 matrix) ComputeParentInformation(Transform transform, Transform parent) { var segments = new List(); var activeSelf = true; + var matrix = Matrix4x4.identity; for (; transform != parent; transform = transform.parent) { segments.Add(transform.name); activeSelf &= transform.gameObject.activeSelf; + matrix = Matrix4x4.TRS(transform) * matrix; } segments.Reverse(); - return (activeSelf, string.Join("$", segments)); + return (activeSelf, string.Join("$", segments), matrix); } }