diff --git a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs index b7f42c40a..a48ef5733 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs @@ -67,12 +67,8 @@ namespace UniVRM10 /// /// ControlRig の生成オプション - /// - /// null: ControlRigGenerationOption.None - /// empty: ControlRigGenerationOption.Generate = Vrm0XCompatibleRig - /// other: ControlRigGenerationOption.Vrm0XCompatibleWithXR_EXT_hand_tracking など /// - private IReadOnlyDictionary m_controlRigInitialRotations; + private bool m_useControlRig; /// /// VRM ファイルに記録された Humanoid ボーンに対応します。 @@ -99,15 +95,15 @@ namespace UniVRM10 { if (m_runtime == null) { - m_runtime = new Vrm10Runtime(this, m_controlRigInitialRotations); + m_runtime = new Vrm10Runtime(this, m_useControlRig); } return m_runtime; } } - internal void InitializeAtRuntime(IReadOnlyDictionary controlRigInitialRotations) + internal void InitializeAtRuntime(bool useControlRig) { - m_controlRigInitialRotations = controlRigInitialRotations; + m_useControlRig = useControlRig; } void Start() diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 6850b680b..29182017f 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -49,7 +49,7 @@ namespace UniVRM10 } } - public Vrm10Runtime(Vrm10Instance target, IReadOnlyDictionary controlRigInitialRotations) + public Vrm10Runtime(Vrm10Instance target, bool useControlRig) { m_target = target; @@ -58,9 +58,9 @@ namespace UniVRM10 throw new Exception(); } - if (controlRigInitialRotations != null) + if (useControlRig) { - ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform, controlRigInitialRotations); + ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform); } Constraints = target.GetComponentsInChildren(); LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, ControlRig); diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs index 681cf681d..c6c13c6df 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs @@ -29,18 +29,12 @@ namespace UniVRM10 /// /// T-Pose である必要があります /// - /// ControlRigの各ボーンの初期回転を表します - public Vrm10RuntimeControlRig(UniHumanoid.Humanoid humanoid, Transform vrmRoot, IReadOnlyDictionary controlRigInitialRotations) + public Vrm10RuntimeControlRig(UniHumanoid.Humanoid humanoid, Transform vrmRoot) { - if (controlRigInitialRotations == null) - { - throw new ArgumentNullException(); - } - _controlRigRoot = new GameObject("Runtime Control Rig").transform; _controlRigRoot.SetParent(vrmRoot); - _hipBone = Vrm10ControlBone.Build(humanoid, controlRigInitialRotations, out _bones); + _hipBone = Vrm10ControlBone.Build(humanoid, out _bones); _hipBone.ControlBone.SetParent(_controlRigRoot); InitialHipsHeight = _hipBone.ControlTarget.position.y; @@ -79,10 +73,11 @@ namespace UniVRM10 public void EnforceTPose() { + // TODO: restore hips position + foreach (var bone in _bones.Values) { - bone.ControlBone.localPosition = bone.InitialControlBoneLocalPosition; - bone.ControlBone.localRotation = bone.InitialControlBoneLocalRotation; + bone.ControlBone.localRotation = Quaternion.identity; } } } diff --git a/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs b/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs index d99dfc4de..4268f59d8 100644 --- a/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs +++ b/Assets/VRM10/Runtime/ControlRig/InitialRotations/ControlRigGenerationOption.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using UnityEngine; - -namespace UniVRM10 +namespace UniVRM10 { public enum ControlRigGenerationOption { @@ -17,44 +13,5 @@ namespace UniVRM10 /// Generate = 1, Vrm0XCompatibleRig = 1, - - /// - /// コントロールリグのボーン Transform を生成し、Root の Animator はコントロールリグのボーンを制御するようになります。 - /// 手と指に関して、XR_EXT_hand_tracking の初期回転を持ちます。 - /// https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_hand_tracking - /// - Vrm0XCompatibleWithXR_EXT_hand_tracking = 2, - - /// - /// コントロールリグのボーン Transform を生成し、Root の Animator はコントロールリグのボーンを制御するようになります。 - /// 上半身に関して、XR_FB_body_tracking の初期回転を持ちます。 - /// https://developer.oculus.com/documentation/native/android/move-ref-body-joints/ - /// - Vrm0XCompatibleWithXR_FB_body_tracking = 3, - } - - internal static class ControlRigGenerationOptionExtensions - { - internal static IReadOnlyDictionary ToInitialRotations(this ControlRigGenerationOption option) - { - switch (option) - { - case ControlRigGenerationOption.None: - return null; - - case ControlRigGenerationOption.Generate: - // case ControlRigGenerationOption.Vrm0XCompatibleRig: - return Vrm0XCompatibleRig.InitialRotations; - - case ControlRigGenerationOption.Vrm0XCompatibleWithXR_EXT_hand_tracking: - return XR_EXT_hand_tracking.InitialRotations; - - case ControlRigGenerationOption.Vrm0XCompatibleWithXR_FB_body_tracking: - return XR_FB_body_tracking.InitialRotations; - - default: - throw new ArgumentException(); - } - } } } diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs b/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs new file mode 100644 index 000000000..ffdb5b7a0 --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs @@ -0,0 +1,39 @@ +using UnityEngine; + +namespace UniVRM10 +{ + /// + /// Represents the rotation at the initial pose (TPose) + /// + public readonly struct Vrm10BoneInitialRotation + { + public readonly Transform Transform; + + public readonly Vector3 InitialLocalPosition; + + public readonly Quaternion InitialLocalRotation; + + public readonly Quaternion InitialGlobalRotation; + + public Vrm10BoneInitialRotation(Transform transform) + { + Transform = transform; + InitialLocalPosition = transform.localPosition; + InitialLocalRotation = transform.localRotation; + InitialGlobalRotation = transform.rotation; + } + + /// + /// 初期姿勢からの相対的な回転。 + /// + /// VRM-0.X 互換リグでは localRotation と同じ値を示す。 + /// + Quaternion NormalizedLocalRotation + { + get + { + return InitialGlobalRotation * Quaternion.Inverse(InitialLocalRotation) * Transform.localRotation * Quaternion.Inverse(InitialGlobalRotation); + } + } + } +} diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs.meta b/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs.meta new file mode 100644 index 000000000..dd0a4eec9 --- /dev/null +++ b/Assets/VRM10/Runtime/ControlRig/Vrm10BoneInitialRotation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db1187bf0b13152439c8a145d9631916 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs b/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs index 3a697bf35..a10fcaba1 100644 --- a/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs +++ b/Assets/VRM10/Runtime/ControlRig/Vrm10ControlBone.cs @@ -31,22 +31,11 @@ namespace UniVRM10 /// public Transform ControlBone { get; } - /// - /// コントロールボーンの初期ローカル位置。 - /// - public Vector3 InitialControlBoneLocalPosition { get; } - - /// - /// コントロールボーンの初期ローカル回転。 - /// - public Quaternion InitialControlBoneLocalRotation { get; } - - private readonly Quaternion _initialControlBoneGlobalRotation; private readonly Quaternion _initialTargetLocalRotation; private readonly Quaternion _initialTargetGlobalRotation; private readonly List _children = new List(); - private Vrm10ControlBone(Transform controlTarget, HumanBodyBones boneType, Vrm10ControlBone parent, IReadOnlyDictionary controlRigInitialRotations) + private Vrm10ControlBone(Transform controlTarget, HumanBodyBones boneType, Vrm10ControlBone parent) { if (boneType == HumanBodyBones.LastBone) { @@ -59,81 +48,59 @@ namespace UniVRM10 BoneType = boneType; ControlTarget = controlTarget; + + // 回転とスケールが除去されたTPoseを構築 // NOTE: bone name must be unique in the vrm instance. ControlBone = new GameObject($"{nameof(Vrm10ControlBone)}:{boneType.ToString()}").transform; - if (controlRigInitialRotations != null) - { - if (controlRigInitialRotations.TryGetValue(boneType, out var rotation)) - { - ControlBone.rotation = rotation; - } - } ControlBone.position = controlTarget.position; - if (parent != null) { ControlBone.SetParent(parent.ControlBone, true); parent._children.Add(this); } - InitialControlBoneLocalPosition = ControlBone.localPosition; - InitialControlBoneLocalRotation = ControlBone.localRotation; - _initialControlBoneGlobalRotation = ControlBone.rotation; _initialTargetLocalRotation = controlTarget.localRotation; _initialTargetGlobalRotation = controlTarget.rotation; } - /// - /// 初期姿勢からの相対的な回転。 - /// - /// VRM-0.X 互換リグでは localRotation と同じ値を示す。 - /// - Quaternion NormalizedLocalRotation - { - get - { - return _initialControlBoneGlobalRotation * Quaternion.Inverse(InitialControlBoneLocalRotation) * ControlBone.localRotation * Quaternion.Inverse(_initialControlBoneGlobalRotation); - } - } - /// /// 親から再帰的にNormalized の ローカル回転を初期回転を加味して Target に適用する。 /// internal void ProcessRecursively() { - ControlTarget.localRotation = _initialTargetLocalRotation * (Quaternion.Inverse(_initialTargetGlobalRotation) * NormalizedLocalRotation * _initialTargetGlobalRotation); + ControlTarget.localRotation = _initialTargetLocalRotation * (Quaternion.Inverse(_initialTargetGlobalRotation) * ControlBone.localRotation * _initialTargetGlobalRotation); foreach (var child in _children) { child.ProcessRecursively(); } } - public static Vrm10ControlBone Build(UniHumanoid.Humanoid humanoid, IReadOnlyDictionary controlRigInitialRotations, out Dictionary boneMap) + public static Vrm10ControlBone Build(UniHumanoid.Humanoid humanoid, out Dictionary boneMap) { - var hips = new Vrm10ControlBone(humanoid.Hips, HumanBodyBones.Hips, null, controlRigInitialRotations); + var hips = new Vrm10ControlBone(humanoid.Hips, HumanBodyBones.Hips, null); boneMap = new Dictionary(); boneMap.Add(HumanBodyBones.Hips, hips); foreach (Transform child in humanoid.Hips) { - BuildRecursively(humanoid, child, hips, controlRigInitialRotations, boneMap); + BuildRecursively(humanoid, child, hips, boneMap); } return hips; } - private static void BuildRecursively(UniHumanoid.Humanoid humanoid, Transform current, Vrm10ControlBone parent, IReadOnlyDictionary controlRigInitialRotations, Dictionary boneMap) + private static void BuildRecursively(UniHumanoid.Humanoid humanoid, Transform current, Vrm10ControlBone parent, Dictionary boneMap) { if (humanoid.TryGetBoneForTransform(current, out var bone)) { - var newBone = new Vrm10ControlBone(current, bone, parent, controlRigInitialRotations); + var newBone = new Vrm10ControlBone(current, bone, parent); parent = newBone; boneMap.Add(bone, newBone); } foreach (Transform child in current) { - BuildRecursively(humanoid, child, parent, controlRigInitialRotations, boneMap); + BuildRecursively(humanoid, child, parent, boneMap); } } } diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index b1b433fe8..73904892f 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -293,7 +293,7 @@ namespace UniVRM10 vrm10Data, textureDeserializer: textureDeserializer, materialGenerator: materialGenerator, - controlRigInitialRotations: controlRigGenerationOption.ToInitialRotations())) + useControlRig: controlRigGenerationOption != ControlRigGenerationOption.None)) { // 1. Load meta information if callback was available. if (vrmMetaInformationCallback != null) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index 5f86c25b2..ef90adc1d 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -18,7 +18,7 @@ namespace UniVRM10 private readonly Vrm10Data m_vrm; /// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する private readonly ModelMap m_map = new ModelMap(); - private readonly IReadOnlyDictionary m_controlRigInitialRotations; + private readonly bool m_useControlRig; private VrmLib.Model m_model; private IReadOnlyDictionary m_externalMap; @@ -31,7 +31,7 @@ namespace UniVRM10 IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, IMaterialDescriptorGenerator materialGenerator = null, - IReadOnlyDictionary controlRigInitialRotations = null + bool useControlRig = false ) : base(vrm.Data, externalObjectMap, textureDeserializer) { @@ -40,7 +40,7 @@ namespace UniVRM10 throw new ArgumentNullException("vrm"); } m_vrm = vrm; - m_controlRigInitialRotations = controlRigInitialRotations; + m_useControlRig = useControlRig; TextureDescriptorGenerator = new Vrm10TextureDescriptorGenerator(Data); MaterialDescriptorGenerator = materialGenerator ?? new BuiltInVrm10MaterialDescriptorGenerator(); @@ -247,7 +247,7 @@ namespace UniVRM10 // VrmController var controller = Root.AddComponent(); - controller.InitializeAtRuntime(m_controlRigInitialRotations); + controller.InitializeAtRuntime(m_useControlRig); controller.enabled = false; // vrm diff --git a/Assets/VRM10/Tests/ExpressionTests.cs b/Assets/VRM10/Tests/ExpressionTests.cs index 99e832566..f097d503d 100644 --- a/Assets/VRM10/Tests/ExpressionTests.cs +++ b/Assets/VRM10/Tests/ExpressionTests.cs @@ -32,7 +32,7 @@ namespace UniVRM10.Test controller.Vrm.Expression.Aa.MaterialColorBindings = src.ToArray(); // ok if no exception - var r = new Vrm10Runtime(controller, null); + var r = new Vrm10Runtime(controller, useControlRig: false); } [Test] @@ -56,7 +56,7 @@ namespace UniVRM10.Test controller.Vrm.Expression.Aa.MaterialUVBindings = src.ToArray(); // ok if no exception - var r = new Vrm10Runtime(controller, null); + var r = new Vrm10Runtime(controller, useControlRig: false); } } } diff --git a/Assets/VRM10/Tests/MigrationTests.cs b/Assets/VRM10/Tests/MigrationTests.cs index 75695ac67..fab6ee3c2 100644 --- a/Assets/VRM10/Tests/MigrationTests.cs +++ b/Assets/VRM10/Tests/MigrationTests.cs @@ -199,7 +199,7 @@ namespace UniVRM10 { try { - Vrm10.LoadPathAsync(gltf.FullName, true, ControlRigGenerationOption.None).Wait(); + Vrm10.LoadPathAsync(gltf.FullName, true, controlRigGenerationOption: ControlRigGenerationOption.None).Wait(); } catch (UnNormalizedException) {