diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 289ef7357..940bdda96 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -179,14 +179,14 @@ namespace UniGLTF if (m_parser.GLTF.materials == null || m_parser.GLTF.materials.Count == 0) { // no material. work around. - var param = GltfMaterialImporter.CreateParam(m_parser, 0); + var param = GltfMaterialImporter.GetMaterialParam(m_parser, 0); var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync); } else { for (int i = 0; i < m_parser.GLTF.materials.Count; ++i) { - var param = GltfMaterialImporter.CreateParam(m_parser, i); + var param = GltfMaterialImporter.GetMaterialParam(m_parser, i); var material = await MaterialFactory.LoadAsync(param, TextureFactory.GetTextureAsync); } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfMaterialImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfMaterialImporter.cs index 6981d96a0..b038d6180 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfMaterialImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfMaterialImporter.cs @@ -34,7 +34,7 @@ namespace UniGLTF return $"material_{index:00}"; } - public MaterialImportParam CreateParam(GltfParser parser, int i) + public MaterialImportParam GetMaterialParam(GltfParser parser, int i) { foreach (var tryCreate in GltfMaterialParamProcessors) { diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs new file mode 100644 index 000000000..e91c28342 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using UnityEngine; +using VRMShaders; + +namespace UniGLTF +{ + public static class MaterialImporterParamExtensions + { + public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateSubAssetKeyValue(this MaterialImportParam param) + { + foreach (var kv in param.TextureSlots) + { + var key = new SubAssetKey(typeof(Texture2D), kv.Value.UnityObjectName); + yield return (key, kv.Value); + } + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs.meta new file mode 100644 index 000000000..d60b35107 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/MaterialImporterParamExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 95bb02953e0720c45a848856c1006ed4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs index 10e8cbb1b..21ec0a3bb 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/SubAssetKey.cs @@ -31,5 +31,10 @@ namespace UniGLTF Type = t; Name = name; } + + public override string ToString() + { + return $"{Type}:{Name}"; + } } } diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfLoadTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfLoadTests.cs index a0140263c..6b173a7e1 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GltfLoadTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfLoadTests.cs @@ -185,5 +185,32 @@ namespace UniGLTF EditorLoad(gltf, root.FullName.Length); } } + + [Test] + public void GltfSampleModelsTest_DamagedHelmet() + { + var env = System.Environment.GetEnvironmentVariable("GLTF_SAMPLE_MODELS"); + if (string.IsNullOrEmpty(env)) + { + return; + } + var root = new DirectoryInfo($"{env}/2.0"); + if (!root.Exists) + { + return; + } + + { + var path = Path.Combine(root.FullName, "DamagedHelmet/glTF-Binary/DamagedHelmet.glb"); + var parser = new GltfParser(); + parser.ParsePath(path); + + var materialParam = new GltfMaterialImporter().GetMaterialParam(parser, 0); + Assert.AreEqual("Standard", materialParam.ShaderName); + Assert.AreEqual(5, materialParam.TextureSlots.Count); + var (key, value) = materialParam.EnumerateSubAssetKeyValue().First(); + Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "texture_0"), key); + } + } } } diff --git a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs index f3b12bacf..107b63d0a 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs @@ -94,7 +94,7 @@ namespace VRM return true; } - public IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateTexturesForMaterial(GltfParser parser, int i) + public MaterialImportParam GetMaterialParam(GltfParser parser, int i) { // mtoon if (!TryCreateParam(parser, i, out MaterialImportParam param)) @@ -106,22 +106,12 @@ namespace VRM GltfPBRMaterial.TryCreateParam(parser, i, out param); } } - - foreach (var kv in param.TextureSlots) - { - var key = new SubAssetKey(typeof(Texture2D), kv.Value.UnityObjectName); - yield return (key, kv.Value); - } + return param; } public IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateAllTexturesDistinct(GltfParser parser) { var used = new HashSet(); - Func<(SubAssetKey, TextureImportParam), bool> add = (kv) => - { - var (key, textureInfo) = kv; - return used.Add(key); - }; for (int i = 0; i < parser.GLTF.materials.Count; ++i) { @@ -129,22 +119,26 @@ namespace VRM if (vrmMaterial.shader == MToon.Utils.ShaderName) { // MToon - foreach (var kv in EnumerateTexturesForMaterial(parser, i)) + if (!TryCreateParam(parser, i, out MaterialImportParam param)) { - if (add(kv)) + throw new Exception(); + } + foreach (var (key, value) in param.EnumerateSubAssetKeyValue()) + { + if (used.Add(key)) { - yield return kv; + yield return (key, value); } } } else { // PBR or Unlit - foreach (var kv in GltfTextureEnumerator.EnumerateTexturesForMaterial(parser, i)) + foreach (var (key, value) in GltfTextureEnumerator.EnumerateTexturesForMaterial(parser, i)) { - if (add(kv)) + if (used.Add(key)) { - yield return kv; + yield return (key, value); } } } @@ -153,10 +147,10 @@ namespace VRM // thumbnail if (m_vrm.meta != null && m_vrm.meta.texture != -1) { - var kv = GltfTextureImporter.CreateSRGB(parser, m_vrm.meta.texture, Vector2.zero, Vector2.one); - if (add(kv)) + var (key, value) = GltfTextureImporter.CreateSRGB(parser, m_vrm.meta.texture, Vector2.zero, Vector2.one); + if (used.Add(key)) { - yield return kv; + yield return (key, value); } } } diff --git a/Assets/VRM/Tests/MToonTest.cs b/Assets/VRM/Tests/MToonTest.cs index a48d15195..4ad1a574f 100644 --- a/Assets/VRM/Tests/MToonTest.cs +++ b/Assets/VRM/Tests/MToonTest.cs @@ -1,3 +1,5 @@ +using System.IO; +using System.Linq; using NUnit.Framework; using UniGLTF; using UnityEngine; @@ -54,5 +56,28 @@ namespace VRM Assert.AreEqual(73, parser.GLTF.materials.Count); Assert.True(materialImporter.TryCreateParam(parser, 0, out MaterialImportParam param)); } + + static string AliciaPath + { + get + { + return Path.GetFullPath(Application.dataPath + "/../Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm") + .Replace("\\", "/"); + } + } + + [Test] + public void MaterialImporterTest() + { + var parser = new GltfParser(); + parser.ParsePath(AliciaPath); + var vrmImporter = new VRMImporterContext(parser, null); + var materialParam = new VRMMaterialImporter(vrmImporter.VRM).GetMaterialParam(parser, 0); + Assert.AreEqual("VRM/MToon", materialParam.ShaderName); + Assert.AreEqual("Alicia_body", materialParam.TextureSlots["_MainTex"].UnityObjectName); + + var (key, value) = materialParam.EnumerateSubAssetKeyValue().First(); + Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key); + } } } diff --git a/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs b/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs index d0f00b682..781602b40 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10MaterialImporter.cs @@ -177,13 +177,7 @@ namespace UniVRM10 return true; } - /// - /// Material一つ分のテクスチャーを列挙する。重複する場合がある - /// - /// - /// - /// - public static IEnumerable<(SubAssetKey, TextureImportParam)> EnumerateTexturesForMaterial(GltfParser parser, int i) + public static MaterialImportParam GetMaterialParam(GltfParser parser, int i) { // mtoon if (!TryCreateParam(parser, i, out MaterialImportParam param)) @@ -195,12 +189,7 @@ namespace UniVRM10 GltfPBRMaterial.TryCreateParam(parser, i, out param); } } - - foreach (var kv in param.TextureSlots) - { - var key = new SubAssetKey(typeof(Texture2D), kv.Key); - yield return (key, kv.Value); - } + return param; } /// @@ -257,18 +246,14 @@ namespace UniVRM10 } var used = new HashSet(); - Func<(SubAssetKey, TextureImportParam), bool> add = (kv) => - { - var (key, textureInfo) = kv; - return used.Add(key); - }; for (int i = 0; i < parser.GLTF.materials.Count; ++i) { - foreach (var kv in EnumerateTexturesForMaterial(parser, i)) + var param = GetMaterialParam(parser, i); + foreach (var (key, value) in param.EnumerateSubAssetKeyValue()) { - if (add(kv)) + if (used.Add(key)) { - yield return kv; + yield return (key, value); } } } diff --git a/Assets/VRM10/Tests/MaterialImportTests.cs b/Assets/VRM10/Tests/MaterialImportTests.cs new file mode 100644 index 000000000..444bc9b3c --- /dev/null +++ b/Assets/VRM10/Tests/MaterialImportTests.cs @@ -0,0 +1,35 @@ +using System.IO; +using System.Linq; +using NUnit.Framework; +using UniGLTF; +using UnityEngine; + +namespace UniVRM10 +{ + public class MaterialImporterTests + { + static string AliciaPath + { + get + { + return Path.GetFullPath(Application.dataPath + "/../Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm") + .Replace("\\", "/"); + } + } + + [Test] + public void MaterialImporterTest() + { + var migratedBytes = MigrationVrm.Migrate(File.ReadAllBytes(AliciaPath)); + var parser = new GltfParser(); + parser.Parse(AliciaPath, migratedBytes); + + var materialParam = Vrm10MaterialImporter.GetMaterialParam(parser, 0); + Assert.AreEqual("VRM/MToon", materialParam.ShaderName); + Assert.AreEqual("Alicia_body", materialParam.TextureSlots["_MainTex"].UnityObjectName); + + var (key, value) = materialParam.EnumerateSubAssetKeyValue().First(); + Assert.AreEqual(new SubAssetKey(typeof(Texture2D), "Alicia_body"), key); + } + } +} diff --git a/Assets/VRM10/Tests/MaterialImportTests.cs.meta b/Assets/VRM10/Tests/MaterialImportTests.cs.meta new file mode 100644 index 000000000..086e968df --- /dev/null +++ b/Assets/VRM10/Tests/MaterialImportTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9609b7e054ece274bbe4a2e1a3405373 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Tests/VRM10.Tests.asmdef b/Assets/VRM10/Tests/VRM10.Tests.asmdef index 06f9033ee..3d13df4f6 100644 --- a/Assets/VRM10/Tests/VRM10.Tests.asmdef +++ b/Assets/VRM10/Tests/VRM10.Tests.asmdef @@ -4,6 +4,7 @@ "VrmLib", "VRM10", "UniGLTF", + "VRMShaders.GLTF.IO.Runtime", "VRMShaders.GLTF.IO.Editor" ], "optionalUnityReferences": [