From 50078af9bcee9ba0021bc5dec7a0f0b34bb7f44d Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 8 Apr 2021 17:15:56 +0900 Subject: [PATCH] ExportExpression --- Assets/VRM10/Editor/Vrm10ExportDialog.cs | 6 +- Assets/VRM10/Runtime/IO/ModelExtensions.cs | 2 +- Assets/VRM10/Runtime/IO/Vrm10Exporter.cs | 146 ++++++++++++++++-- .../VRM10/Runtime/Scenes/ExportDebugUtil.cs | 2 +- .../Extensions/ArraySegmentExtensions.cs.meta | 11 -- 5 files changed, 138 insertions(+), 29 deletions(-) delete mode 100644 Assets/VRM10/vrmlib/Runtime/Extensions/ArraySegmentExtensions.cs.meta diff --git a/Assets/VRM10/Editor/Vrm10ExportDialog.cs b/Assets/VRM10/Editor/Vrm10ExportDialog.cs index ecc9bab1f..90f8768b3 100644 --- a/Assets/VRM10/Editor/Vrm10ExportDialog.cs +++ b/Assets/VRM10/Editor/Vrm10ExportDialog.cs @@ -302,7 +302,8 @@ namespace UniVRM10 try { - var model = new UniVRM10.RuntimeVrmConverter().ToModelFrom10(root); + var converter = new UniVRM10.RuntimeVrmConverter(); + var model = converter.ToModelFrom10(root); // if (MeshUtility.Validators.HumanoidValidator.HasRotationOrScale(root)) // { @@ -316,11 +317,10 @@ namespace UniVRM10 m_logLabel += $"convert to right handed coordinate...\n"; model.ConvertCoordinate(VrmLib.Coordinates.Vrm1, ignoreVrm: false); - // var exportedBytes = GetGlb(model); // export vrm-1.0 var exporter = new UniVRM10.Vrm10Exporter(AssetTextureUtil.IsTextureEditorAsset); var option = new VrmLib.ExportArgs(); - exporter.Export(root, model, option, Meta ? Meta : m_tmpMeta); + exporter.Export(root, model, converter, option, Meta ? Meta : m_tmpMeta); var exportedBytes = exporter.Storage.ToBytes(); diff --git a/Assets/VRM10/Runtime/IO/ModelExtensions.cs b/Assets/VRM10/Runtime/IO/ModelExtensions.cs index 2aadc8b46..3f8a29204 100644 --- a/Assets/VRM10/Runtime/IO/ModelExtensions.cs +++ b/Assets/VRM10/Runtime/IO/ModelExtensions.cs @@ -12,7 +12,7 @@ namespace UniVRM10 { // vrm = false }; - exporter10.Export(null, model, option); + exporter10.Export(null, model, null, option); var glb10 = UniGLTF.Glb.Parse(exporter10.Storage.ToBytes()); return glb10.ToBytes(); } diff --git a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs index 92f9b4b67..4447de46a 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Exporter.cs @@ -118,7 +118,7 @@ namespace UniVRM10 }); } - public void Export(GameObject root, Model model, ExportArgs option, VRM10MetaObject metaObject = null) + public void Export(GameObject root, Model model, RuntimeVrmConverter converter, ExportArgs option, VRM10MetaObject metaObject = null) { ExportAsset(model); @@ -166,7 +166,7 @@ namespace UniVRM10 Storage.Gltf.materials.Add(glTFMaterial); } - var (vrm, thumbnailTextureIndex) = ExportVrm(root, model, metaObject); + var (vrm, thumbnailTextureIndex) = ExportVrm(root, model, converter, metaObject); // Extension で Texture が増える場合があるので最後に呼ぶ for (int i = 0; i < m_textureExporter.Exported.Count; ++i) @@ -184,12 +184,13 @@ namespace UniVRM10 } - (UniGLTF.Extensions.VRMC_vrm.VRMC_vrm, int?) ExportVrm(GameObject root, Model model, VRM10MetaObject meta) + (UniGLTF.Extensions.VRMC_vrm.VRMC_vrm, int?) ExportVrm(GameObject root, Model model, RuntimeVrmConverter converter, VRM10MetaObject meta) { - if (meta is null) + var vrmController = root.GetComponent(); + + if (meta == null) { - var vrmController = root.GetComponent(); - if (vrmController is null || vrmController.Meta is null) + if (vrmController == null || vrmController.Meta == null) { throw new NullReferenceException("metaObject is null"); } @@ -214,19 +215,138 @@ namespace UniVRM10 }; ExportHumanoid(vrm, model); + var thumbnailTextureIndex = ExportMeta(vrm, meta); - // meta - - // expression - - // lookAt - - // firstPerson + if (vrmController != null) + { + ExportExpression(vrm, vrmController, model, converter); + // lookAt + // firstPerson + } return (vrm, thumbnailTextureIndex); } + UniGLTF.Extensions.VRMC_vrm.MorphTargetBind ExportMorphTargetBinding(MorphTargetBinding binding, Func getIndex) + { + return new UniGLTF.Extensions.VRMC_vrm.MorphTargetBind + { + Node = getIndex(binding.RelativePath), + Index = binding.Index, + Weight = binding.Weight, + }; + } + + UniGLTF.Extensions.VRMC_vrm.MaterialColorBind ExportMaterialColorBinding(MaterialColorBinding binding, Func getIndex) + { + return new UniGLTF.Extensions.VRMC_vrm.MaterialColorBind + { + Material = getIndex(binding.MaterialName), + Type = binding.BindType, + TargetValue = new float[] { binding.TargetValue.x, binding.TargetValue.y, binding.TargetValue.z, binding.TargetValue.w }, + }; + } + + UniGLTF.Extensions.VRMC_vrm.TextureTransformBind ExportTextureTransformBinding(MaterialUVBinding binding, Func getIndex) + { + return new UniGLTF.Extensions.VRMC_vrm.TextureTransformBind + { + Material = getIndex(binding.MaterialName), + Offset = new float[] { binding.Offset.x, binding.Offset.y }, + Scaling = new float[] { binding.Scaling.x, binding.Scaling.y }, + }; + } + + void ExportExpression(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10Controller vrmController, Model model, RuntimeVrmConverter converter) + { + if (vrmController?.Expression?.ExpressionAvatar?.Clips == null) + { + return; + } + + vrm.Expressions = new List(); + foreach (var e in vrmController.Expression.ExpressionAvatar.Clips) + { + var vrmExpression = new UniGLTF.Extensions.VRMC_vrm.Expression + { + Preset = e.Preset, + Name = e.ExpressionName, + IsBinary = e.IsBinary, + OverrideBlink = e.OverrideBlink, + OverrideLookAt = e.OverrideLookAt, + OverrideMouth = e.OverrideMouth, + MorphTargetBinds = new List(), + MaterialColorBinds = new List(), + TextureTransformBinds = new List(), + }; + foreach (var b in e.MorphTargetBindings) + { + try + { + Func getIndex = relativePath => + { + var rendererNode = vrmController.transform.GetFromPath(relativePath); + var node = converter.Nodes[rendererNode.gameObject]; + return model.Nodes.IndexOf(node); + }; + vrmExpression.MorphTargetBinds.Add(ExportMorphTargetBinding(b, getIndex)); + } + catch (Exception ex) + { + Debug.LogWarning(ex); + } + } + foreach (var b in e.MaterialColorBindings) + { + try + { + Func getIndex = materialName => + { + for (int i = 0; i < model.Materials.Count; ++i) + { + var m = model.Materials[i] as Material; + if (m.name == materialName) + { + return i; + } + } + throw new KeyNotFoundException(); + }; + vrmExpression.MaterialColorBinds.Add(ExportMaterialColorBinding(b, getIndex)); + } + catch (Exception ex) + { + Debug.LogWarning(ex); + } + } + foreach (var b in e.MaterialUVBindings) + { + try + { + Func getIndex = materialName => + { + for (int i = 0; i < model.Materials.Count; ++i) + { + var m = model.Materials[i] as Material; + if (m.name == materialName) + { + return i; + } + } + throw new KeyNotFoundException(); + }; + vrmExpression.TextureTransformBinds.Add(ExportTextureTransformBinding(b, getIndex)); + } + catch (Exception ex) + { + Debug.LogWarning(ex); + } + } + vrm.Expressions.Add(vrmExpression); + } + } + int? ExportMeta(UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, VRM10MetaObject meta) { vrm.Meta.Name = meta.Name; diff --git a/Assets/VRM10/Runtime/Scenes/ExportDebugUtil.cs b/Assets/VRM10/Runtime/Scenes/ExportDebugUtil.cs index ced938199..0b29ff9bc 100644 --- a/Assets/VRM10/Runtime/Scenes/ExportDebugUtil.cs +++ b/Assets/VRM10/Runtime/Scenes/ExportDebugUtil.cs @@ -27,7 +27,7 @@ public static class ExportDebugUtil { // vrm = false }; - exporter10.Export(null, model, option); + exporter10.Export(null, model, null, option); var glbBytes10 = exporter10.Storage.ToBytes(); var glb10 = UniGLTF.Glb.Parse(glbBytes10); return System.Text.Encoding.UTF8.GetString(glb10.Json.Bytes.Array, glb10.Json.Bytes.Offset, glb10.Json.Bytes.Count); diff --git a/Assets/VRM10/vrmlib/Runtime/Extensions/ArraySegmentExtensions.cs.meta b/Assets/VRM10/vrmlib/Runtime/Extensions/ArraySegmentExtensions.cs.meta deleted file mode 100644 index 06000f6f4..000000000 --- a/Assets/VRM10/vrmlib/Runtime/Extensions/ArraySegmentExtensions.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: eb18d59756b3d844d8dddda3ab391541 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: