diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureImporter.cs index 6fdb77787..27cdef130 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO/GltfTextureImporter.cs @@ -12,6 +12,8 @@ namespace UniGLTF /// public static class GltfTextureImporter { + public static bool ImportKhrTextureBasisuExtension { get; set; } = true; + /// /// glTF の Texture が存在せず Image のみのものを、Texture として扱いたい場合の関数. /// @@ -38,14 +40,15 @@ namespace UniGLTF public static bool TryCreateSrgb(GltfData data, int textureIndex, Vector2 offset, Vector2 scale, out SubAssetKey key, out TextureDescriptor desc) { var gltfTexture = data.GLTF.textures[textureIndex]; - if (!gltfTexture.source.HasValidIndex()) + var imageIndex = GetImageIndexFromTextureIndex(data, textureIndex); + if (!imageIndex.HasValue) { key = default; desc = default; return false; } - var gltfImage = data.GLTF.images[gltfTexture.source.Value]; + var gltfImage = data.GLTF.images[imageIndex.Value]; var name = TextureImportName.GetUnityObjectName(TextureImportTypes.sRGB, gltfTexture.name, gltfImage.uri); var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex); desc = new TextureDescriptor( @@ -55,7 +58,7 @@ namespace UniGLTF TextureImportTypes.sRGB, default, default, - () => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)), + () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex.Value)), default, default, default, default, default); key = desc.SubAssetKey; return true; @@ -64,14 +67,15 @@ namespace UniGLTF public static bool TryCreateLinear(GltfData data, int textureIndex, Vector2 offset, Vector2 scale, out SubAssetKey key, out TextureDescriptor desc) { var gltfTexture = data.GLTF.textures[textureIndex]; - if (!gltfTexture.source.HasValidIndex()) + var imageIndex = GetImageIndexFromTextureIndex(data, textureIndex); + if (!imageIndex.HasValue) { key = default; desc = default; return false; } - var gltfImage = data.GLTF.images[gltfTexture.source.Value]; + var gltfImage = data.GLTF.images[imageIndex.Value]; var name = TextureImportName.GetUnityObjectName(TextureImportTypes.Linear, gltfTexture.name, gltfImage.uri); var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex); desc = new TextureDescriptor( @@ -82,7 +86,7 @@ namespace UniGLTF TextureImportTypes.Linear, default, default, - () => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)), + () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex.Value)), default, default, default, default, default); key = desc.SubAssetKey; return true; @@ -91,14 +95,15 @@ namespace UniGLTF public static bool TryCreateNormal(GltfData data, int textureIndex, Vector2 offset, Vector2 scale, out SubAssetKey key, out TextureDescriptor desc) { var gltfTexture = data.GLTF.textures[textureIndex]; - if (!gltfTexture.source.HasValidIndex()) + var imageIndex = GetImageIndexFromTextureIndex(data, textureIndex); + if (!imageIndex.HasValue) { key = default; desc = default; return false; } - var gltfImage = data.GLTF.images[gltfTexture.source.Value]; + var gltfImage = data.GLTF.images[imageIndex.Value]; var name = TextureImportName.GetUnityObjectName(TextureImportTypes.NormalMap, gltfTexture.name, gltfImage.uri); var sampler = TextureSamplerUtil.CreateSampler(data.GLTF, textureIndex); desc = new TextureDescriptor( @@ -109,7 +114,7 @@ namespace UniGLTF TextureImportTypes.NormalMap, default, default, - () => Task.FromResult(GetImageBytesFromTextureIndex(data, textureIndex)), + () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex.Value)), default, default, default, default, default); key = desc.SubAssetKey; return true; @@ -118,35 +123,45 @@ namespace UniGLTF public static bool TryCreateStandard(GltfData data, int? metallicRoughnessTextureIndex, int? occlusionTextureIndex, Vector2 offset, Vector2 scale, float metallicFactor, float roughnessFactor, out SubAssetKey key, out TextureDescriptor desc) { string name = default; - + SamplerParam? sampler = default; GetTextureBytesAsync getMetallicRoughnessAsync = default; - SamplerParam sampler = default; + GetTextureBytesAsync getOcclusionAsync = default; + if (metallicRoughnessTextureIndex.HasValue) { var gltfTexture = data.GLTF.textures[metallicRoughnessTextureIndex.Value]; - if (gltfTexture.source.HasValidIndex()) + var imageIndex = GetImageIndexFromTextureIndex(data, metallicRoughnessTextureIndex.Value); + if (imageIndex.HasValue) { - name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source.Value].uri); + var gltfImage = data.GLTF.images[imageIndex.Value]; + name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, gltfImage.uri); sampler = TextureSamplerUtil.CreateSampler(data.GLTF, metallicRoughnessTextureIndex.Value); - getMetallicRoughnessAsync = () => Task.FromResult(GetImageBytesFromTextureIndex(data, metallicRoughnessTextureIndex.Value)); + getMetallicRoughnessAsync = () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex.Value)); } } - GetTextureBytesAsync getOcclusionAsync = default; if (occlusionTextureIndex.HasValue) { var gltfTexture = data.GLTF.textures[occlusionTextureIndex.Value]; - if (gltfTexture.source.HasValidIndex()) + var imageIndex = GetImageIndexFromTextureIndex(data, occlusionTextureIndex.Value); + if (imageIndex.HasValue) { + var gltfImage = data.GLTF.images[imageIndex.Value]; if (string.IsNullOrEmpty(name)) { - name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, data.GLTF.images[gltfTexture.source.Value].uri); + name = TextureImportName.GetUnityObjectName(TextureImportTypes.StandardMap, gltfTexture.name, gltfImage.uri); } - sampler = TextureSamplerUtil.CreateSampler(data.GLTF, occlusionTextureIndex.Value); - getOcclusionAsync = () => Task.FromResult(GetImageBytesFromTextureIndex(data, occlusionTextureIndex.Value)); + sampler ??= TextureSamplerUtil.CreateSampler(data.GLTF, occlusionTextureIndex.Value); + getOcclusionAsync = () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex.Value)); } } + if (getMetallicRoughnessAsync == null && getOcclusionAsync == null) + { + key = default; + desc = default; + return false; + } if (string.IsNullOrEmpty(name)) { key = default; @@ -158,7 +173,7 @@ namespace UniGLTF name, offset, scale, - sampler, + sampler.Value, TextureImportTypes.StandardMap, metallicFactor, roughnessFactor, @@ -166,11 +181,6 @@ namespace UniGLTF getOcclusionAsync, default, default, default, default); key = desc.SubAssetKey; - if (string.IsNullOrEmpty(desc.UnityObjectName)) - { - throw new ArgumentNullException(); - } - Debug.Log("${name}"); return true; } @@ -206,43 +216,47 @@ namespace UniGLTF return (offset, scale); } - public static (byte[] binary, string mimeType)? GetImageBytesFromTextureIndex(GltfData data, int textureIndex) + private static (byte[] binary, string mimeType)? GetImageBytesFromImageIndex(GltfData data, int imageIndex) { - if (Application.isPlaying) + if (imageIndex >= 0 && imageIndex < data.GLTF.images.Count) { - // NOTE: Runtime の場合は、拡張を考える. - var imageIndex = GetImageIndexFromTexture(data, textureIndex); - - if (textureIndex >= 0 && textureIndex < data.GLTF.textures.Count) + var imageBytes = data.GetBytesFromImage(imageIndex); + if (imageBytes.HasValue) { - var texture = data.GLTF.textures[textureIndex]; - if (glTF_KHR_texture_basisu.TryGet(texture, out var basisuExtension)) + + return (ToArray(imageBytes.Value.binary), imageBytes.Value.mimeType); + } + } + + return default; + } + + private static int? GetImageIndexFromTextureIndex(GltfData data, int textureIndex) + { + if (textureIndex >= 0 && textureIndex < data.GLTF.textures.Count) + { + var texture = data.GLTF.textures[textureIndex]; + + // NOTE: Runtime の場合は KHR_texture_basisu 拡張を考える. + if (ImportKhrTextureBasisuExtension && + Application.isPlaying && + glTF_KHR_texture_basisu.TryGet(texture, out var basisuExtension)) + { + var basisuImageIndex = basisuExtension.source; + if (basisuImageIndex >= 0 && basisuImageIndex < data.GLTF.images.Count) { - imageIndex = basisuExtension.source; + return basisuImageIndex; } } - if (!imageIndex.HasValue) return default; - - var imageBytes = data.GetBytesFromImage(imageIndex.Value); - return (ToArray(imageBytes?.binary ?? default), imageBytes?.mimeType); + var imageIndex = texture.source; + if (imageIndex >= 0 && imageIndex < data.GLTF.images.Count) + { + return imageIndex; + } } - else - { - // NOTE: Editor の場合は通常通り読み込む. - var imageIndex = GetImageIndexFromTexture(data, textureIndex); - if (!imageIndex.HasValue) return default; - var imageBytes = data.GetBytesFromImage(imageIndex.Value); - return (ToArray(imageBytes?.binary ?? default), imageBytes?.mimeType); - } - } - - private static int? GetImageIndexFromTexture(GltfData data, int textureIndex) - { - if (textureIndex < 0 || textureIndex >= data.GLTF.textures.Count) return default; - - return data.GLTF.textures[textureIndex].source; + return default; } private static byte[] ToArray(NativeArray bytes) diff --git a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/TextureDescriptor.cs b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/TextureDescriptor.cs index 83c434c58..ac9b01850 100644 --- a/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/TextureDescriptor.cs +++ b/Assets/VRMShaders/GLTF/IO/Runtime/Texture/Importer/TextureDescriptor.cs @@ -54,7 +54,7 @@ namespace VRMShaders { if (string.IsNullOrEmpty(name)) { - throw new ArgumentNullException("name"); + throw new ArgumentNullException(nameof(name)); } UnityObjectName = name; Offset = offset; diff --git a/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs b/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs index e73efc003..41dc1ce84 100644 --- a/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs +++ b/Assets/VRM_Samples/SimpleViewer/ViewerUI.cs @@ -416,9 +416,10 @@ namespace VRM.SimpleViewer case ".glb": case ".zip": { - var instance = await GltfUtility.LoadBytesAsync(path, bytes, + var instance = await GltfUtility.LoadAsync(path, GetIAwaitCaller(m_useAsync.isOn), GetGltfMaterialGenerator(m_useUrpMaterial.isOn)); + SetModel(instance); break; }