From 5fd2a743a191eb52d6ef726b98349e83a9872ecc Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 16 May 2022 16:44:01 +0900 Subject: [PATCH] =?UTF-8?q?=E7=B5=B1=E5=90=88Mesh=E3=82=92=E3=83=92?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=AB=E3=82=AD=E3=83=BC=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=81=99=E3=82=8B=E3=82=BF=E3=82=A4=E3=83=9F=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E3=82=B3=E3=83=94=E3=83=BC=E5=BE=8C=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Editor/MeshUtility/TabMeshIntegrator.cs | 84 ++----------------- .../Runtime/MeshUtility/MeshIntegrator.cs | 5 +- .../MeshUtility/MeshIntegratorUtility.cs | 61 +++++++++++++- .../VrmMeshIntegratorWizard.cs | 65 +++++++++++--- .../VRMMeshIntegratorUtility.cs | 33 +------- 5 files changed, 123 insertions(+), 125 deletions(-) diff --git a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs index ed366f531..66b19537d 100644 --- a/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs +++ b/Assets/UniGLTF/Editor/MeshUtility/TabMeshIntegrator.cs @@ -1,4 +1,4 @@ -using System.IO; +using System.Collections.Generic; using UniGLTF.M17N; using UnityEditor; using UnityEngine; @@ -7,8 +7,6 @@ namespace UniGLTF.MeshUtility { public static class TabMeshIntegrator { - const string ASSET_SUFFIX = ".mesh.asset"; - public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers) { var _isInvokeSuccess = false; @@ -44,6 +42,7 @@ namespace UniGLTF.MeshUtility static bool Execute(GameObject root, bool onlyBlendShapeRenderers) { + // check if (root == null) { EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok"); @@ -62,87 +61,22 @@ namespace UniGLTF.MeshUtility return false; } + // execute + var results = new List(); if (onlyBlendShapeRenderers) { - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape); - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape)); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape)); } else { - MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All); + results.Add(MeshIntegratorUtility.Integrate(root, onlyBlendShapeRenderers: MeshEnumerateOption.All)); } - CopyAndSaveAssetEtc(root); + // 統合結果を適用した新しいヒエラルキーをコピーから作成する + MeshIntegratorUtility.CopyAndReplaceWithResults(root, results); return true; } - - static void CopyAndSaveAssetEtc(GameObject root) - { - // copy hierarchy - var outputObject = GameObject.Instantiate(root); - outputObject.name = outputObject.name + "_mesh_integration"; - var skinnedMeshes = outputObject.GetComponentsInChildren(); - - // destroy integrated meshes in the source - foreach (var skinnedMesh in root.GetComponentsInChildren()) - { - if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - } - foreach (var skinnedMesh in skinnedMeshes) - { - // destroy original meshes in the copied GameObject - if (!(skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME)) - { - GameObject.DestroyImmediate(skinnedMesh); - } - // check if the integrated mesh is empty - else if (skinnedMesh.sharedMesh.subMeshCount == 0) - { - GameObject.DestroyImmediate(skinnedMesh.gameObject); - } - // save mesh data - else if (skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_NAME || - skinnedMesh.sharedMesh.name == MeshIntegratorUtility.INTEGRATED_MESH_BLENDSHAPE_NAME) - { - SaveMeshData(skinnedMesh.sharedMesh); - } - } - - var normalMeshes = outputObject.GetComponentsInChildren(); - foreach (var normalMesh in normalMeshes) - { - if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) - { - if (normalMesh.gameObject.GetComponent()) - { - GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); - } - GameObject.DestroyImmediate(normalMesh); - } - } - } - - static void SaveMeshData(Mesh mesh) - { - var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - Debug.Log(assetPath); - if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) - { - var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); - assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - else - { - assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); - } - Debug.LogFormat("CreateAsset: {0}", assetPath); - AssetDatabase.CreateAsset(mesh, assetPath); - } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs index 81759c546..f4ddfdd20 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegrator.cs @@ -25,7 +25,7 @@ namespace UniGLTF.MeshUtility public Vector3[] Tangents; } - public MeshIntegrationResult Result { get; } = new MeshIntegrationResult(); + MeshIntegrationResult Result { get; } = new MeshIntegrationResult(); List Positions { get; } = new List(); List Normals { get; } = new List(); List UV { get; } = new List(); @@ -230,7 +230,7 @@ namespace UniGLTF.MeshUtility } } - public void Integrate(MeshEnumerateOption onlyBlendShapeRenderers) + public MeshIntegrationResult Integrate(MeshEnumerateOption onlyBlendShapeRenderers) { var mesh = new Mesh(); @@ -290,6 +290,7 @@ namespace UniGLTF.MeshUtility integrated.bones = Bones.ToArray(); Result.IntegratedRenderer = integrated; Result.MeshMap.Integrated = mesh; + return Result; } } } diff --git a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs index 5938452d1..f01b42dbc 100644 --- a/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs +++ b/Assets/UniGLTF/Runtime/MeshUtility/MeshIntegratorUtility.cs @@ -1,10 +1,14 @@ using System.Collections.Generic; +using System.IO; +using UnityEditor; using UnityEngine; namespace UniGLTF.MeshUtility { public static class MeshIntegratorUtility { + const string ASSET_SUFFIX = ".mesh.asset"; + public static string INTEGRATED_MESH_NAME => MeshIntegrator.INTEGRATED_MESH_NAME; public static string INTEGRATED_MESH_BLENDSHAPE_NAME => MeshIntegrator.INTEGRATED_MESH_BLENDSHAPE_NAME; @@ -19,7 +23,9 @@ namespace UniGLTF.MeshUtility /// null: すべてのSkinnedMeshRenderer + MeshRenderer /// /// - public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption onlyBlendShapeRenderers, IEnumerable excludes = null) + public static MeshIntegrationResult Integrate(GameObject go, MeshEnumerateOption onlyBlendShapeRenderers, + IEnumerable excludes = null, + bool destroyIntegratedRenderer = false) { var exclude = new MeshExclude(excludes); @@ -87,9 +93,7 @@ namespace UniGLTF.MeshUtility } } - integrator.Integrate(onlyBlendShapeRenderers); - integrator.Result.IntegratedRenderer.transform.SetParent(go.transform, false); - return integrator.Result; + return integrator.Integrate(onlyBlendShapeRenderers); } public static IEnumerable EnumerateSkinnedMeshRenderer(Transform root, MeshEnumerateOption hasBlendShape) @@ -160,5 +164,54 @@ namespace UniGLTF.MeshUtility } } } + + public static void CopyAndReplaceWithResults(GameObject root, List results) + { + // copy hierarchy + var outputObject = GameObject.Instantiate(root); + outputObject.name = outputObject.name + "_mesh_integration"; + + // destroy original meshes in the copied GameObject + foreach (var skinnedMesh in outputObject.GetComponentsInChildren()) + { + GameObject.DestroyImmediate(skinnedMesh); + } + foreach (var normalMesh in outputObject.GetComponentsInChildren()) + { + if (normalMesh.sharedMesh.name != MeshIntegratorUtility.INTEGRATED_MESH_NAME) + { + if (normalMesh.gameObject.GetComponent()) + { + GameObject.DestroyImmediate(normalMesh.gameObject.GetComponent()); + } + GameObject.DestroyImmediate(normalMesh); + } + } + + foreach (var result in results) + { + // Add integrated + result.IntegratedRenderer.transform.SetParent(outputObject.transform, false); + // save mesh data + SaveMeshData(result.IntegratedRenderer.sharedMesh); + } + } + + static void SaveMeshData(Mesh mesh) + { + var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + Debug.Log(assetPath); + if (!string.IsNullOrEmpty((AssetDatabase.GetAssetPath(mesh)))) + { + var directory = Path.GetDirectoryName(AssetDatabase.GetAssetPath(mesh)).Replace("\\", "/"); + assetPath = string.Format("{0}/{1}{2}", directory, Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + else + { + assetPath = string.Format("Assets/{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX); + } + Debug.LogFormat("CreateAsset: {0}", assetPath); + AssetDatabase.CreateAsset(mesh, assetPath); + } } } \ No newline at end of file diff --git a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs index 3f991627b..a5db19875 100644 --- a/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs +++ b/Assets/VRM/Editor/SkinnedMeshUtility/VrmMeshIntegratorWizard.cs @@ -217,6 +217,9 @@ namespace VRM // helpString = "Set target gameobject `in scene`. Prefab not supported."; } + /// + /// Prefab に対する操作として実装されている + /// void Integrate() { var prefabPath = AssetDatabase.GetAssetPath(m_root); @@ -241,33 +244,70 @@ namespace VRM Undo.RecordObject(m_root, "Mesh Integration"); var instance = VrmPrefabUtility.InstantiatePrefab(m_root); - var clips = new List(); var proxy = instance.GetComponent(); if (proxy != null && proxy.BlendShapeAvatar != null) { - clips = proxy.BlendShapeAvatar.Clips; + clips.AddRange(proxy.BlendShapeAvatar.Clips); } foreach (var clip in clips) { Undo.RecordObject(clip, "Mesh Integration"); } + _Integrate(instance, excludes, assetPath, clips); + + // destroy source renderers + UnityEngine.Object.DestroyImmediate(instance); + } + + void _Integrate(GameObject instance, IEnumerable excludes, UniGLTF.UnityPath assetPath, List clips) + { // Execute - var results = VRMMeshIntegratorUtility.Integrate(instance, clips, excludes, m_separateByBlendShape); - // integrationResults = MeshIntegratorEditor.Integrate(m_root, assetPath, excludes, m_separateByBlendShape).Select(x => x.MeshMap).ToArray(); - // public static List Integrate(GameObject prefab, UniGLTF.UnityPath writeAssetPath, IEnumerable excludes, bool separateByBlendShape) + var results = new List(); + if (m_separateByBlendShape) + { + var withoutBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithoutBlendShape, excludes: excludes); + if (withoutBlendShape.IntegratedRenderer != null) + { + results.Add(withoutBlendShape); + } + + var onlyBlendShape = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.OnlyWithBlendShape, excludes: excludes); + if (onlyBlendShape.IntegratedRenderer != null) + { + results.Add(onlyBlendShape); + VRMMeshIntegratorUtility.FollowBlendshapeRendererChange(clips, onlyBlendShape, instance); + } + } + else + { + var integrated = MeshIntegratorUtility.Integrate(instance, onlyBlendShapeRenderers: MeshEnumerateOption.All, excludes: excludes); + if (integrated.IntegratedRenderer != null) + { + results.Add(integrated); + } + } + + DeactivateOldRendererAndAddIntegrated(instance, results, assetPath, + UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)); + } + + static void DeactivateOldRendererAndAddIntegrated(GameObject instance, List results, UniGLTF.UnityPath assetPath, + bool applyToPrefab) + { + // TODO: add integrated // disable source renderer - foreach (var res in results) + foreach (var result in results) { - foreach (var renderer in res.SourceSkinnedMeshRenderers) + foreach (var renderer in result.SourceSkinnedMeshRenderers) { Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); renderer.gameObject.SetActive(false); } - foreach (var renderer in res.SourceMeshRenderers) + foreach (var renderer in result.SourceMeshRenderers) { Undo.RecordObject(renderer.gameObject, "Deactivate old renderer"); renderer.gameObject.SetActive(false); @@ -278,6 +318,10 @@ namespace VRM { if (result.IntegratedRenderer == null) continue; + // Add integrated + result.IntegratedRenderer.transform.SetParent(instance.transform, false); + + // save as asset mesh var childAssetPath = assetPath.Parent.Child($"{result.IntegratedRenderer.gameObject.name}{ASSET_SUFFIX}"); Debug.LogFormat("CreateAsset: {0}", childAssetPath); childAssetPath.CreateAsset(result.IntegratedRenderer.sharedMesh); @@ -285,7 +329,7 @@ namespace VRM } // Apply to Prefab - if (UniGLTF.UnityPath.FromUnityPath(AssetDatabase.GetAssetPath(m_root)).Equals(assetPath)) + if (applyToPrefab) { VrmPrefabUtility.ApplyChangesToPrefab(instance); } @@ -297,9 +341,6 @@ namespace VRM throw new System.Exception($"PrefabUtility.SaveAsPrefabAsset: {assetPath}"); } } - - // destroy source renderers - UnityEngine.Object.DestroyImmediate(instance); } void OnWizardCreate() diff --git a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs index fea51d76c..066b55fbd 100644 --- a/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs +++ b/Assets/VRM/Runtime/SkinnedMeshUtility/VRMMeshIntegratorUtility.cs @@ -11,38 +11,7 @@ namespace VRM /// 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) + public static void FollowBlendshapeRendererChange(List clips, MeshIntegrationResult result, GameObject root) { if (clips == null || result == null || result.IntegratedRenderer == null || root == null) return;