From ef802377823f0e07596e6610b19dc34cadad3ad8 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 27 Feb 2023 18:47:30 +0900 Subject: [PATCH 1/3] =?UTF-8?q?ITPoseProvider=20=E3=82=92=E7=B8=AE?= =?UTF-8?q?=E5=B0=8F=E3=80=82EuclideanTransform=20=E5=B0=8E=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ControlRig/Vrm10RuntimeControlRig.cs | 37 +++--------- .../ControlRig/AnimatorPoseProvider.cs | 34 ++++------- .../Runtime/ControlRig/EuclideanTransform.cs | 31 ++++++++++ .../ControlRig/EuclideanTransform.cs.meta | 11 ++++ .../Runtime/ControlRig/ITPoseProvider.cs | 58 ++++++++++++++++--- .../ControlRig/InitialRotationPoseProvider.cs | 12 +--- .../VRM10Viewer/VRM10Retarget.cs | 8 +-- 7 files changed, 116 insertions(+), 75 deletions(-) create mode 100644 Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs index 5af0d7732..f1f7028b8 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs @@ -68,7 +68,6 @@ namespace UniVRM10 } } - #region INormalizedPoseApplicable public void SetRawHipsPosition(Vector3 position) { var world = _controlRigRoot.TransformPoint(position); @@ -82,39 +81,17 @@ namespace UniVRM10 t.ControlBone.localRotation = normalizedLocalRotation; } } - #endregion - IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> Traverse(Vrm10ControlBone bone, Vrm10ControlBone parent = null) + public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) { - yield return (bone.BoneType, parent != null ? parent.BoneType : HumanBodyBones.LastBone); - - foreach (var child in bone.Children) + if (_bones.TryGetValue(bone, out var t)) { - foreach (var headParent in Traverse(child, bone)) - { - yield return headParent; - } + return new EuclideanTransform(t.InitialTargetGlobalPosition); + } + else + { + return default; } } - - #region ITPoseProvider - public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs() - { - foreach (var headParent in Traverse(_hipBone)) - { - yield return headParent; - } - } - - public Quaternion? GetBoneWorldRotation(HumanBodyBones bone) - { - return Quaternion.identity; - } - - public Vector3? GetBoneWorldPosition(HumanBodyBones bone) - { - return _bones[bone].InitialTargetGlobalPosition; - } - #endregion } } diff --git a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs index 90742e54a..9ad0f6570 100644 --- a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs @@ -16,7 +16,7 @@ namespace UniVRM10 { Transform m_root; Animator m_animator; - Dictionary m_posMap = new Dictionary(); + Dictionary m_posMap = new Dictionary(); public AnimatorPoseProvider(Transform root, Animator animator) { @@ -24,23 +24,21 @@ namespace UniVRM10 m_animator = animator; var hips = animator.GetBoneTransform(HumanBodyBones.Hips); - HipTPoseWorldPosition = root.worldToLocalMatrix.MultiplyPoint(hips.position); foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones))) { - if(bone==HumanBodyBones.LastBone) + if (bone == HumanBodyBones.LastBone) { continue; } var t = animator.GetBoneTransform(bone); if (t != null) { - m_posMap[bone] = root.worldToLocalMatrix.MultiplyPoint(t.position); + m_posMap[bone] = new EuclideanTransform(root.worldToLocalMatrix * t.localToWorldMatrix); } } } - #region INormalizedPoseProvider public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) { if (m_animator.GetBoneTransform(bone) is Transform t) @@ -60,25 +58,17 @@ namespace UniVRM10 // TODO: from model root ? return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition; } - #endregion - #region ITPoseProvider - public Vector3 HipTPoseWorldPosition { get; } - - public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs() + public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) { - throw new System.NotImplementedException(); + if (m_posMap.TryGetValue(bone, out var t)) + { + return t; + } + else + { + return default; + } } - - public Quaternion? GetBoneWorldRotation(HumanBodyBones bone) - { - throw new System.NotImplementedException(); - } - - public Vector3? GetBoneWorldPosition(HumanBodyBones bone) - { - return m_posMap[bone]; - } - #endregion } } diff --git a/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs b/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs new file mode 100644 index 000000000..28c9e572a --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs @@ -0,0 +1,31 @@ +using UnityEngine; + +namespace UniVRM10 +{ + public readonly struct EuclideanTransform + { + public readonly Quaternion Rotation; + public readonly Vector3 Translation; + + public EuclideanTransform(Quaternion rotation, Vector3 translation) + { + Rotation = rotation; + Translation = translation; + } + public EuclideanTransform(Quaternion rotation) + { + Rotation = rotation; + Translation = Vector3.zero; + } + public EuclideanTransform(Vector3 translation) + { + Rotation = Quaternion.identity; + Translation = translation; + } + public EuclideanTransform(Matrix4x4 matrix) + { + Rotation = matrix.rotation; + Translation = matrix.GetColumn(3); + } + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta b/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta new file mode 100644 index 000000000..363d1575a --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af1b96890351fa24e9a49e7c4a6c2185 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs index 1ffe5f60a..48e24a06f 100644 --- a/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using UnityEngine; @@ -6,15 +7,56 @@ namespace UniVRM10 public interface ITPoseProvider { /// - /// このTPoseに含まれるボーンと親ボーンの組み合わせを列挙する。 - /// - /// * Humanoidの木構造を深さ優先の順番で列挙する - /// + /// TPose 時のモデルルートを基準とした world 回転と位置を返す。 + /// 該当する bone が無いときは null。 /// - /// hips の場合は parent は HumanBodyBones.LastBone で null を表す - IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs(); + EuclideanTransform? GetWorldTransform(HumanBodyBones bone); + } - Quaternion? GetBoneWorldRotation(HumanBodyBones bone); - Vector3? GetBoneWorldPosition(HumanBodyBones bone); + public static class ITPoseProviderExtensions + { + static HumanBodyBones GetParent(ITPoseProvider self, HumanBodyBones bone) + { + var current = bone; + // 無限ループ防止のため念のためカウンター付き + for (int i = 0; i < 100; ++i) + { + var vrmBone = Vrm10HumanoidBoneSpecification.ConvertFromUnityBone(current); + var def = Vrm10HumanoidBoneSpecification.GetDefine(vrmBone); + var parentBone = Vrm10HumanoidBoneSpecification.ConvertToUnityBone(def.ParentBone.Value); + if (self.GetWorldTransform(parentBone).HasValue) + { + return parentBone; + } + current = parentBone; + } + + // Hips 以外は必ず親ボーンが有るはずなのでここには来ない + throw new Exception("parent not found"); + } + + public static IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs(this ITPoseProvider self) + { + foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones))) + { + if (bone == HumanBodyBones.LastBone) + { + continue; + } + if (!self.GetWorldTransform(bone).HasValue) + { + continue; + } + + if (bone == HumanBodyBones.Hips) + { + yield return (bone, HumanBodyBones.LastBone); + } + else + { + yield return (bone, GetParent(self, bone)); + } + } + } } } diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs index a2d01d06a..e2eca54cb 100644 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs @@ -56,17 +56,7 @@ namespace UniVRM10 } } - public IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs() - { - throw new System.NotImplementedException(); - } - - public Quaternion? GetBoneWorldRotation(HumanBodyBones bone) - { - throw new System.NotImplementedException(); - } - - public Vector3? GetBoneWorldPosition(HumanBodyBones bone) + public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) { throw new System.NotImplementedException(); } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs index 7825fd36e..2d91fb3e6 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10Retarget.cs @@ -13,9 +13,9 @@ namespace UniVRM10.VRM10Viewer } // scaling hips position - var scaling = sink.TPose.GetBoneWorldPosition(HumanBodyBones.LeftUpperLeg).Value.y / source.TPose.GetBoneWorldPosition(HumanBodyBones.LeftUpperLeg).Value.y; - var delta = source.Pose.GetRawHipsPosition() - source.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value; - sink.Pose.SetRawHipsPosition(sink.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value + delta * scaling); + var scaling = sink.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y / source.TPose.GetWorldTransform(HumanBodyBones.LeftUpperLeg).Value.Translation.y; + var delta = source.Pose.GetRawHipsPosition() - source.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation; + sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation + delta * scaling); } public static void EnforceTPose((INormalizedPoseApplicable Pose, ITPoseProvider TPose) sink) @@ -25,7 +25,7 @@ namespace UniVRM10.VRM10Viewer sink.Pose.SetNormalizedLocalRotation(bone, Quaternion.identity); } - sink.Pose.SetRawHipsPosition(sink.TPose.GetBoneWorldPosition(HumanBodyBones.Hips).Value); + sink.Pose.SetRawHipsPosition(sink.TPose.GetWorldTransform(HumanBodyBones.Hips).Value.Translation); } } } From 18660498a556ba40911b86a4295fd846837d97d1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 27 Feb 2023 18:59:27 +0900 Subject: [PATCH 2/3] mv EuclideanTransform to UniGLTF.Utils --- .../ControlRig => UniGLTF/Runtime/Utils}/EuclideanTransform.cs | 2 +- .../Runtime/Utils}/EuclideanTransform.cs.meta | 0 .../Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs | 1 + Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs | 1 + Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs | 3 ++- Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs | 1 + 6 files changed, 6 insertions(+), 2 deletions(-) rename Assets/{VRM10/Runtime/ControlRig => UniGLTF/Runtime/Utils}/EuclideanTransform.cs (97%) rename Assets/{VRM10/Runtime/ControlRig => UniGLTF/Runtime/Utils}/EuclideanTransform.cs.meta (100%) diff --git a/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs b/Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs similarity index 97% rename from Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs rename to Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs index 28c9e572a..5c6992f1b 100644 --- a/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs +++ b/Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs @@ -1,6 +1,6 @@ using UnityEngine; -namespace UniVRM10 +namespace UniGLTF.Utils { public readonly struct EuclideanTransform { diff --git a/Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta b/Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/ControlRig/EuclideanTransform.cs.meta rename to Assets/UniGLTF/Runtime/Utils/EuclideanTransform.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs index f1f7028b8..07ce942ad 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using UniHumanoid; using UnityEngine; +using UniGLTF.Utils; namespace UniVRM10 { diff --git a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs index 9ad0f6570..535c757db 100644 --- a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 diff --git a/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs index 48e24a06f..3f996bcc5 100644 --- a/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/ITPoseProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 @@ -37,7 +38,7 @@ namespace UniVRM10 public static IEnumerable<(HumanBodyBones Bone, HumanBodyBones Parent)> EnumerateBoneParentPairs(this ITPoseProvider self) { - foreach (HumanBodyBones bone in Enum.GetValues(typeof(HumanBodyBones))) + foreach (var bone in CachedEnum.GetValues()) { if (bone == HumanBodyBones.LastBone) { diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs index e2eca54cb..aea486911 100644 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using UniGLTF.Utils; using UnityEngine; namespace UniVRM10 From 4f6ff8f798d763164b5128d221732a1da1f16ccb Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 27 Feb 2023 19:18:51 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=E6=98=8E=E7=A4=BA=E7=9A=84=E3=81=AA?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=BF=E3=83=BC=E3=83=95=E3=82=A7=E3=82=A4?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs | 6 +++--- Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs | 6 +++--- .../VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs index 07ce942ad..d054033e8 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10RuntimeControlRig.cs @@ -69,13 +69,13 @@ namespace UniVRM10 } } - public void SetRawHipsPosition(Vector3 position) + void INormalizedPoseApplicable.SetRawHipsPosition(Vector3 position) { var world = _controlRigRoot.TransformPoint(position); _hipBone.ControlBone.position = world; } - public void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation) + void INormalizedPoseApplicable.SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation) { if (_bones.TryGetValue(bone, out var t)) { @@ -83,7 +83,7 @@ namespace UniVRM10 } } - public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) + EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone) { if (_bones.TryGetValue(bone, out var t)) { diff --git a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs index 535c757db..5d570c36b 100644 --- a/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/AnimatorPoseProvider.cs @@ -40,7 +40,7 @@ namespace UniVRM10 } } - public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) + Quaternion INormalizedPoseProvider.GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) { if (m_animator.GetBoneTransform(bone) is Transform t) { @@ -54,13 +54,13 @@ namespace UniVRM10 } } - public Vector3 GetRawHipsPosition() + Vector3 INormalizedPoseProvider.GetRawHipsPosition() { // TODO: from model root ? return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition; } - public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) + EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone) { if (m_posMap.TryGetValue(bone, out var t)) { diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs index aea486911..e87769866 100644 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotationPoseProvider.cs @@ -32,7 +32,7 @@ namespace UniVRM10 } } - public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) + Quaternion INormalizedPoseProvider.GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) { if (m_bones.TryGetValue(bone, out var c)) { @@ -45,7 +45,7 @@ namespace UniVRM10 } } - public Vector3 GetRawHipsPosition() + Vector3 INormalizedPoseProvider.GetRawHipsPosition() { if (m_hips.parent == m_root) { @@ -57,7 +57,7 @@ namespace UniVRM10 } } - public EuclideanTransform? GetWorldTransform(HumanBodyBones bone) + EuclideanTransform? ITPoseProvider.GetWorldTransform(HumanBodyBones bone) { throw new System.NotImplementedException(); }