using System.Collections.Generic; using System.Linq; using UniGLTF; using UniGLTF.MeshUtility; using UnityEngine; namespace VRM { /// /// Meshを統合し、統合後のMeshのBlendShapeの変化をVRMのBlendShapeClipに反映する /// public static class VRMMeshIntegratorUtility { public static List Integrate(GameObject root, List blendshapeClips, IEnumerable excludes, bool separateByBlendShape) { var result = new List(); if (separateByBlendShape) { var withoutBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); if (withoutBlendShape.IntegratedRenderer != null) { result.Add(withoutBlendShape); } var onlyBlendShape = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); if (onlyBlendShape.IntegratedRenderer != null) { result.Add(onlyBlendShape); FollowBlendshapeRendererChange(blendshapeClips, onlyBlendShape, root); } } else { var integrated = MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); if (integrated.IntegratedRenderer != null) { result.Add(integrated); } } return result; } private static void FollowBlendshapeRendererChange(List clips, MeshIntegrationResult result, GameObject root) { if (clips == null || result == null || result.IntegratedRenderer == null || root == null) return; var rendererDict = result.SourceSkinnedMeshRenderers .ToDictionary(x => x.transform.RelativePathFrom(root.transform), x => x); var dstPath = result.IntegratedRenderer.transform.RelativePathFrom(root.transform); foreach (var clip in clips) { if (clip == null) continue; for (var i = 0; i < clip.Values.Length; ++i) { var val = clip.Values[i]; if (rendererDict.ContainsKey(val.RelativePath)) { var srcRenderer = rendererDict[val.RelativePath]; var name = srcRenderer.sharedMesh.GetBlendShapeName(val.Index); var newIndex = result.IntegratedRenderer.sharedMesh.GetBlendShapeIndex(name); val.RelativePath = dstPath; val.Index = newIndex; } clip.Values[i] = val; } } } } }