using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UniGLTF; using UnityEngine; using VRMShaders; namespace UniVRM10 { public sealed class Vrm10TextureDescriptorGenerator : ITextureDescriptorGenerator { public const string UniqueThumbnailName = "thumbnail__VRM10"; private readonly GltfData m_data; private TextureDescriptorSet _textureDescriptorSet; public Vrm10TextureDescriptorGenerator(GltfData data) { m_data = data; } public TextureDescriptorSet Get() { if (_textureDescriptorSet == null) { _textureDescriptorSet = new TextureDescriptorSet(); foreach (var (_, param) in EnumerateAllTextures(m_data)) { _textureDescriptorSet.Add(param); } } return _textureDescriptorSet; } /// /// glTF 全体で使うテクスチャーを列挙する /// private static IEnumerable<(SubAssetKey, TextureDescriptor)> EnumerateAllTextures(GltfData data) { if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(data.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) { throw new System.Exception("not vrm"); } // Textures referenced by Materials. for (var materialIdx = 0; materialIdx < data.GLTF.materials.Count; ++materialIdx) { var m = data.GLTF.materials[materialIdx]; if (UniGLTF.Extensions.VRMC_materials_mtoon.GltfDeserializer.TryGet(m.extensions, out var mToon)) { foreach (var (_, tex) in Vrm10MToonTextureImporter.EnumerateAllTextures(data, m, mToon)) { yield return tex; } } else { // Fallback to glTF PBR & glTF Unlit foreach (var tex in GltfPbrTextureImporter.EnumerateAllTextures(data, materialIdx)) { yield return tex; } } } // Thumbnail Texture referenced by VRM Meta. if (TryGetMetaThumbnailTextureImportParam(data, vrm, out (SubAssetKey key, TextureDescriptor) thumbnail)) { yield return thumbnail; } } /// /// VRM-1 の thumbnail テクスチャー。gltf.textures ではなく gltf.images の参照であることに注意(sampler等の設定が無い) /// public static bool TryGetMetaThumbnailTextureImportParam(GltfData data, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, out (SubAssetKey, TextureDescriptor) value) { if (vrm?.Meta?.ThumbnailImage == null) { value = default; return false; } var thumbnailImage = vrm.Meta.ThumbnailImage; if (!thumbnailImage.HasValue) { value = default; return false; } var imageIndex = thumbnailImage.Value; if (imageIndex < 0 || imageIndex >= data.GLTF.images.Count) { value = default; return false; } var gltfImage = data.GLTF.images[imageIndex]; // data.GLTF.textures は前処理によりユニーク性がある // unique な名前を振り出す var used = new HashSet(data.GLTF.textures.Select(x => x.name)); var uniqueName = GlbLowLevelParser.FixNameUnique(used, UniqueThumbnailName); value = GltfTextureImporter.CreateSrgbFromOnlyImage(data, imageIndex, uniqueName, gltfImage.uri); return true; } } }