diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs new file mode 100644 index 000000000..0dc1a9f49 --- /dev/null +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; + +namespace UniGLTF +{ + [Serializable] + public class MeshExportValidator : ScriptableObject + { + public static Mesh GetMesh(Renderer r) + { + if (r is SkinnedMeshRenderer smr) + { + return smr.sharedMesh; + } + if (r is MeshRenderer) + { + MeshFilter f = r.GetComponent(); + if (f != null) + { + return f.sharedMesh; + } + } + return null; + } + + public List Meshes = new List(); + + public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize); + + List m_validations = new List(); + + public IEnumerable Validations => m_validations; + + public MeshExportSettings Settings; + + public virtual bool UseBlendShape(int index, string relativePath) => true; + + public virtual void CalcMeshSize(ref MeshExportInfo info, + string relativePath) + { + var sb = new StringBuilder(); + if (!info.IsRendererActive) + { + sb.Append("[NotActive]"); + } + + info.VertexCount = info.Mesh.vertexCount; + info.ExportVertexSize = 0; + info.TotalBlendShapeCount = 0; + info.ExportBlendShapeCount = 0; + + // float4 x 3 + // vertices + sb.Append($"(Pos"); + if (info.HasNormal) + { + sb.Append("+Nom"); + info.ExportVertexSize += 4 * 3; + } + if (info.HasUV) + { + sb.Append("+UV"); + info.ExportVertexSize += 4 * 2; + } + if (info.HasVertexColor) + { + sb.Append("+Col"); + info.ExportVertexSize += 4 * 4; + } + if (info.HasSkinning) + { + // short, float x 4 weights + sb.Append("+Skin"); + info.ExportVertexSize += (2 + 4) * 4; + } + // indices + info.IndexCount = info.Mesh.triangles.Length; + + // postion + normal ?. always tangent is ignored + info.TotalBlendShapeCount = info.Mesh.blendShapeCount; + info.ExportBlendShapeVertexSize = Settings.ExportOnlyBlendShapePosition ? 4 * 3 : 4 * (3 + 3); + for (var i = 0; i < info.Mesh.blendShapeCount; ++i) + { + if (!UseBlendShape(i, relativePath)) + { + continue; + } + + ++info.ExportBlendShapeCount; + } + + if (info.ExportBlendShapeCount > 0) + { + sb.Append($"+Morph x {info.ExportBlendShapeCount}"); + } + sb.Append($") x {info.Mesh.vertexCount}"); + switch (info.VertexColor) + { + case MeshExportInfo.VertexColorState.ExistsAndIsUsed: + case MeshExportInfo.VertexColorState.ExistsAndMixed: // エクスポートする + sb.Insert(0, "[use vcolor]"); + break; + case MeshExportInfo.VertexColorState.ExistsButNotUsed: + sb.Insert(0, "[remove vcolor]"); + break; + } + if (info.ExportBlendShapeCount > 0 && !info.HasSkinning) + { + sb.Insert(0, "[morph without skin]"); + } + + // total bytes + sb.Insert(0, $"{info.ExportByteSize:#,0} Bytes = "); + info.Summary = sb.ToString(); + } + + bool TryGetMeshInfo(GameObject root, Renderer renderer, out MeshExportInfo info) + { + info = default; + if (root == null) + { + info.Summary = ""; + return false; + } + if (renderer == null) + { + info.Summary = "no Renderer"; + return false; + } + info.Renderer = renderer; + + if (renderer is SkinnedMeshRenderer smr) + { + info.Skinned = true; + info.Mesh = smr.sharedMesh; + info.IsRendererActive = smr.EnableForExport(); + } + else if (renderer is MeshRenderer mr) + { + var filter = mr.GetComponent(); + if (filter != null) + { + info.Mesh = filter.sharedMesh; + } + info.IsRendererActive = mr.EnableForExport(); + } + else + { + info.Summary = "no Mesh"; + return false; + } + + info.VertexColor = MeshExportInfo.DetectVertexColor(info.Mesh, info.Renderer.sharedMaterials); + + var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform); + CalcMeshSize(ref info, relativePath); + + return true; + } + + public void SetRoot(GameObject ExportRoot, MeshExportSettings settings) + { + Settings = settings; + m_validations.Clear(); + Meshes.Clear(); + if (ExportRoot == null) + { + return; + } + + foreach (var renderer in ExportRoot.GetComponentsInChildren(true)) + { + if (TryGetMeshInfo(ExportRoot, renderer, out MeshExportInfo info)) + { + Meshes.Add(info); + } + } + } + } +} diff --git a/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs.meta b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs.meta new file mode 100644 index 000000000..4ab87b983 --- /dev/null +++ b/Assets/UniGLTF/Editor/UniGLTF/ExportDialog/MeshExportValidator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15b6e58b6aafb284783d551ac475ca3f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM/Editor/Format/VRMExportMeshes.cs b/Assets/VRM/Editor/Format/VRMExportMeshes.cs index 58e7e253d..e0f3202be 100644 --- a/Assets/VRM/Editor/Format/VRMExportMeshes.cs +++ b/Assets/VRM/Editor/Format/VRMExportMeshes.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using MeshUtility; using UniGLTF; using UnityEngine; @@ -15,25 +14,8 @@ namespace VRM /// Meshのエクスポートサイズを試算する。 /// [Serializable] - public class VRMExportMeshes : ScriptableObject + public class VRMExportMeshes : MeshExportValidator { - static Mesh GetMesh(Renderer r) - { - if (r is SkinnedMeshRenderer smr) - { - return smr.sharedMesh; - } - if (r is MeshRenderer) - { - MeshFilter f = r.GetComponent(); - if (f != null) - { - return f.sharedMesh; - } - } - return null; - } - static bool ClipsContainsName(IReadOnlyList clips, bool onlyPreset, BlendShapeBinding binding) { foreach (var c in clips) @@ -57,172 +39,42 @@ namespace VRM return false; } - public List Meshes = new List(); + public VRMExportSettings VRMExportSettings; + public List Clips; - public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize); - - List m_validations = new List(); - public IEnumerable Validations => m_validations; - - public static void CalcMeshSize(ref MeshExportInfo info, - string relativePath, VRMExportSettings settings, IReadOnlyList clips) + public override bool UseBlendShape(int index, string relativePath) { - var sb = new StringBuilder(); - if (!info.IsRendererActive) + if (VRMExportSettings.ReduceBlendshape) { - sb.Append("[NotActive]"); - } - - info.VertexCount = info.Mesh.vertexCount; - info.ExportVertexSize = 0; - info.TotalBlendShapeCount = 0; - info.ExportBlendShapeCount = 0; - - // float4 x 3 - // vertices - sb.Append($"(Pos"); - if (info.HasNormal) - { - sb.Append("+Nom"); - info.ExportVertexSize += 4 * 3; - } - if (info.HasUV) - { - sb.Append("+UV"); - info.ExportVertexSize += 4 * 2; - } - if (info.HasVertexColor) - { - sb.Append("+Col"); - info.ExportVertexSize += 4 * 4; - } - if (info.HasSkinning) - { - // short, float x 4 weights - sb.Append("+Skin"); - info.ExportVertexSize += (2 + 4) * 4; - } - // indices - info.IndexCount = info.Mesh.triangles.Length; - - // postion + normal ?. always tangent is ignored - info.TotalBlendShapeCount = info.Mesh.blendShapeCount; - info.ExportBlendShapeVertexSize = settings.OnlyBlendshapePosition ? 4 * 3 : 4 * (3 + 3); - for (var i = 0; i < info.Mesh.blendShapeCount; ++i) - { - // var name = Mesh.GetBlendShapeName(i); - if (settings.ReduceBlendshape) + if (!ClipsContainsName(Clips, VRMExportSettings, new BlendShapeBinding { - if (!ClipsContainsName(clips, settings.ReduceBlendshapeClip, new BlendShapeBinding - { - Index = i, - RelativePath = relativePath, - })) - { - // skip - continue; - } - } - - ++info.ExportBlendShapeCount; - } - - if (info.ExportBlendShapeCount > 0) - { - sb.Append($"+Morph x {info.ExportBlendShapeCount}"); - } - sb.Append($") x {info.Mesh.vertexCount}"); - switch (info.VertexColor) - { - case MeshExportInfo.VertexColorState.ExistsAndIsUsed: - case MeshExportInfo.VertexColorState.ExistsAndMixed: // エクスポートする - sb.Insert(0, "[use vcolor]"); - break; - case MeshExportInfo.VertexColorState.ExistsButNotUsed: - sb.Insert(0, "[remove vcolor]"); - break; - } - if (info.ExportBlendShapeCount > 0 && !info.HasSkinning) - { - sb.Insert(0, "[morph without skin]"); - } - - // total bytes - sb.Insert(0, $"{info.ExportByteSize:#,0} Bytes = "); - info.Summary = sb.ToString(); - } - - bool TryGetMeshInfo(GameObject root, Renderer renderer, IReadOnlyList clips, VRMExportSettings settings, out MeshExportInfo info) - { - info = default; - if (root == null) - { - info.Summary = ""; - return false; - } - if (renderer == null) - { - info.Summary = "no Renderer"; - return false; - } - info.Renderer = renderer; - - if (renderer is SkinnedMeshRenderer smr) - { - info.Skinned = true; - info.Mesh = smr.sharedMesh; - info.IsRendererActive = smr.EnableForExport(); - } - else if (renderer is MeshRenderer mr) - { - var filter = mr.GetComponent(); - if (filter != null) + Index = index, + RelativePath = relativePath, + })) { - info.Mesh = filter.sharedMesh; + // skip + return false; } - info.IsRendererActive = mr.EnableForExport(); } - else - { - info.Summary = "no Mesh"; - return false; - } - - info.VertexColor = MeshExportInfo.DetectVertexColor(info.Mesh, info.Renderer.sharedMaterials); - - var relativePath = UniGLTF.UnityExtensions.RelativePathFrom(renderer.transform, root.transform); - CalcMeshSize(ref info, relativePath, settings, clips); return true; } public void SetRoot(GameObject ExportRoot, VRMExportSettings settings) { - m_validations.Clear(); - Meshes.Clear(); - if (ExportRoot == null) - { - return; - } - - var clips = new List(); + VRMExportSettings = settings; + Clips = new List(); var proxy = ExportRoot.GetComponent(); if (proxy != null) { // Export サイズ の 計算 if (proxy.BlendShapeAvatar != null) { - clips.AddRange(proxy.BlendShapeAvatar.Clips); + Clips.AddRange(proxy.BlendShapeAvatar.Clips); } } - foreach (var renderer in ExportRoot.GetComponentsInChildren(true)) - { - if (TryGetMeshInfo(ExportRoot, renderer, clips, settings, out MeshExportInfo info)) - { - Meshes.Add(info); - } - } + SetRoot(ExportRoot, settings.MeshExportSettings); } } } diff --git a/Assets/VRM10/Editor/Vrm10ExportDialog.cs b/Assets/VRM10/Editor/Vrm10ExportDialog.cs index 81e7f2681..17778c7f1 100644 --- a/Assets/VRM10/Editor/Vrm10ExportDialog.cs +++ b/Assets/VRM10/Editor/Vrm10ExportDialog.cs @@ -1,9 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Reflection; -using MeshUtility; using UniGLTF; using UnityEditor; using UnityEngine;