diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshWithRenderer.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshWithRenderer.cs index 1ee16c1e8e..4caee6365d 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshWithRenderer.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshWithRenderer.cs @@ -91,5 +91,21 @@ public static IEnumerable FromNodes(IEnumerable nod yield return x; } } + + public bool IsSameMeshAndMaterials(MeshWithRenderer other) + { + return IsSameMeshAndMaterials(other.Mesh, other.Renderer.sharedMaterials); + } + + public bool IsSameMeshAndMaterials(Mesh mesh, Material[] materials) + { + if (Mesh != mesh) return false; + if (Renderer.sharedMaterials.Length != materials.Length) return false; + for (var i = 0; i < Renderer.sharedMaterials.Length; i++) + { + if (Renderer.sharedMaterials[i] != materials[i]) return false; + } + return true; + } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs index 12631dd417..f8e42179d6 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/gltfExporter.cs @@ -134,7 +134,7 @@ public void Dispose() } #region Export - static glTFNode ExportNode(Transform x, List nodes, List renderers, List skins) + static glTFNode ExportNode(Transform x, List nodes, List meshWithRenderers, List skins) { var node = new glTFNode { @@ -148,22 +148,62 @@ static glTFNode ExportNode(Transform x, List nodes, List re if (x.gameObject.activeInHierarchy) { var meshRenderer = x.GetComponent(); + if (meshRenderer != null) { - node.mesh = renderers.IndexOf(meshRenderer); + var meshFilter = x.GetComponent(); + if(meshFilter != null) + { + var mesh = meshFilter.sharedMesh; + var materials = meshRenderer.sharedMaterials; + if (TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex)) + { + node.mesh = meshIndex; + } + else + { + // MeshとMaterialが一致するものが見つからなかった + throw new Exception("Mesh not found."); + } + } } var skinnedMeshRenderer = x.GetComponent(); if (skinnedMeshRenderer != null) { - node.mesh = renderers.IndexOf(skinnedMeshRenderer); - node.skin = skins.IndexOf(skinnedMeshRenderer); + var mesh = skinnedMeshRenderer.sharedMesh; + var materials = skinnedMeshRenderer.sharedMaterials; + if(TryGetSameMeshIndex(meshWithRenderers, mesh, materials, out int meshIndex)) + { + node.mesh = meshIndex; + node.skin = skins.IndexOf(skinnedMeshRenderer); + } + else + { + // MeshとMaterialが一致するものが見つからなかった + throw new Exception("Mesh not found."); + } } } return node; } + private static bool TryGetSameMeshIndex(List meshWithRenderers, Mesh mesh, Material[] materials, out int meshIndex) + { + for (var i = 0; i < meshWithRenderers.Count; i++) + { + if (meshWithRenderers[i].IsSameMeshAndMaterials(mesh, materials)) + { + meshIndex = i; + return true; + } + } + + meshIndex = -1; + return false; + } + public virtual void ExportExtensions(Func getTextureBytes) { @@ -189,9 +229,14 @@ public virtual void Export(MeshExportSettings meshExportSettings, Func x.Mesh.vertices.Any()).ToList(); + var uniqueUnityMeshes = new List(); + foreach (var um in unityMeshes) + { + if (!uniqueUnityMeshes.Any(x => x.IsSameMeshAndMaterials(um))) uniqueUnityMeshes.Add(um); + } MeshBlendShapeIndexMap = new Dictionary>(); - foreach (var unityMesh in unityMeshes) + foreach (var unityMesh in uniqueUnityMeshes) { var (gltfMesh, blendShapeIndexMap) = MeshExporter.ExportMesh(glTF, bufferIndex, unityMesh, Materials, meshExportSettings, m_axisInverter); glTF.meshes.Add(gltfMesh); @@ -205,10 +250,10 @@ public virtual void Export(MeshExportSettings meshExportSettings, Func x.UniqueBones != null) .ToList(); - glTF.nodes = Nodes.Select(x => ExportNode(x, Nodes, unityMeshes.Select(y => y.Renderer).ToList(), unitySkins.Select(y => y.Renderer as SkinnedMeshRenderer).ToList())).ToList(); + glTF.nodes = Nodes.Select(x => ExportNode(x, Nodes, uniqueUnityMeshes, unitySkins.Select(y => y.Renderer as SkinnedMeshRenderer).ToList())).ToList(); glTF.scenes = new List { new gltfScene