diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10ControlBone.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10ControlBone.cs index 7c022fc3a..f6b441c5c 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10ControlBone.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/ControlRig/Vrm10ControlBone.cs @@ -5,99 +5,94 @@ using UnityEngine; namespace UniVRM10 { /// + /// The control bone of the control rig. + /// /// このクラスのヒエラルキーが 正規化された TPose を表している。 /// 同時に、元のヒエラルキーの初期回転を保持する。 /// Apply 関数で、再帰的に正規化済みのローカル回転から初期回転を加味したローカル回転を作って適用する。 /// - public class Vrm10ControlBone + public sealed class Vrm10ControlBone { - public readonly HumanBodyBones Bone; + /// + /// このボーンに紐づく種類。 + /// + public HumanBodyBones BoneType { get; } /// - /// 元のヒエラルキーの対応ボーン + /// コントロール対象のボーン Transform。 /// - public readonly Transform Target; + public Transform ControlTarget { get; } /// - /// 回転と拡大縮小を除去した(正規化された)ボーン。 - /// このボーンに対して localRotation を代入する。 + /// コントロールのためのボーン Transform。 + /// + /// VRM の T-Pose 姿勢をしているときに、回転とスケールが初期値になっている(正規化)。 + /// このボーンに対して localRotation を代入し、コントロールを行う。 /// - public readonly Transform Normalized; + public Transform ControlBone { get; } - /// - /// 元のボーンの初期回転。 - /// - public readonly Quaternion InitialLocalRotation; + private readonly Quaternion _initialTargetLocalRotation; + private readonly Quaternion _initialTargetGlobalRotation; + private readonly List _children = new List(); - public readonly Quaternion ToLocal; - - public List Children = new List(); - - public Vrm10ControlBone(Transform current, Quaternion parentInverse, HumanBodyBones bone) + internal Vrm10ControlBone(Transform controlTarget, HumanBodyBones boneType) { - if (bone == HumanBodyBones.LastBone) + if (boneType == HumanBodyBones.LastBone) { throw new ArgumentNullException(); } - if (current == null) + if (controlTarget == null) { throw new ArgumentNullException(); } - Bone = bone; - Target = current; - Normalized = new GameObject(bone.ToString()).transform; - Normalized.position = current.position; - // InitialLocalRotation = parentInverse * current.rotation; - InitialLocalRotation = current.localRotation; - // InitialLocalRotation = current.rotation; - ToLocal = current.rotation; + + BoneType = boneType; + ControlTarget = controlTarget; + ControlBone = new GameObject(boneType.ToString()).transform; + ControlBone.position = controlTarget.position; + _initialTargetLocalRotation = controlTarget.localRotation; + _initialTargetGlobalRotation = controlTarget.rotation; + } + + /// + /// 親から再帰的にNormalized の ローカル回転を初期回転を加味して Target に適用する。 + /// + internal void ProcessRecursively() + { + ControlTarget.localRotation = _initialTargetLocalRotation * Quaternion.Inverse(_initialTargetGlobalRotation) * ControlBone.localRotation * _initialTargetGlobalRotation; + foreach (var child in _children) + { + child.ProcessRecursively(); + } } public static Vrm10ControlBone Build(UniHumanoid.Humanoid humanoid, Dictionary boneMap) { - var hips = new Vrm10ControlBone(humanoid.Hips, Quaternion.identity, HumanBodyBones.Hips); + var hips = new Vrm10ControlBone(humanoid.Hips, HumanBodyBones.Hips); boneMap.Add(HumanBodyBones.Hips, hips); foreach (Transform child in humanoid.Hips) { - Traverse(humanoid, child, hips, boneMap); + BuildRecursively(humanoid, child, hips, boneMap); } return hips; } - private static void Traverse(UniHumanoid.Humanoid humanoid, Transform current, Vrm10ControlBone parent, Dictionary boneMap) + private static void BuildRecursively(UniHumanoid.Humanoid humanoid, Transform current, Vrm10ControlBone parent, Dictionary boneMap) { if (humanoid.TryGetBoneForTransform(current, out var bone)) { - - // ヒューマンボーンだけを対象にするので、 - // parent が current の直接の親でない場合がある。 - // ワールド回転 parent^-1 * current からローカル回転を算出する。 - var parentInverse = Quaternion.Inverse(parent.Target.rotation); - - var newBone = new Vrm10ControlBone(current, parentInverse, bone); - newBone.Normalized.SetParent(parent.Normalized, true); - parent.Children.Add(newBone); + var newBone = new Vrm10ControlBone(current, bone); + newBone.ControlBone.SetParent(parent.ControlBone, true); + parent._children.Add(newBone); parent = newBone; boneMap.Add(bone, newBone); } foreach (Transform child in current) { - Traverse(humanoid, child, parent, boneMap); - } - } - - /// - /// 親から再帰的にNormalized の ローカル回転を初期回転を加味して Target に適用する。 - /// - public void ApplyRecursive(Quaternion worldParentRotation) - { - Target.localRotation = InitialLocalRotation * Quaternion.Inverse(ToLocal) * Normalized.localRotation * ToLocal; - foreach (var child in Children) - { - child.ApplyRecursive(Normalized.rotation); + BuildRecursively(humanoid, child, parent, boneMap); } } } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 8f555e2c0..12a474a89 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -9,7 +9,14 @@ using UniVRM10.FastSpringBones.System; namespace UniVRM10 { /// - /// Play時 と Editorからの参照情報置き場 + /// VRM モデルインスタンスを、状態をもって、元の状態から操作・変更するためのクラス。 + /// また、仕様に従ってその操作を行う。 + /// + /// 操作対象としては以下が挙げられる。 + /// - ControlRig + /// - Constraint + /// - LookAt + /// - Expression /// public class Vrm10Runtime : IDisposable { diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs index 65224f4f2..bfd70716c 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs @@ -10,31 +10,31 @@ 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 class Vrm10RuntimeControlRig + public sealed class Vrm10RuntimeControlRig { private readonly Vrm10ControlBone _rootBone; private readonly Dictionary _bones = new Dictionary(); - public readonly float InitialHipsHeight; + public float InitialHipsHeight { get; } public Vrm10RuntimeControlRig(UniHumanoid.Humanoid humanoid) { _rootBone = Vrm10ControlBone.Build(humanoid, _bones); - InitialHipsHeight = _rootBone.Target.position.y; + InitialHipsHeight = _rootBone.ControlTarget.position.y; Debug.Log($"InitialHipsHeight: {InitialHipsHeight}"); } public void Process() { - _rootBone.Target.position = _rootBone.Normalized.position; - _rootBone.ApplyRecursive(Quaternion.identity); + _rootBone.ControlTarget.position = _rootBone.ControlBone.position; + _rootBone.ProcessRecursively(); } public Transform GetBoneTransform(HumanBodyBones bone) { if (_bones.TryGetValue(bone, out var value)) { - return value.Normalized; + return value.ControlBone; } else {