From f06d4bdd358d721ba8f6ea8191522819b40a24aa Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 7 Sep 2022 16:36:29 +0900 Subject: [PATCH 1/4] Create the ControlRig at a child of the VRM instance root. --- .../Components/Vrm10Runtime/Vrm10Runtime.cs | 15 ++++++----- .../Vrm10Runtime/Vrm10RuntimeControlRig.cs | 26 ++++++++++++++----- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 1138f08ee..5d96bb2e1 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -42,7 +42,7 @@ namespace UniVRM10 throw new Exception(); } - ControlRig = new Vrm10RuntimeControlRig(target.Humanoid); + ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform); Constraints = target.GetComponentsInChildren(); LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, m_head, target.LookAtTargetType, target.Gaze); Expression = new Vrm10RuntimeExpression(target, LookAt, LookAt.EyeDirectionApplicable); @@ -69,6 +69,13 @@ namespace UniVRM10 } } + public void Dispose() + { + ControlRig.Dispose(); + m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); + m_fastSpringBoneBuffer.Dispose(); + } + /// /// このVRMに紐づくSpringBone関連のバッファを再構築する /// ランタイム実行時にSpringBoneに対して変更を行いたいときは、このメソッドを明示的に呼ぶ必要がある @@ -169,11 +176,5 @@ namespace UniVRM10 // 4. Expression Expression.Process(); } - - public void Dispose() - { - m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); - m_fastSpringBoneBuffer.Dispose(); - } } } \ No newline at end of file diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs index 9adbeb807..d038a9cda 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using UnityEngine; @@ -10,9 +11,10 @@ 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 + public sealed class Vrm10RuntimeControlRig : IDisposable { - private readonly Vrm10ControlBone _rootBone; + private readonly Transform _controlRigRoot; + private readonly Vrm10ControlBone _hipBone; private readonly Dictionary _bones; public float InitialHipsHeight { get; } @@ -21,16 +23,26 @@ namespace UniVRM10 /// コンストラクタ。 /// humanoid は VRM T-Pose でなければならない。 /// - public Vrm10RuntimeControlRig(UniHumanoid.Humanoid humanoid) + public Vrm10RuntimeControlRig(UniHumanoid.Humanoid humanoid, Transform vrmRoot) { - _rootBone = Vrm10ControlBone.Build(humanoid, out _bones); - InitialHipsHeight = _rootBone.ControlTarget.position.y; + _controlRigRoot = new GameObject("Runtime Control Rig").transform; + _controlRigRoot.SetParent(vrmRoot); + + _hipBone = Vrm10ControlBone.Build(humanoid, out _bones); + _hipBone.ControlBone.SetParent(_controlRigRoot); + + InitialHipsHeight = _hipBone.ControlTarget.position.y; + } + + public void Dispose() + { + UnityEngine.Object.Destroy(_controlRigRoot); } internal void Process() { - _rootBone.ControlTarget.position = _rootBone.ControlBone.position; - _rootBone.ProcessRecursively(); + _hipBone.ControlTarget.position = _hipBone.ControlBone.position; + _hipBone.ProcessRecursively(); } public Transform GetBoneTransform(HumanBodyBones bone) From 12ac6e372ed5647b9d26a044cfa9e7f842395da6 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 7 Sep 2022 16:44:43 +0900 Subject: [PATCH 2/4] Apply localPosition while bvh motion transfer in VRM10 Viewer. --- Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs index b99f1e17e..a400bd797 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs +++ b/Assets/VRM10_Samples/VRM10Viewer/VRM10ViewerUI.cs @@ -301,7 +301,7 @@ namespace UniVRM10.VRM10Viewer if (bone == HumanBodyBones.Hips) { - controlRigBone.position = bvhBone.position * controlRig.InitialHipsHeight; + controlRigBone.localPosition = bvhBone.localPosition * controlRig.InitialHipsHeight; } } else From e7ed265d67b6e46d2889ade6eaa05b8d0b238518 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 7 Sep 2022 18:22:11 +0900 Subject: [PATCH 3/4] refactoring --- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 34 ++++++++++-------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index 0d6a2b495..5b5cd31c3 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -15,11 +15,15 @@ namespace UniVRM10 /// public class Vrm10Importer : UniGLTF.ImporterContext { - VrmLib.Model m_model; + private readonly Vrm10Data m_vrm; + /// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する + private readonly ModelMap m_map = new ModelMap(); - readonly Vrm10Data m_vrm; - - IReadOnlyDictionary m_externalMap; + private VrmLib.Model m_model; + private IReadOnlyDictionary m_externalMap; + private Avatar m_humanoid; + private VRM10Object m_vrmObject; + private List<(ExpressionPreset Preset, VRM10Expression Clip)> m_expressions = new List<(ExpressionPreset, VRM10Expression)>(); public Vrm10Importer( Vrm10Data vrm, @@ -44,18 +48,6 @@ namespace UniVRM10 } } - public class ModelMap - { - public readonly Dictionary Nodes = new Dictionary(); - public readonly Dictionary Meshes = new Dictionary(); - } - - /// - /// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する - /// - /// - readonly ModelMap m_map = new ModelMap(); - static void AssignHumanoid(List nodes, UniGLTF.Extensions.VRMC_vrm.HumanBone humanBone, VrmLib.HumanoidBones key) { if (nodes == null) @@ -237,10 +229,6 @@ namespace UniVRM10 } } - UnityEngine.Avatar m_humanoid; - VRM10Object m_vrmObject; - List<(ExpressionPreset Preset, VRM10Expression Clip)> m_expressions = new List<(ExpressionPreset, VRM10Expression)>(); - protected override async Task OnLoadHierarchy(IAwaitCaller awaitCaller, Func MeasureTime) { Root.name = "VRM1"; @@ -847,5 +835,11 @@ namespace UniVRM10 base.Dispose(); } + + public sealed class ModelMap + { + public readonly Dictionary Nodes = new Dictionary(); + public readonly Dictionary Meshes = new Dictionary(); + } } } \ No newline at end of file From 9c88a9761c3878c62f0bff5ea1008a24d4dbb613 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Wed, 7 Sep 2022 18:51:23 +0900 Subject: [PATCH 4/4] Add generateControlRig option to VRM 1.0 Importer --- .../Components/Vrm10Instance/Vrm10Instance.cs | 13 +++++++++---- .../Components/Vrm10Runtime/Vrm10Runtime.cs | 9 ++++++--- .../Vrm10Runtime/Vrm10RuntimeControlRig.cs | 12 ++++++++++++ Assets/VRM10/Runtime/IO/Vrm10.cs | 16 +++++++++++++++- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 6 +++++- Assets/VRM10/Tests/ExpressionTests.cs | 4 ++-- 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs index 809ea6736..16199a6ec 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Instance/Vrm10Instance.cs @@ -50,7 +50,9 @@ namespace UniVRM10 [SerializeField] public VRM10ObjectLookAt.LookAtTargetTypes LookAtTargetType; - UniHumanoid.Humanoid m_humanoid; + private UniHumanoid.Humanoid m_humanoid; + private Vrm10Runtime m_runtime; + private bool m_generateControlRig = false; public UniHumanoid.Humanoid Humanoid { @@ -64,8 +66,6 @@ namespace UniVRM10 } } - Vrm10Runtime m_runtime; - /// /// ランタイム情報 /// @@ -75,12 +75,17 @@ namespace UniVRM10 { if (m_runtime == null) { - m_runtime = new Vrm10Runtime(this); + m_runtime = new Vrm10Runtime(this, m_generateControlRig); } return m_runtime; } } + internal void InitializeAtRuntime(bool generateControlRig) + { + m_generateControlRig = generateControlRig; + } + void Start() { // cause new Vrm10Runtime. diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs index 5d96bb2e1..18872aa83 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10Runtime.cs @@ -33,7 +33,7 @@ namespace UniVRM10 public Vrm10RuntimeExpression Expression { get; } public Vrm10RuntimeLookAt LookAt { get; } - public Vrm10Runtime(Vrm10Instance target) + public Vrm10Runtime(Vrm10Instance target, bool generateControlRig) { m_target = target; @@ -42,7 +42,10 @@ namespace UniVRM10 throw new Exception(); } - ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform); + if (generateControlRig) + { + ControlRig = new Vrm10RuntimeControlRig(target.Humanoid, m_target.transform); + } Constraints = target.GetComponentsInChildren(); LookAt = new Vrm10RuntimeLookAt(target.Vrm.LookAt, target.Humanoid, m_head, target.LookAtTargetType, target.Gaze); Expression = new Vrm10RuntimeExpression(target, LookAt, LookAt.EyeDirectionApplicable); @@ -71,7 +74,7 @@ namespace UniVRM10 public void Dispose() { - ControlRig.Dispose(); + ControlRig?.Dispose(); m_fastSpringBoneService.BufferCombiner.Unregister(m_fastSpringBoneBuffer); m_fastSpringBoneBuffer.Dispose(); } diff --git a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs index d038a9cda..fb4acf273 100644 --- a/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs +++ b/Assets/VRM10/Runtime/Components/Vrm10Runtime/Vrm10RuntimeControlRig.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using UniHumanoid; using UnityEngine; namespace UniVRM10 @@ -16,7 +18,10 @@ namespace UniVRM10 private readonly Transform _controlRigRoot; private readonly Vrm10ControlBone _hipBone; private readonly Dictionary _bones; + private readonly Avatar _controlRigAvatar; + public IReadOnlyDictionary Bones => _bones; + public Animator ControlRigAnimator { get; } public float InitialHipsHeight { get; } /// @@ -32,10 +37,17 @@ namespace UniVRM10 _hipBone.ControlBone.SetParent(_controlRigRoot); InitialHipsHeight = _hipBone.ControlTarget.position.y; + + var transformBonePairs = _bones.Select(kv => (kv.Value.ControlBone, kv.Key)); + _controlRigAvatar = HumanoidLoader.LoadHumanoidAvatar(_controlRigRoot, transformBonePairs); + _controlRigAvatar.name = "Runtime Control Rig"; + ControlRigAnimator = _controlRigRoot.gameObject.AddComponent(); + ControlRigAnimator.avatar = _controlRigAvatar; } public void Dispose() { + UnityEngine.Object.Destroy(_controlRigAvatar); UnityEngine.Object.Destroy(_controlRigRoot); } diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index 78453a442..55e51eecc 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -27,6 +27,7 @@ namespace UniVRM10 /// /// vrm file path /// if true, this loader can load the vrm-0.x model as vrm-1.0 model with migration. + /// if true, generating the control rig provides bone manipulation like vrm-0.x /// if true, show meshes when loaded. /// this loader use specified await strategy. /// this loader use specified material generation strategy. @@ -36,6 +37,7 @@ namespace UniVRM10 public static async Task LoadPathAsync( string path, bool canLoadVrm0X = true, + bool generateControlRig = true, bool showMeshes = true, IAwaitCaller awaitCaller = null, IMaterialDescriptorGenerator materialGenerator = null, @@ -53,6 +55,7 @@ namespace UniVRM10 path, System.IO.File.ReadAllBytes(path), canLoadVrm0X, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -68,6 +71,7 @@ namespace UniVRM10 /// /// vrm file data /// if true, this loader can load the vrm-0.x model as vrm-1.0 model with migration. + /// if true, generating the control rig provides bone manipulation like vrm-0.x /// if true, show meshes when loaded. /// this loader use specified await strategy. /// this loader use specified material generation strategy. @@ -77,6 +81,7 @@ namespace UniVRM10 public static async Task LoadBytesAsync( byte[] bytes, bool canLoadVrm0X = true, + bool generateControlRig = true, bool showMeshes = true, IAwaitCaller awaitCaller = null, IMaterialDescriptorGenerator materialGenerator = null, @@ -94,6 +99,7 @@ namespace UniVRM10 string.Empty, bytes, canLoadVrm0X, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -105,6 +111,7 @@ namespace UniVRM10 string name, byte[] bytes, bool canLoadVrm0X, + bool generateControlRig, bool showMeshes, IAwaitCaller awaitCaller, IMaterialDescriptorGenerator materialGenerator, @@ -122,6 +129,7 @@ namespace UniVRM10 // 1. Try loading as vrm-1.0 var instance = await TryLoadingAsVrm10Async( gltfData, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -146,6 +154,7 @@ namespace UniVRM10 // 3. Try migration from vrm-0.x into vrm-1.0 var migratedInstance = await TryMigratingFromVrm0XAsync( gltfData, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -168,6 +177,7 @@ namespace UniVRM10 private static async Task TryLoadingAsVrm10Async( GltfData gltfData, + bool generateControlRig, bool showMeshes, IAwaitCaller awaitCaller, IMaterialDescriptorGenerator materialGenerator, @@ -192,6 +202,7 @@ namespace UniVRM10 return await LoadVrm10DataAsync( vrm10Data, null, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -201,6 +212,7 @@ namespace UniVRM10 private static async Task TryMigratingFromVrm0XAsync( GltfData gltfData, + bool generateControlRig, bool showMeshes, IAwaitCaller awaitCaller, IMaterialDescriptorGenerator materialGenerator, @@ -227,6 +239,7 @@ namespace UniVRM10 var migratedVrm10Instance = await LoadVrm10DataAsync( migratedVrm10Data, migrationData, + generateControlRig, showMeshes, awaitCaller, materialGenerator, @@ -243,6 +256,7 @@ namespace UniVRM10 private static async Task LoadVrm10DataAsync( Vrm10Data vrm10Data, MigrationData migrationData, + bool generateControlRig, bool showMeshes, IAwaitCaller awaitCaller, IMaterialDescriptorGenerator materialGenerator, @@ -260,7 +274,7 @@ namespace UniVRM10 throw new ArgumentNullException(nameof(vrm10Data)); } - using (var loader = new Vrm10Importer(vrm10Data, materialGenerator: materialGenerator)) + using (var loader = new Vrm10Importer(vrm10Data, generateControlRig: generateControlRig, materialGenerator: materialGenerator)) { // 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 5b5cd31c3..b6261f30a 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -18,6 +18,7 @@ namespace UniVRM10 private readonly Vrm10Data m_vrm; /// VrmLib.Model の オブジェクトと UnityEngine.Object のマッピングを記録する private readonly ModelMap m_map = new ModelMap(); + private readonly bool m_generateControlRig; private VrmLib.Model m_model; private IReadOnlyDictionary m_externalMap; @@ -29,7 +30,8 @@ namespace UniVRM10 Vrm10Data vrm, IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null, - IMaterialDescriptorGenerator materialGenerator = null) + IMaterialDescriptorGenerator materialGenerator = null, + bool generateControlRig = false) : base(vrm.Data, externalObjectMap, textureDeserializer) { if (vrm == null) @@ -37,6 +39,7 @@ namespace UniVRM10 throw new ArgumentNullException("vrm"); } m_vrm = vrm; + m_generateControlRig = generateControlRig; TextureDescriptorGenerator = new Vrm10TextureDescriptorGenerator(Data); MaterialDescriptorGenerator = materialGenerator ?? new Vrm10MaterialDescriptorGenerator(); @@ -243,6 +246,7 @@ namespace UniVRM10 // VrmController var controller = Root.AddComponent(); + controller.InitializeAtRuntime(m_generateControlRig); controller.enabled = false; // vrm diff --git a/Assets/VRM10/Tests/ExpressionTests.cs b/Assets/VRM10/Tests/ExpressionTests.cs index d176cb3e9..dfd370363 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); + var r = new Vrm10Runtime(controller, 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); + var r = new Vrm10Runtime(controller, false); } } }