From 0d35c6df0dfb55f259088cf048dd5354e95b5ada Mon Sep 17 00:00:00 2001 From: ousttrue Date: Tue, 2 Jun 2020 21:31:23 +0900 Subject: [PATCH] cleanup --- .../UniVRM/Editor/Format/VRMEditorExporter.cs | 132 +++++++++--------- .../UniVRM/Editor/Format/VRMExportSettings.cs | 2 +- 2 files changed, 66 insertions(+), 68 deletions(-) diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs b/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs index ce2a1675a..5c2474ebd 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMEditorExporter.cs @@ -10,6 +10,11 @@ namespace VRM { public static class VRMEditorExporter { + /// + /// Editor向けのエクスポート処理 + /// + /// 出力先 + /// エクスポート設定 public static void Export(string path, VRMExportSettings settings) { List destroy = new List(); @@ -48,6 +53,57 @@ namespace VRM return avatar; } + /// + /// 使用されない BlendShape を間引いた Mesh を作成して置き換える + /// + /// + /// + static void ReplaceMesh(GameObject target, SkinnedMeshRenderer smr, BlendShapeAvatar copyBlendShapeAvatar) + { + Mesh mesh = smr.sharedMesh; + if (mesh == null) return; + if (mesh.blendShapeCount == 0) return; + + // Mesh から BlendShapeClip からの参照がある blendShape の index を集める + var usedBlendshapeIndexArray = copyBlendShapeAvatar.Clips + .SelectMany(clip => clip.Values) + .Where(val => target.transform.Find(val.RelativePath) == smr.transform) + .Select(val => val.Index) + .Distinct() + .ToArray(); + + var copyMesh = mesh.Copy(copyBlendShape: false); + // 使われている BlendShape だけをコピーする + foreach (var i in usedBlendshapeIndexArray) + { + var name = copyMesh.GetBlendShapeName(i); + var vCount = copyMesh.vertexCount; + var vertices = new Vector3[vCount]; + var normals = new Vector3[vCount]; + var tangents = new Vector3[vCount]; + mesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents); + copyMesh.AddBlendShapeFrame(name, 100f, vertices, normals, tangents); + } + + // BlendShapeClip の BlendShapeIndex を更新する(前に詰める) + var indexMapper = usedBlendshapeIndexArray + .Select((x, i) => new { x, i }) + .ToDictionary(pair => pair.x, pair => pair.i); + foreach (var clip in copyBlendShapeAvatar.Clips) + { + for (var i = 0; i < clip.Values.Length; ++i) + { + var value = clip.Values[i]; + if (target.transform.Find(value.RelativePath) != smr.transform) continue; + value.Index = indexMapper[value.Index]; + clip.Values[i] = value; + } + } + + // mesh を置き換える + smr.sharedMesh = copyMesh; + } + static void Export(string path, VRMExportSettings settings, List destroy) { var target = settings.Source; @@ -60,6 +116,7 @@ namespace VRM } } + // 正規化 if (settings.PoseFreeze) { using (new RecordDisposer(target.transform.Traverse().ToArray(), "before normalize")) @@ -71,84 +128,24 @@ namespace VRM } } - // remove unused blendShape + // BlendShape削減 if (settings.ReduceBlendshapeSize) { + // remove unused blendShape var proxy = target.GetComponent(); // 元のBlendShapeClipに変更を加えないように複製 var copyBlendShapeAvatar = CopyBlendShapeAvatar(proxy.BlendShapeAvatar); + proxy.BlendShapeAvatar = copyBlendShapeAvatar; - var skinnedMeshRenderers = target.GetComponentsInChildren(); - - var names = new Dictionary(); - var vs = new Dictionary(); - var ns = new Dictionary(); - var ts = new Dictionary(); - - foreach (SkinnedMeshRenderer smr in skinnedMeshRenderers) + foreach (SkinnedMeshRenderer smr in target.GetComponentsInChildren()) { - Mesh mesh = smr.sharedMesh; - if (mesh == null) continue; - if (mesh.blendShapeCount == 0) continue; - - var copyMesh = mesh.Copy(true); - var vCount = copyMesh.vertexCount; - names.Clear(); - - vs.Clear(); - ns.Clear(); - ts.Clear(); - - var usedBlendshapeIndexArray = copyBlendShapeAvatar.Clips - .SelectMany(clip => clip.Values) - .Where(val => target.transform.Find(val.RelativePath) == smr.transform) - .Select(val => val.Index) - .Distinct() - .ToArray(); - - foreach (var i in usedBlendshapeIndexArray) - { - var name = copyMesh.GetBlendShapeName(i); - var vertices = new Vector3[vCount]; - var normals = new Vector3[vCount]; - var tangents = new Vector3[vCount]; - copyMesh.GetBlendShapeFrameVertices(i, 0, vertices, normals, tangents); - - names.Add(i, name); - vs.Add(i, vertices); - ns.Add(i, normals); - ts.Add(i, tangents); - } - - copyMesh.ClearBlendShapes(); - - foreach (var i in usedBlendshapeIndexArray) - { - copyMesh.AddBlendShapeFrame(names[i], 100f, vs[i], ns[i], ts[i]); - } - - var indexMapper = usedBlendshapeIndexArray - .Select((x, i) => new { x, i }) - .ToDictionary(pair => pair.x, pair => pair.i); - - foreach (var clip in copyBlendShapeAvatar.Clips) - { - for (var i = 0; i < clip.Values.Length; ++i) - { - var value = clip.Values[i]; - if (target.transform.Find(value.RelativePath) != smr.transform) continue; - value.Index = indexMapper[value.Index]; - clip.Values[i] = value; - } - } - - proxy.BlendShapeAvatar = copyBlendShapeAvatar; - - smr.sharedMesh = copyMesh; + // 未使用のBlendShapeを間引く + ReplaceMesh(target, smr, copyBlendShapeAvatar); } } + // 出力 { var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target, settings.ReduceBlendshapeSize); @@ -165,6 +162,7 @@ namespace VRM if (path.StartsWithUnityAssetPath()) { + // 出力ファイルのインポートを発動 AssetDatabase.ImportAsset(path.ToUnityRelativePath()); } } diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs index 2d8d3fa3b..588061205 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExportSettings.cs @@ -59,7 +59,7 @@ namespace VRM public bool UseExperimentalExporter = false; /// - /// エクスポート時にBlendShapeを削減する + /// エクスポート時にBlendShapeClipから参照されないBlendShapeを削除する /// public bool ReduceBlendshapeSize = false; #endregion