diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs similarity index 62% rename from Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs rename to Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs index 62b293e1a..03c2ce3df 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs +++ b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs @@ -1,121 +1,27 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Threading.Tasks; using UniGLTF; using UniHumanoid; using UniJSON; using UnityEngine; +using UniVRM10; using VRMShaders; -namespace UniVRM10.VRM10Viewer +namespace UniVRM10 { - public interface IMotion : IDisposable + + public class VrmAnimationImporter : UniGLTF.ImporterContext { - (INormalizedPoseProvider, ITPoseProvider) ControlRig { get; } - IDictionary ExpressionMap { get; } - - void ShowBoxMan(bool enable); - } - - public class BvhMotion : IMotion - { - UniHumanoid.BvhImporterContext m_context; - public Transform Root => m_context?.Root.transform; - public SkinnedMeshRenderer m_boxMan; - public SkinnedMeshRenderer BoxMan => m_boxMan; - (INormalizedPoseProvider, ITPoseProvider) m_controlRig; - (INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig; - public IDictionary ExpressionMap { get; } = new Dictionary(); - public BvhMotion(UniHumanoid.BvhImporterContext context) + public VrmAnimationImporter(GltfData data, + IReadOnlyDictionary externalObjectMap = null, + ITextureDeserializer textureDeserializer = null, + IMaterialDescriptorGenerator materialGenerator = null) + : base(data, externalObjectMap, textureDeserializer, materialGenerator) { - m_context = context; - var provider = new AnimatorPoseProvider(m_context.Root.transform, m_context.Root.GetComponent()); - m_controlRig = (provider, provider); - - // create SkinnedMesh for bone visualize - var animator = m_context.Root.GetComponent(); - m_boxMan = SkeletonMeshUtility.CreateRenderer(animator); - var material = new Material(Shader.Find("Standard")); - BoxMan.sharedMaterial = material; - var mesh = BoxMan.sharedMesh; - mesh.name = "box-man"; } - public static BvhMotion LoadBvhFromText(string source, string path = "tmp.bvh") - { - var context = new UniHumanoid.BvhImporterContext(); - context.Parse(path, source); - context.Load(); - return new BvhMotion(context); - } - public static BvhMotion LoadBvhFromPath(string path) - { - return LoadBvhFromText(File.ReadAllText(path), path); - } - - public void ShowBoxMan(bool enable) - { - m_boxMan.enabled = enable; - } - - public void Dispose() - { - GameObject.Destroy(m_context.Root); - } - } - - public class VrmAnimation : IMotion - { - UniGLTF.RuntimeGltfInstance m_instance; - public SkinnedMeshRenderer m_boxMan; - public SkinnedMeshRenderer BoxMan => m_boxMan; - (INormalizedPoseProvider, ITPoseProvider) m_controlRig; - (INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig; - public IDictionary ExpressionMap { get; } = new Dictionary(); - - public VrmAnimation(UniGLTF.RuntimeGltfInstance instance) - { - m_instance = instance; - if (instance.GetComponent() is Animation animation) - { - animation.Play(); - } - - var humanoid = instance.gameObject.AddComponent(); - if (humanoid.AssignBonesFromAnimator()) - { - var provider = new InitRotationPoseProvider(instance.transform, humanoid); - m_controlRig = (provider, provider); - - // create SkinnedMesh for bone visualize - var animator = instance.GetComponent(); - m_boxMan = SkeletonMeshUtility.CreateRenderer(animator); - var material = new Material(Shader.Find("Standard")); - BoxMan.sharedMaterial = material; - var mesh = BoxMan.sharedMesh; - mesh.name = "box-man"; - } - } - - public void ShowBoxMan(bool enable) - { - if (m_boxMan != null) - { - m_boxMan.enabled = enable; - } - } - - public void Dispose() - { - if (m_boxMan != null) - { - GameObject.Destroy(m_boxMan.gameObject); - } - } - - static int? GetNodeIndex(UniGLTF.Extensions.VRMC_vrm_animation.Humanoid humanoid, HumanBodyBones bone) + private static int? GetNodeIndex(UniGLTF.Extensions.VRMC_vrm_animation.Humanoid humanoid, HumanBodyBones bone) { switch (bone) { @@ -178,10 +84,10 @@ namespace UniVRM10.VRM10Viewer return default; } - static Dictionary GetHumanMap(GltfData data, IReadOnlyList nodes) + public Dictionary GetHumanMap() { var humanMap = new Dictionary(); - if (data.GLTF.extensions is UniGLTF.glTFExtensionImport extensions) + if (Data.GLTF.extensions is UniGLTF.glTFExtensionImport extensions) { foreach (var kv in extensions.ObjectItems()) { @@ -196,7 +102,7 @@ namespace UniVRM10.VRM10Viewer var node = GetNodeIndex(animation.Humanoid, bone); if (node.HasValue) { - humanMap.Add(bone, nodes[node.Value]); + humanMap.Add(bone, Nodes[node.Value]); } } } @@ -206,10 +112,10 @@ namespace UniVRM10.VRM10Viewer return humanMap; } - static List<(ExpressionKey, Transform)> GetExpressions(GltfData data, IReadOnlyList nodes) + public List<(ExpressionKey, Transform)> GetExpressions() { var expressions = new List<(ExpressionKey, Transform)>(); - if (data.GLTF.extensions is UniGLTF.glTFExtensionImport extensions) + if (Data.GLTF.extensions is UniGLTF.glTFExtensionImport extensions) { foreach (var kv in extensions.ObjectItems()) { @@ -223,7 +129,7 @@ namespace UniVRM10.VRM10Viewer var node = GetNodeIndex(animation.Expressions, preset); if (node.HasValue) { - expressions.Add((ExpressionKey.CreateFromPreset(preset), nodes[node.Value])); + expressions.Add((ExpressionKey.CreateFromPreset(preset), Nodes[node.Value])); } } } @@ -259,40 +165,27 @@ namespace UniVRM10.VRM10Viewer return default; } - public static async Task LoadVrmAnimationFromPathAsync(string path) + public override async Task LoadAsync(IAwaitCaller awaitCaller, Func measureTime = null) { - // - // GetHumanoid Mapping - // - using (GltfData data = new AutoGltfFileParser(path).Parse()) - using (var loader = new UniGLTF.ImporterContext(data)) + var instance = await base.LoadAsync(awaitCaller, measureTime); + + // VRMA-humanoid + var humanMap = GetHumanMap(); + if (humanMap.Count > 0) { - loader.InvertAxis = Axes.X; - var instance = await loader.LoadAsync(new ImmediateCaller()); - - // VRMA-humanoid - var humanMap = GetHumanMap(data, loader.Nodes); - if (humanMap.Count > 0) - { - var description = AvatarDescription.Create(humanMap); - // - // avatar - // - var avatar = description.CreateAvatar(instance.Root.transform); - avatar.name = "Avatar"; - // AvatarDescription = description; - var animator = instance.gameObject.AddComponent(); - animator.avatar = avatar; - } - - // VRMA-expression - var animation = new VrmAnimation(instance); - foreach (var (preset, transform) in GetExpressions(data, loader.Nodes)) - { - animation.ExpressionMap.Add(preset, transform); - } - return animation; + var description = AvatarDescription.Create(humanMap); + // + // avatar + // + var avatar = description.CreateAvatar(instance.Root.transform); + avatar.name = "Avatar"; + // AvatarDescription = description; + var animator = instance.gameObject.AddComponent(); + animator.avatar = avatar; } + + return instance; } + } } diff --git a/Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs.meta b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs.meta similarity index 83% rename from Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs.meta rename to Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs.meta index a3c573986..33367c278 100644 --- a/Assets/VRM10_Samples/VRM10Viewer/VRM10Motion.cs.meta +++ b/Assets/VRM10/Runtime/IO/VrmAnimationImporter.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 08f06b12436bf594b9982c6a8ec71374 +guid: 0381f410b38d5184baa6f28213608810 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs new file mode 100644 index 000000000..0a801d555 --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using System.IO; +using UniHumanoid; +using UnityEngine; + +namespace UniVRM10.VRM10Viewer +{ + public class BvhMotion : IMotion + { + UniHumanoid.BvhImporterContext m_context; + public Transform Root => m_context?.Root.transform; + public SkinnedMeshRenderer m_boxMan; + public SkinnedMeshRenderer BoxMan => m_boxMan; + (INormalizedPoseProvider, ITPoseProvider) m_controlRig; + (INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig; + public IDictionary ExpressionMap { get; } = new Dictionary(); + public BvhMotion(UniHumanoid.BvhImporterContext context) + { + m_context = context; + var provider = new AnimatorPoseProvider(m_context.Root.transform, m_context.Root.GetComponent()); + m_controlRig = (provider, provider); + + // create SkinnedMesh for bone visualize + var animator = m_context.Root.GetComponent(); + m_boxMan = SkeletonMeshUtility.CreateRenderer(animator); + var material = new Material(Shader.Find("Standard")); + BoxMan.sharedMaterial = material; + var mesh = BoxMan.sharedMesh; + mesh.name = "box-man"; + } + + public static BvhMotion LoadBvhFromText(string source, string path = "tmp.bvh") + { + var context = new UniHumanoid.BvhImporterContext(); + context.Parse(path, source); + context.Load(); + return new BvhMotion(context); + } + public static BvhMotion LoadBvhFromPath(string path) + { + return LoadBvhFromText(File.ReadAllText(path), path); + } + + public void ShowBoxMan(bool enable) + { + m_boxMan.enabled = enable; + } + + public void Dispose() + { + GameObject.Destroy(m_context.Root); + } + } +} diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs.meta b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs.meta new file mode 100644 index 000000000..32ed60374 --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/BvhMotion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bed75b815cb24843a50063a9dd7376e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs b/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs new file mode 100644 index 000000000..656548b24 --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UniVRM10.VRM10Viewer +{ + public interface IMotion : IDisposable + { + (INormalizedPoseProvider, ITPoseProvider) ControlRig { get; } + IDictionary ExpressionMap { get; } + + void ShowBoxMan(bool enable); + } +} diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs.meta b/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs.meta new file mode 100644 index 000000000..bdc7beafd --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/IMotion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd8db8a4bdc3e7f40a0a7a1bcd554137 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs b/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs new file mode 100644 index 000000000..d2cd6c63b --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using UniGLTF; +using UniHumanoid; +using UnityEngine; +using VRMShaders; + +namespace UniVRM10.VRM10Viewer +{ + public class VrmAnimation : IMotion + { + private RuntimeGltfInstance m_instance; + public SkinnedMeshRenderer m_boxMan; + public SkinnedMeshRenderer BoxMan => m_boxMan; + private (INormalizedPoseProvider, ITPoseProvider) m_controlRig; + (INormalizedPoseProvider, ITPoseProvider) IMotion.ControlRig => m_controlRig; + public IDictionary ExpressionMap { get; } = new Dictionary(); + + public VrmAnimation(RuntimeGltfInstance instance) + { + m_instance = instance; + if (instance.GetComponent() is Animation animation) + { + animation.Play(); + } + + var humanoid = instance.gameObject.AddComponent(); + if (humanoid.AssignBonesFromAnimator()) + { + var provider = new InitRotationPoseProvider(instance.transform, humanoid); + m_controlRig = (provider, provider); + + // create SkinnedMesh for bone visualize + var animator = instance.GetComponent(); + m_boxMan = SkeletonMeshUtility.CreateRenderer(animator); + var material = new Material(Shader.Find("Standard")); + BoxMan.sharedMaterial = material; + var mesh = BoxMan.sharedMesh; + mesh.name = "box-man"; + } + } + + public void ShowBoxMan(bool enable) + { + if (m_boxMan != null) + { + m_boxMan.enabled = enable; + } + } + + public void Dispose() + { + if (m_boxMan != null) + { + GameObject.Destroy(m_boxMan.gameObject); + } + } + + public static async Task LoadVrmAnimationFromPathAsync(string path) + { + using (GltfData data = new AutoGltfFileParser(path).Parse()) + using (var loader = new VrmAnimationImporter(data)) + { + loader.InvertAxis = Axes.X; + var instance = await loader.LoadAsync(new ImmediateCaller()); + + var animation = new VrmAnimation(instance); + foreach (var (preset, transform) in loader.GetExpressions()) + { + animation.ExpressionMap.Add(preset, transform); + } + return animation; + } + } + } +} diff --git a/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs.meta b/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs.meta new file mode 100644 index 000000000..1ea946b9b --- /dev/null +++ b/Assets/VRM10_Samples/VRM10Viewer/Motions/VrmAnimation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0180f844d447bc45889d6c72a2d4ec4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: