From 6dd2bb38ccb8a70ebe84e9108dee30f6f64d31bc Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 20 Feb 2023 15:49:50 +0900 Subject: [PATCH] =?UTF-8?q?IControlRigGetter=20=E3=81=A8=20IControlRigSett?= =?UTF-8?q?er=20=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add ControlRigRetarget impl InitialRotationRigGetter.cs impl NormalizedRotationRigGetter.cs mv Assets/Vrm10/Runtime/ControlRig/Vrm10ControlBone.cs => Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs mv Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs => Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs rename Vrm10BoneInitialRotation => BoneInitialRotation remove Vrm0XCompatibleRig.cs --- .../UniGLTF/Runtime/UniHumanoid/Humanoid.cs | 2 +- .../ControlRigGenerationOption.cs | 0 .../ControlRigGenerationOption.cs.meta | 0 .../Vrm10Runtime}/Vrm10ControlBone.cs | 1 + .../Vrm10Runtime}/Vrm10ControlBone.cs.meta | 0 .../Vrm10Runtime/Vrm10RuntimeControlRig.cs | 40 +++++++++++++-- ...tialRotation.cs => BoneInitialRotation.cs} | 10 ++-- ...on.cs.meta => BoneInitialRotation.cs.meta} | 0 .../Runtime/ControlRig/ControlRigRetarget.cs | 15 ++++++ ...Rig.cs.meta => ControlRigRetarget.cs.meta} | 2 +- .../Runtime/ControlRig/IControlRigGetter.cs | 11 ++++ .../ControlRig/IControlRigGetter.cs.meta | 11 ++++ .../Runtime/ControlRig/IControlRigSetter.cs | 17 +++++++ .../ControlRig/IControlRigSetter.cs.meta | 11 ++++ .../ControlRig/InitialRotationRigGetter.cs | 50 +++++++++++++++++++ .../InitialRotationRigGetter.cs.meta | 11 ++++ .../InitialRotations/Vrm0XCompatibleRig.cs | 15 ------ .../ControlRig/NormalizedRotationRigGetter.cs | 41 +++++++++++++++ .../NormalizedRotationRigGetter.cs.meta | 11 ++++ 19 files changed, 222 insertions(+), 26 deletions(-) rename Assets/VRM10/Runtime/{ControlRig/InitialRotations => Components/Vrm10Runtime}/ControlRigGenerationOption.cs (100%) rename Assets/VRM10/Runtime/{ControlRig/InitialRotations => Components/Vrm10Runtime}/ControlRigGenerationOption.cs.meta (100%) rename Assets/VRM10/Runtime/{ControlRig => Components/Vrm10Runtime}/Vrm10ControlBone.cs (98%) rename Assets/VRM10/Runtime/{ControlRig => Components/Vrm10Runtime}/Vrm10ControlBone.cs.meta (100%) rename Assets/VRM10/Runtime/ControlRig/{Vrm10BoneInitialRotation.cs => BoneInitialRotation.cs} (74%) rename Assets/VRM10/Runtime/ControlRig/{Vrm10BoneInitialRotation.cs.meta => BoneInitialRotation.cs.meta} (100%) create mode 100644 Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs rename Assets/VRM10/Runtime/ControlRig/{InitialRotations/Vrm0XCompatibleRig.cs.meta => ControlRigRetarget.cs.meta} (83%) create mode 100644 Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs.meta create mode 100644 Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs.meta create mode 100644 Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs.meta delete mode 100644 Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs create mode 100644 Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniHumanoid/Humanoid.cs b/Assets/UniGLTF/Runtime/UniHumanoid/Humanoid.cs index b896a6017..068492f5d 100644 --- a/Assets/UniGLTF/Runtime/UniHumanoid/Humanoid.cs +++ b/Assets/UniGLTF/Runtime/UniHumanoid/Humanoid.cs @@ -239,7 +239,7 @@ namespace UniHumanoid return null; } - IEnumerable<(Transform, HumanBodyBones)> BoneMap + public IEnumerable<(Transform, HumanBodyBones)> BoneMap { get { diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs similarity index 100% rename from Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRigGenerationOption.cs.meta diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs similarity index 98% rename from Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs index a10fcaba1..eec7aa06a 100644 --- a/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs @@ -34,6 +34,7 @@ namespace UniVRM10 private readonly Quaternion _initialTargetLocalRotation; private readonly Quaternion _initialTargetGlobalRotation; private readonly List _children = new List(); + public IReadOnlyList Children => _children; private Vrm10ControlBone(Transform controlTarget, HumanBodyBones boneType, Vrm10ControlBone parent) { diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs.meta b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs.meta rename to Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10ControlBone.cs.meta diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs index c6c13c6df..65497ec19 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs @@ -13,7 +13,7 @@ namespace UniVRM10 /// Create a control rig for the VRM 1.0 model instance. /// This provides the normalized operation of bones, like VRM 0.x. /// - public sealed class Vrm10RuntimeControlRig : IDisposable + public sealed class Vrm10RuntimeControlRig : IDisposable, IControlRigSetter { private readonly Transform _controlRigRoot; private readonly Vrm10ControlBone _hipBone; @@ -73,12 +73,46 @@ namespace UniVRM10 public void EnforceTPose() { - // TODO: restore hips position - + SetRootPosition(_hipBone.ControlBone.position); foreach (var bone in _bones.Values) { bone.ControlBone.localRotation = Quaternion.identity; } } + + public void SetRootPosition(Vector3 position) + { + // TODO: scale model local position + _hipBone.ControlTarget.position = position; + } + + public void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation) + { + if (_bones.TryGetValue(bone, out var t)) + { + t.ControlBone.localRotation = normalizedLocalRotation; + } + } + + IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> Traverse(Vrm10ControlBone bone, Vrm10ControlBone parent = null) + { + yield return (bone.BoneType, parent != null ? parent.BoneType : HumanBodyBones.LastBone); + + foreach (var child in bone.Children) + { + foreach (var headParent in Traverse(child, bone)) + { + yield return headParent; + } + } + } + + public IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones() + { + foreach (var headParent in Traverse(_hipBone)) + { + yield return headParent; + } + } } } diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs b/Assets/VRM10/Runtime/ControlRig/BoneInitialRotation.cs similarity index 74% rename from Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs rename to Assets/VRM10/Runtime/ControlRig/BoneInitialRotation.cs index ffdb5b7a0..d926be18b 100644 --- a/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs +++ b/Assets/VRM10/Runtime/ControlRig/BoneInitialRotation.cs @@ -5,7 +5,7 @@ namespace UniVRM10 /// /// Represents the rotation at the initial pose (TPose) /// - public readonly struct Vrm10BoneInitialRotation + public readonly struct BoneInitialRotation { public readonly Transform Transform; @@ -15,7 +15,7 @@ namespace UniVRM10 public readonly Quaternion InitialGlobalRotation; - public Vrm10BoneInitialRotation(Transform transform) + public BoneInitialRotation(Transform transform) { Transform = transform; InitialLocalPosition = transform.localPosition; @@ -24,11 +24,9 @@ namespace UniVRM10 } /// - /// 初期姿勢からの相対的な回転。 - /// - /// VRM-0.X 互換リグでは localRotation と同じ値を示す。 + /// Convert the local rotation, including the initial rotation, to a normalized local rotation /// - Quaternion NormalizedLocalRotation + public Quaternion NormalizedLocalRotation { get { diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs.meta b/Assets/VRM10/Runtime/ControlRig/BoneInitialRotation.cs.meta similarity index 100% rename from Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs.meta rename to Assets/VRM10/Runtime/ControlRig/BoneInitialRotation.cs.meta diff --git a/Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs b/Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs new file mode 100644 index 000000000..31304b1bc --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs @@ -0,0 +1,15 @@ +namespace UniVRM10 +{ + public static class ControlRigRetarget + { + public static void Retarget(IControlRigGetter getter, IControlRigSetter setter) + { + foreach (var (head, parent) in setter.EnumerateBones()) + { + var q = getter.GetNormalizedLocalRotation(head, parent); + setter.SetNormalizedLocalRotation(head, q); + } + setter.SetRootPosition(getter.GetRootPosition()); + } + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs.meta b/Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs.meta similarity index 83% rename from Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs.meta rename to Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs.meta index 515a87b3b..4bfbd264e 100644 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs.meta +++ b/Assets/VRM10/Runtime/ControlRig/ControlRigRetarget.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d1e0f212571bf3f41809f19c2d8f3211 +guid: 55c7c4cd6bc756142a927d385a1c0d29 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs b/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs new file mode 100644 index 000000000..69bc2e009 --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs @@ -0,0 +1,11 @@ +using UnityEngine; + +namespace UniVRM10 +{ + public interface IControlRigGetter + { + Vector3 GetRootPosition(); + + Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone); + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs.meta b/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs.meta new file mode 100644 index 000000000..7169bd3ee --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/IControlRigGetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 624d9ba92e6c69b40abab8223e530d9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs b/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs new file mode 100644 index 000000000..598b8ce6a --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UniVRM10 +{ + public interface IControlRigSetter + { + /// TODO: 何らかのスケーリングが必用 + void SetRootPosition(Vector3 position); + + /// 初期姿勢(TPose) が Quaternion.Identity である相対回転 + void SetNormalizedLocalRotation(HumanBodyBones bone, Quaternion normalizedLocalRotation); + + /// ボーンを親ボーンとセットで返す + IEnumerable<(HumanBodyBones Head, HumanBodyBones Parent)> EnumerateBones(); + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs.meta b/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs.meta new file mode 100644 index 000000000..8eee27ebc --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/IControlRigSetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9e200e64e4f18884d8a35bf9ce27cd4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs new file mode 100644 index 000000000..f10888419 --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace UniVRM10 +{ + /// + /// VRM0TPose と異なる初期回転を持ったヒエラルキー + /// + /// - XR_EXT_hand_tracking + /// - XR_FB_body_tracking + /// - vrm-animation + /// + /// から VRM0TPose 互換の NormalizedLocalRotation(VRM0互換)を取り出す。 + /// BoneInitialRotation が値を計算できる。 + /// + public class InitRotationRigGetter : IControlRigGetter + { + Transform m_root; + private readonly Dictionary m_bones = new Dictionary(); + + /// TPoseのヒエラルキー + public InitRotationRigGetter(Transform root, UniHumanoid.Humanoid humanoid) + { + m_root = root; + foreach (var (t, bone) in humanoid.BoneMap) + { + m_bones.Add(bone, new BoneInitialRotation(t)); + } + } + + public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) + { + if (m_bones.TryGetValue(bone, out var c)) + { + return c.NormalizedLocalRotation; + } + else + { + // Debug.LogWarning($"${bone} not found"); + return Quaternion.identity; + } + } + + public Vector3 GetRootPosition() + { + // TODO: from m_root relative ? scaling ? + return m_bones[HumanBodyBones.Hips].Transform.localPosition; + } + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs.meta b/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs.meta new file mode 100644 index 000000000..c3b1ac27e --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotationRigGetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b21b9221f1a87564ea6dc5cf6037195a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs deleted file mode 100644 index ddc033dc5..000000000 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotations/Vrm0XCompatibleRig.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -namespace UniVRM10 -{ - public static class Vrm0XCompatibleRig - { - /// - /// 空の Dictionary を返します。 - /// HumanBodyBones に対応する Quaternion が無い場合は Quaternion.Identity を採用する仕様です。 - /// VRM-0.X では T-Pose のときにすべてのボーンが Quaternion.Identity です。 - /// - public static IReadOnlyDictionary InitialRotations => new Dictionary(); - } -} diff --git a/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs b/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs new file mode 100644 index 000000000..fedbf83cd --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs @@ -0,0 +1,41 @@ +using UnityEngine; + +namespace UniVRM10 +{ + /// + /// 正規化済みのヒエラルキーの getter。 + /// localRotation をコピーするだけなのだが、 + /// GetNormalizedLocalRotation にて、ボーンの有無(upperChestなど)の違いの対応をする予定(未実装)。 + /// + public class NormalizedRigGetter : IControlRigGetter + { + Transform m_root; + Animator m_animator; + + public NormalizedRigGetter(Transform root, Animator animator) + { + m_root = root; + m_animator = animator; + } + + public Quaternion GetNormalizedLocalRotation(HumanBodyBones bone, HumanBodyBones parentBone) + { + if (m_animator.GetBoneTransform(bone) is Transform t) + { + // TODO: parentBone relative + return t.localRotation; + } + else + { + // Debug.LogWarning($"{bone} not found"); + return Quaternion.identity; + } + } + + public Vector3 GetRootPosition() + { + // TODO: from model root ? + return m_animator.GetBoneTransform(HumanBodyBones.Hips).localPosition; + } + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs.meta b/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs.meta new file mode 100644 index 000000000..ae53d6441 --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/NormalizedRotationRigGetter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 77dc323422a0e59449bd822dac490495 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: