diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs index 771a14c4e..35506de87 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialIO/GltfTextureEnumerator.cs @@ -1,10 +1,37 @@ using System.Collections.Generic; using VRMShaders; + namespace UniGLTF { public delegate IEnumerable TextureEnumerator(GltfParser parser); + /// + /// Texture 生成に関して + /// Runtimeは LoadImage するだけだが、Editor時には Asset 化するにあたって続きの処理がある。 + /// + /// * (gltf/glb/vrm-1): AssetImporterContext.AddObjectToAsset(SubAsset) + /// * (gltf/glb/vrm-1): ScriptedImporter.GetExternalObjectMap(Extracted) + /// * (vrm-0): (Extracted) ScriptedImporter では無いので ScriptedImporter.AddRemap が無い + /// + /// Extract は外部ファイルに png/jpg のバイト列を出力して、TextureImporter を設定すること。ScriptedImporter.AddRemap + /// Extracted は、 + /// + /// ファイル名もしくはSubAsset名を介してテクスチャーアセットにアクセスるので、文字列をユニークなキーとしてテクスチャーを識別できる必要がある。 + /// 基本的に、gltf.textures と Texture2D が1対1に対応するので、 gltfTexture.name のユニーク性を確保した上で + /// これを用いればよいが以下の例外がある。 + /// + /// * PBR の MetallicSmoothness と Occlusion が合体する場合 + /// * (gltf)外部テクスチャーファイルの uri 参照が同じになる場合(同じイメージファイルが異なるテクスチャー設定を保持するケースをサポートしない) + /// * 異なる gltfTexture.source が 同じ gltfImage を参照する場合 + /// * 異なる gltfImage.uri が 同じ ファイルを参照する場合 + /// + /// 例外に対処した上で、ユニークなテクスチャー生成情報を列挙するのが + /// + /// GltfTextureEnumerator.Enumerate + /// + /// である。 + /// public static class GltfTextureEnumerator { public static IEnumerable EnumerateTextures(GltfParser parser, glTFMaterial m) @@ -54,12 +81,12 @@ namespace UniGLTF public static IEnumerable Enumerate(GltfParser parser) { - var used = new HashSet(); + var used = new HashSet(); foreach (var material in parser.GLTF.materials) { foreach (var textureInfo in EnumerateTextures(parser, material)) { - if(used.Add(textureInfo)){ + if(used.Add(textureInfo.ExtractKey)){ yield return textureInfo; } } diff --git a/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs b/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs new file mode 100644 index 000000000..403638bb5 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs @@ -0,0 +1,242 @@ +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; + + +namespace UniGLTF +{ + + public class TextureEnumerateTests + { + static glTF TwoTexture() + { + return new glTF + { + images = new List + { + new glTFImage{ + name = "image_0", + mimeType = "image/png", + }, + new glTFImage{ + name = "image_1", + mimeType = "image/png", + }, + }, + textures = new List + { + new glTFTexture{ + name = "texture_0", + source = 0, + }, + new glTFTexture{ + name = "texture_1", + source = 1, + }, + }, + materials = new List + { + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 0, + } + } + }, + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 1, + } + } + }, + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 0, + } + } + }, + }, + }; + } + + static glTF TwoTextureOneUri() + { + return new glTF + { + images = new List + { + new glTFImage{ + name = "image_0", + mimeType = "image/png", + uri = "some.png", + }, + new glTFImage{ + name = "image_1", + mimeType = "image/png", + uri = "some.png", + }, + }, + textures = new List + { + new glTFTexture{ + name = "texture_0", + source = 0, + }, + new glTFTexture{ + name = "texture_1", + source = 1, + }, + }, + materials = new List + { + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 0, + } + } + }, + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 1, + } + } + }, + }, + }; + } + + static glTF TwoTextureOneImage() + { + return new glTF + { + images = new List + { + new glTFImage{ + name = "image_0", + mimeType = "image/png", + uri = "some.png", + }, + }, + textures = new List + { + new glTFTexture{ + name = "texture_0", + source = 0, + }, + new glTFTexture{ + name = "texture_1", + source = 0, + }, + }, + materials = new List + { + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 0, + } + } + }, + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + baseColorTexture = new glTFMaterialBaseColorTextureInfo{ + index = 1, + } + } + }, + }, + }; + } + + static glTF CombineMetallicSmoothOcclusion() + { + return new glTF + { + images = new List + { + new glTFImage{ + name = "image_0", + mimeType = "image/png", + uri = "metallicSmoothness.png", + }, + new glTFImage{ + name = "image_1", + mimeType = "image/png", + uri = "occlusion.png", + }, + }, + textures = new List + { + new glTFTexture{ + name = "texture_0", + source = 0, + }, + new glTFTexture{ + name = "texture_1", + source = 1, + }, + }, + materials = new List + { + new glTFMaterial{ + pbrMetallicRoughness = new glTFPbrMetallicRoughness{ + metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo{ + index = 0, + } + }, + occlusionTexture = new glTFMaterialOcclusionTextureInfo{ + index = 1, + } + }, + }, + }; + } + + /// + /// Test uniqueness + /// + [Test] + public void TextureEnumerationTest() + { + { + var parser = new GltfParser + { + GLTF = TwoTexture(), + }; + var items = GltfTextureEnumerator.Enumerate(parser).ToArray(); + Assert.AreEqual(2, items.Length); + } + + { + var parser = new GltfParser + { + GLTF = TwoTextureOneUri(), + }; + var items = GltfTextureEnumerator.Enumerate(parser).ToArray(); + Assert.AreEqual(1, items.Length); + } + + { + var parser = new GltfParser + { + GLTF = TwoTextureOneImage(), + }; + var items = GltfTextureEnumerator.Enumerate(parser).ToArray(); + Assert.AreEqual(1, items.Length); + } + + { + var parser = new GltfParser + { + GLTF = CombineMetallicSmoothOcclusion(), + }; + var items = GltfTextureEnumerator.Enumerate(parser).ToArray(); + Assert.AreEqual(1, items.Length); + } + } + } +} diff --git a/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs.meta new file mode 100644 index 000000000..ad8c597bf --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/TextureEnumerateTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 544988eb7d07aca41b87d167dbc79c62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRMShaders/Runtime/TextureImportName.cs b/Assets/VRMShaders/Runtime/TextureImportName.cs index 713ec6a20..3a2277f0d 100644 --- a/Assets/VRMShaders/Runtime/TextureImportName.cs +++ b/Assets/VRMShaders/Runtime/TextureImportName.cs @@ -1,4 +1,6 @@ -namespace VRMShaders +using System.IO; + +namespace VRMShaders { public struct TextureImportName { @@ -6,14 +8,38 @@ public readonly string ConvertedName; public readonly string Ext; - public string Uri; + public readonly string Uri; + public readonly string ExtractKey; - public TextureImportName(string gltfName, string convertedName, string ext, string uri) + public static string GetExtractKey(TextureImportTypes type, string gltfName, string convertedName, string uri) + { + if (type == TextureImportTypes.StandardMap) + { + // metallic, smooth, occlusion + return convertedName; + } + else + { + if (!string.IsNullOrEmpty(uri)) + { + // external image + return Path.GetFileNameWithoutExtension(uri); + } + else + { + // texture name + return gltfName; + } + } + } + + public TextureImportName(TextureImportTypes textureType, string gltfName, string ext, string uri) { GltfName = gltfName; - ConvertedName = convertedName; + ConvertedName = TextureImportName.Convert(gltfName, textureType); Ext = ext; Uri = uri; + ExtractKey = GetExtractKey(textureType, gltfName, ConvertedName, uri); } public string GltfFileName => $"{GltfName}{Ext}"; diff --git a/Assets/VRMShaders/Runtime/TextureImportParam.cs b/Assets/VRMShaders/Runtime/TextureImportParam.cs index 8e59e5c2f..f297a299d 100644 --- a/Assets/VRMShaders/Runtime/TextureImportParam.cs +++ b/Assets/VRMShaders/Runtime/TextureImportParam.cs @@ -29,6 +29,9 @@ namespace VRMShaders public string ConvertedName => Name.ConvertedName; public string ConvertedFileName => Name.ConvertedFileName; public string Uri => Name.Uri; + + public string ExtractKey => Name.ExtractKey; + public Vector2 Offset; public Vector2 Scale;