From 153ec536e64167ffafc003c0cf897461bcafebeb Mon Sep 17 00:00:00 2001 From: ousttrue Date: Fri, 12 Feb 2021 20:32:05 +0900 Subject: [PATCH] TextureItem to MaterialFactory.GetTextureAsync --- .../Runtime/UniGLTF/IO/ImporterContext.cs | 28 +- .../Runtime/UniGLTF/IO/MeshImporter.cs | 6 +- .../UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs | 133 +--------- .../MaterialFacotry/MaterialFactory.cs | 241 +++++++++++------- .../MaterialFacotry/MaterialItemBase.cs | 8 +- .../MaterialFacotry/PBRMaterialItem.cs | 36 ++- .../TextureLoader/AssetTextureLoader.cs | 28 +- .../TextureLoader/GltfTextureLoader.cs | 50 ++-- .../TextureLoader/ITextureLoader.cs | 23 -- .../TextureLoader/ITextureLoader.cs.meta | 12 - .../UnityWebRequestTextureLoader.cs | 2 +- .../MaterialFacotry/UnlitMaterialItem.cs | 13 +- Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs | 24 +- .../VRM.Samples/Scripts/VRMRuntimeExporter.cs | 4 +- .../VRM.Samples/Scripts/VRMRuntimeLoader.cs | 4 +- Assets/VRM.Samples/Scripts/ViewerUI.cs | 13 +- Assets/VRM/Runtime/IO/VRMImporterContext.cs | 37 +-- Assets/VRM/Runtime/IO/VRMMaterialImporter.cs | 17 +- 18 files changed, 257 insertions(+), 422 deletions(-) delete mode 100644 Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs delete mode 100644 Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 3445e005c..b6bbcbbc8 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -105,14 +105,9 @@ namespace UniGLTF #endregion - MaterialFactory m_materialFactory = new MaterialFactory(); + MaterialFactory m_materialFactory; public MaterialFactory MaterialFactory => m_materialFactory; - public ImporterContext(MaterialImporter materialImporter) - { - m_materialFactory.MaterialImporter = materialImporter; - } - public ImporterContext() { } @@ -267,12 +262,13 @@ namespace UniGLTF Json = json; Storage = storage; GLTF = GltfDeserializer.Deserialize(json.ParseAsJson()); - if (GLTF.asset.version != "2.0") { throw new UniGLTFException("unknown gltf version {0}", GLTF.asset.version); } + m_materialFactory = new MaterialFactory(GLTF, Storage); + // Version Compatibility RestoreOlderVersionValues(); @@ -501,10 +497,9 @@ namespace UniGLTF Schedulable.Create() .AddTask(Scheduler.ThreadPool, () => { - m_materialFactory.Prepare(GLTF); + // root task. do nothing }) - .ContinueWithCoroutine(Scheduler.MainThread, () => m_materialFactory.TexturesProcessOnMainThread(GLTF, Storage)) - .ContinueWithCoroutine(Scheduler.MainThread, () => m_materialFactory.LoadMaterials(GLTF)) + .ContinueWithCoroutine(Scheduler.MainThread, () => m_materialFactory.LoadMaterials()) .OnExecute(Scheduler.ThreadPool, parent => { // UniGLTF does not support draco @@ -695,16 +690,10 @@ namespace UniGLTF protected virtual IEnumerable ObjectsForSubAsset() { - HashSet textures = new HashSet(); - foreach (var x in MaterialFactory.GetTextures().SelectMany(y => y.GetTexturesForSaveAssets())) + foreach (var x in MaterialFactory.ObjectsForSubAsset()) { - if (!textures.Contains(x)) - { - textures.Add(x); - } + yield return x; } - foreach (var x in textures) { yield return x; } - foreach (var x in MaterialFactory.GetMaterials()) { yield return x.GetOrCreate(MaterialFactory.GetTexture); } foreach (var x in Meshes) { yield return x.Mesh; } foreach (var x in AnimationClips) { yield return x; } } @@ -895,7 +884,8 @@ namespace UniGLTF AssetDatabase.Refresh(); } - m_materialFactory.CreateTextureItems(GLTF, prefabParentDir); + // texture will load from assets + m_materialFactory.ImageBaseDir = prefabParentDir; } #endregion #endif diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs index 305a47bdc..c4346a974 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs @@ -634,10 +634,11 @@ namespace UniGLTF mesh.RecalculateTangents(); } + // 先にすべてのマテリアルを作成済みなのでテクスチャーは生成済み。Resultを使ってよい var result = new MeshWithMaterials { Mesh = mesh, - Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreate(ctx.GetTexture)).ToArray() + Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreateAsync(ctx.GetTextureAsync).Result).ToArray() }; if (meshContext.BlendShapes.Count > 0) @@ -662,10 +663,11 @@ namespace UniGLTF yield return null; } + // 先にすべてのマテリアルを作成済みなのでテクスチャーは生成済み。Resultを使ってよい var result = new MeshWithMaterials { Mesh = mesh, - Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreate(ctx.GetTexture)).ToArray() + Materials = meshContext.MaterialIndices.Select(x => ctx.GetMaterial(x).GetOrCreateAsync(ctx.GetTextureAsync).Result).ToArray() }; yield return null; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs index 6a0477461..320e23cb5 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs @@ -1,10 +1,6 @@ using UnityEngine; -using System.Linq; -using System.Collections.Generic; -using System.Collections; using System.IO; using System; -using DepthFirstScheduler; #if UNITY_EDITOR using UnityEditor; #endif @@ -12,135 +8,8 @@ using UnityEditor; namespace UniGLTF { - public class TextureItem + public static class TextureItem { - private int m_textureIndex; - public Texture2D Texture - { - get - { - return m_textureLoader.Texture; - } - } - - #region Texture converter - private Dictionary m_converts = new Dictionary(); - public Dictionary Converts - { - get { return m_converts; } - } - - /// - /// - /// - /// - /// used only when converting MetallicRoughness maps - /// - public Texture2D ConvertTexture(string prop, float smoothnessOrRoughness = 1.0f) - { - var convertedTexture = Converts.FirstOrDefault(x => x.Key == prop); - if (convertedTexture.Value != null) - return convertedTexture.Value; - - if (prop == "_BumpMap") - { - if (Application.isPlaying) - { - var converted = new NormalConverter().GetImportTexture(Texture); - m_converts.Add(prop, converted); - return converted; - } - else - { -#if UNITY_EDITOR - var textureAssetPath = AssetDatabase.GetAssetPath(Texture); - if (!string.IsNullOrEmpty(textureAssetPath)) - { - TextureIO.MarkTextureAssetAsNormalMap(textureAssetPath); - } - else - { - Debug.LogWarningFormat("no asset for {0}", Texture); - } -#endif - return Texture; - } - } - - if (prop == "_MetallicGlossMap") - { - var converted = new MetallicRoughnessConverter(smoothnessOrRoughness).GetImportTexture(Texture); - m_converts.Add(prop, converted); - return converted; - } - - if (prop == "_OcclusionMap") - { - var converted = new OcclusionConverter().GetImportTexture(Texture); - m_converts.Add(prop, converted); - return converted; - } - - return null; - } - #endregion - - public bool IsAsset - { - set; - get; - } - - public IEnumerable GetTexturesForSaveAssets() - { - if (!IsAsset) - { - yield return Texture; - } - if (m_converts.Any()) - { - foreach (var texture in m_converts) - { - yield return texture.Value; - } - } - } - - /// - /// Texture from buffer - /// - /// - public TextureItem(int index, ITextureLoader textureLoader) - { - m_textureIndex = index; - m_textureLoader = textureLoader; - - if (m_textureLoader == null) - { - throw new Exception("ITextureLoader is null."); - } - } - - #region Process - ITextureLoader m_textureLoader; - - // public void Process(glTF gltf, IStorage storage) - // { - // ProcessOnMainThreadCoroutine(gltf, storage).CoroutineToEnd(); - // } - - public IEnumerator ProcessOnMainThreadCoroutine(glTF gltf, IStorage storage) - { - using (m_textureLoader) - { - var textureType = TextureIO.GetglTFTextureType(gltf, m_textureIndex); - var colorSpace = TextureIO.GetColorSpace(textureType); - var isLinear = colorSpace == RenderTextureReadWrite.Linear; - yield return m_textureLoader.ProcessOnMainThread(gltf, storage, isLinear, gltf.GetSamplerFromTextureIndex(m_textureIndex)); - } - } - #endregion - struct ColorSpaceScope : IDisposable { bool m_sRGBWrite; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs index 14901128f..5c21c8d9c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs @@ -1,19 +1,80 @@ using System; using System.Collections; using System.Collections.Generic; -using System.IO; using System.Linq; +using System.Threading.Tasks; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif namespace UniGLTF { - public delegate TextureItem GetTextureItemFunc(int i); + public struct GetTextureParam + { + public const string NORMAL_PROP = "_BumpMap"; + public const string METALLIC_GLOSS_PROP = "_MetallicGlossMap"; + public const string OCCLUSION_PROP = "_OcclusionMap"; + + public readonly string TextureType; + public readonly float MetallicFactor; + public readonly ushort? Index0; + public readonly ushort? Index1; + public readonly ushort? Index2; + public readonly ushort? Index3; + public readonly ushort? Index4; + public readonly ushort? Index5; + + public GetTextureParam(string textureType, float metallicFactor, int i0, int i1, int i2, int i3, int i4, int i5) + { + TextureType = textureType; + MetallicFactor = metallicFactor; + Index0 = (ushort)i0; + Index1 = (ushort)i1; + Index2 = (ushort)i2; + Index3 = (ushort)i3; + Index4 = (ushort)i4; + Index5 = (ushort)i5; + } + + public static GetTextureParam Create(int index) + { + return new GetTextureParam(default, default, index, default, default, default, default, default); + } + + public static GetTextureParam CreateNormal(int index) + { + return new GetTextureParam(NORMAL_PROP, default, index, default, default, default, default, default); + } + + public static GetTextureParam CreateMetallic(int index, float metallicFactor) + { + return new GetTextureParam(METALLIC_GLOSS_PROP, metallicFactor, index, default, default, default, default, default); + } + + public static GetTextureParam CreateOcclusion(int index) + { + return new GetTextureParam(OCCLUSION_PROP, default, index, default, default, default, default, default); + } + } + + public delegate Task GetTextureAsyncFunc(GetTextureParam param); public delegate Shader GetShaderFunc(); public delegate MaterialItemBase MaterialImporter(int i, glTFMaterial x, bool hasVertexColor); public class MaterialFactory : IDisposable { + glTF m_gltf; + IStorage m_storage; + public MaterialFactory(glTF gltf, IStorage storage) + { + m_gltf = gltf; + m_storage = storage; + } + + public UnityPath ImageBaseDir { get; set; } + MaterialImporter m_materialImporter; public MaterialImporter MaterialImporter { @@ -31,22 +92,74 @@ namespace UniGLTF } } - List m_textures = new List(); - public IList GetTextures() + List m_textuers = new List(); + Dictionary m_textureCache = new Dictionary(); + + /// + /// テクスチャーをロード、必要であれば変換して返す。 + /// 同じものはキャッシュを返す + /// + /// 変換の有無を判断する: METALLIC_GLOSS_PROP + /// METALLIC_GLOSS_PROPの追加パラメーター + /// gltf の texture index + /// + public async Task GetTextureAsync(GetTextureParam param) { - return m_textures; - } - public TextureItem GetTexture(int i) - { - if (i < 0 || i >= m_textures.Count) + if (m_textureCache.TryGetValue(param, out Texture2D texture)) { - return null; + return texture; } - return m_textures[i]; - } - public void AddTexture(TextureItem item) - { - m_textures.Add(item); + + texture = await LoadTextureAsync(param.Index0.Value); + m_textureCache.Add(GetTextureParam.Create(param.Index0.Value), texture); + switch (param.TextureType) + { + case GetTextureParam.NORMAL_PROP: + { + if (Application.isPlaying) + { + var converted = new NormalConverter().GetImportTexture(texture); + m_textureCache.Add(param, converted); + return converted; + } + else + { +#if UNITY_EDITOR + var textureAssetPath = AssetDatabase.GetAssetPath(texture); + if (!string.IsNullOrEmpty(textureAssetPath)) + { + TextureIO.MarkTextureAssetAsNormalMap(textureAssetPath); + } + else + { + Debug.LogWarningFormat("no asset for {0}", texture); + } +#endif + m_textureCache.Add(param, texture); + return texture; + } + } + + case GetTextureParam.METALLIC_GLOSS_PROP: + { + // Bake roughnessFactor values into a texture. + var converted = new MetallicRoughnessConverter(param.MetallicFactor).GetImportTexture(texture); + m_textureCache.Add(param, converted); + return converted; + } + + case GetTextureParam.OCCLUSION_PROP: + { + var converted = new OcclusionConverter().GetImportTexture(texture); + m_textureCache.Add(param, converted); + return converted; + } + + default: + return texture; + } + + throw new NotImplementedException(); } List m_materials = new List(); @@ -71,95 +184,28 @@ namespace UniGLTF return m_materials[index]; } - public virtual ITextureLoader CreateTextureLoader(int index) + public virtual Task LoadTextureAsync(int index) { #if UNIGLTF_USE_WEBREQUEST_TEXTURELOADER - return new UnityWebRequestTextureLoader(index); + return UnityWebRequestTextureLoader.LoadTextureAsync(index); #else - return new GltfTextureLoader(index); + return GltfTextureLoader.LoadTextureAsync(m_gltf, m_storage, index); #endif } - public void Prepare(UniGLTF.glTF gltf, UnityPath imageBaseDir = default(UnityPath)) - { - if (m_textures.Count == 0) - { - // - // runtime - // - CreateTextureItems(gltf, imageBaseDir); - } - else - { - // - // already CreateTextures(by assetPostProcessor or editor menu) - // - } - - } - - public void CreateTextureItems(UniGLTF.glTF gltf, UnityPath imageBaseDir) - { - if (m_textures.Any()) - { - return; - } - - for (int i = 0; i < gltf.textures.Count; ++i) - { - - TextureItem item = null; -#if UNITY_EDITOR - var image = gltf.GetImageFromTextureIndex(i); - if (imageBaseDir.IsUnderAssetsFolder - && !string.IsNullOrEmpty(image.uri) - && !image.uri.FastStartsWith("data:") - ) - { - /// - /// required SaveTexturesAsPng or SetTextureBaseDir - /// - var assetPath = imageBaseDir.Child(image.uri); - var textureName = !string.IsNullOrEmpty(image.name) ? image.name : Path.GetFileNameWithoutExtension(image.uri); - item = new TextureItem(i, new AssetTextureLoader(assetPath, textureName)) - { - IsAsset = true - }; - } - else -#endif - { - item = new TextureItem(i, CreateTextureLoader(i)); - } - - AddTexture(item); - } - } - - public IEnumerator TexturesProcessOnMainThread(glTF gltf, IStorage storage) - { - // using (MeasureTime("TexturesProcessOnMainThread")) - { - foreach (var x in GetTextures()) - { - yield return x.ProcessOnMainThreadCoroutine(gltf, storage); - } - } - } - - public IEnumerator LoadMaterials(glTF gltf) + public IEnumerator LoadMaterials() { // using (MeasureTime("LoadMaterials")) { - if (gltf.materials == null || !gltf.materials.Any()) + if (m_gltf.materials == null || !m_gltf.materials.Any()) { AddMaterial(MaterialImporter(0, null, false)); } else { - for (int i = 0; i < gltf.materials.Count; ++i) + for (int i = 0; i < m_gltf.materials.Count; ++i) { - AddMaterial(MaterialImporter(i, gltf.materials[i], gltf.MaterialHasVertexColor(i))); + AddMaterial(MaterialImporter(i, m_gltf.materials[i], m_gltf.MaterialHasVertexColor(i))); } } } @@ -184,7 +230,22 @@ namespace UniGLTF public void Dispose() { - throw new NotImplementedException(); + foreach (var x in ObjectsForSubAsset()) + { + UnityEngine.Object.DestroyImmediate(x, true); + } + } + + public IEnumerable ObjectsForSubAsset() + { + foreach (var kv in m_textureCache) + { + yield return kv.Value; + } + foreach (var x in m_materials) + { + yield return x.GetOrCreateAsync(GetTextureAsync).Result; + } } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs index ad551e149..35191bab6 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using UnityEngine; @@ -17,7 +18,12 @@ namespace UniGLTF Name = src != null ? m_src.name : ""; } - public abstract Material GetOrCreate(GetTextureItemFunc getTexture); + public abstract Task GetOrCreateAsync(GetTextureAsyncFunc getTexture); + + public Material GetOrCreateForTest() + { + return GetOrCreateAsync(null).Result; + } protected Material CreateMaterial(string shaderName) { diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs index d8e0e06ac..9a2602473 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using System.Threading.Tasks; +using UnityEngine; namespace UniGLTF { @@ -45,11 +46,11 @@ namespace UniGLTF { } - public override Material GetOrCreate(GetTextureItemFunc getTexture) + public override async Task GetOrCreateAsync(GetTextureAsyncFunc getTexture) { if (getTexture == null) { - getTexture = _ => null; + getTexture = _ => Task.FromResult(null); } var material = CreateMaterial(ShaderName); @@ -67,11 +68,7 @@ namespace UniGLTF if (m_src.pbrMetallicRoughness.baseColorTexture != null && m_src.pbrMetallicRoughness.baseColorTexture.index != -1) { - var texture = getTexture(m_src.pbrMetallicRoughness.baseColorTexture.index); - if (texture != null) - { - material.mainTexture = texture.Texture; - } + material.mainTexture = await getTexture(GetTextureParam.Create(m_src.pbrMetallicRoughness.baseColorTexture.index)); // Texture Offset and Scale SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); @@ -80,12 +77,13 @@ namespace UniGLTF if (m_src.pbrMetallicRoughness.metallicRoughnessTexture != null && m_src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { material.EnableKeyword("_METALLICGLOSSMAP"); - var texture = getTexture(m_src.pbrMetallicRoughness.metallicRoughnessTexture.index); + + var texture = await getTexture(GetTextureParam.CreateMetallic( + m_src.pbrMetallicRoughness.metallicRoughnessTexture.index, + m_src.pbrMetallicRoughness.metallicFactor)); if (texture != null) { - var prop = "_MetallicGlossMap"; - // Bake roughnessFactor values into a texture. - material.SetTexture(prop, texture.ConvertTexture(prop, m_src.pbrMetallicRoughness.roughnessFactor)); + material.SetTexture(GetTextureParam.METALLIC_GLOSS_PROP, texture); } material.SetFloat("_Metallic", 1.0f); @@ -105,11 +103,10 @@ namespace UniGLTF if (m_src.normalTexture != null && m_src.normalTexture.index != -1) { material.EnableKeyword("_NORMALMAP"); - var texture = getTexture(m_src.normalTexture.index); + var texture = await getTexture(GetTextureParam.CreateNormal(m_src.normalTexture.index)); if (texture != null) { - var prop = "_BumpMap"; - material.SetTexture(prop, texture.ConvertTexture(prop)); + material.SetTexture(GetTextureParam.NORMAL_PROP, texture); material.SetFloat("_BumpScale", m_src.normalTexture.scale); } @@ -119,11 +116,10 @@ namespace UniGLTF if (m_src.occlusionTexture != null && m_src.occlusionTexture.index != -1) { - var texture = getTexture(m_src.occlusionTexture.index); + var texture = await getTexture(GetTextureParam.CreateOcclusion(m_src.occlusionTexture.index)); if (texture != null) { - var prop = "_OcclusionMap"; - material.SetTexture(prop, texture.ConvertTexture(prop)); + material.SetTexture(GetTextureParam.OCCLUSION_PROP, texture); material.SetFloat("_OcclusionStrength", m_src.occlusionTexture.strength); } @@ -144,10 +140,10 @@ namespace UniGLTF if (m_src.emissiveTexture != null && m_src.emissiveTexture.index != -1) { - var texture = getTexture(m_src.emissiveTexture.index); + var texture = await getTexture(GetTextureParam.Create(m_src.emissiveTexture.index)); if (texture != null) { - material.SetTexture("_EmissionMap", texture.Texture); + material.SetTexture("_EmissionMap", texture); } // Texture Offset and Scale diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/AssetTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/AssetTextureLoader.cs index 9c92a7a02..352f0396e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/AssetTextureLoader.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/AssetTextureLoader.cs @@ -1,29 +1,14 @@ using System.Collections; +using System.Threading.Tasks; using UnityEngine; namespace UniGLTF { #if UNITY_EDITOR - public class AssetTextureLoader : ITextureLoader + public static class AssetTextureLoader { - public Texture2D Texture - { - private set; - get; - } - - UnityPath m_assetPath; - - public AssetTextureLoader(UnityPath assetPath, string _) - { - m_assetPath = assetPath; - } - - public void Dispose() - { - } - - public IEnumerator ProcessOnMainThread(glTF gltf, IStorage storage, bool isLinear, glTFTextureSampler sampler) + public static Task LoadTaskAsync(UnityPath m_assetPath, + bool isLinear, glTFTextureSampler sampler) { // // texture from assets @@ -39,9 +24,8 @@ namespace UniGLTF importer.SaveAndReimport(); - Texture = m_assetPath.LoadAsset(); + var Texture = m_assetPath.LoadAsset(); - //Texture.name = m_textureName; if (Texture == null) { Debug.LogWarningFormat("fail to Load Texture2D: {0}", m_assetPath); @@ -66,7 +50,7 @@ namespace UniGLTF TextureSamplerUtil.SetSampler(Texture, sampler); } - yield break; + return Task.FromResult(Texture); } } #endif diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/GltfTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/GltfTextureLoader.cs index 17028c1cc..50eb5c3de 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/GltfTextureLoader.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/GltfTextureLoader.cs @@ -1,28 +1,11 @@ using System; -using System.Collections; using System.Threading.Tasks; using UnityEngine; namespace UniGLTF { - public class GltfTextureLoader : ITextureLoader + public static class GltfTextureLoader { - int m_textureIndex; - public GltfTextureLoader(int textureIndex) - { - m_textureIndex = textureIndex; - } - - public Texture2D Texture - { - private set; - get; - } - - public void Dispose() - { - } - static Byte[] ToArray(ArraySegment bytes) { if (bytes.Array == null) @@ -41,36 +24,35 @@ namespace UniGLTF } } - string m_textureName; - - public IEnumerator ProcessOnMainThread(glTF gltf, IStorage storage, bool isLinear, glTFTextureSampler sampler) + public static async Task LoadTextureAsync(glTF gltf, IStorage storage, int index) { - Byte[] imageBytes = default; - var task = Task.Run(() => + string m_textureName = default; + var imageBytes = await Task.Run(() => { - var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); + var imageIndex = gltf.GetImageIndexFromTextureIndex(index); var segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); - var m_imageBytes = ToArray(segments); + return ToArray(segments); }); - while (!task.IsCompleted) - { - yield break; - } // // texture from image(png etc) bytes // - Texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, isLinear); - Texture.name = m_textureName; + var textureType = TextureIO.GetglTFTextureType(gltf, index); + var colorSpace = TextureIO.GetColorSpace(textureType); + var isLinear = colorSpace == RenderTextureReadWrite.Linear; + var sampler = gltf.GetSamplerFromTextureIndex(index); + + var texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, isLinear); + texture.name = m_textureName; if (imageBytes != null) { - Texture.LoadImage(imageBytes); + texture.LoadImage(imageBytes); } if (sampler != null) { - TextureSamplerUtil.SetSampler(Texture, sampler); + TextureSamplerUtil.SetSampler(texture, sampler); } - yield break; + return texture; } } } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs deleted file mode 100644 index a0381ab87..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections; -using UnityEngine; -#if UNITY_EDITOR -using UnityEditor; -#endif - - -namespace UniGLTF -{ - public interface ITextureLoader : IDisposable - { - Texture2D Texture { get; } - - /// - /// Call from unity main thread - /// - /// - /// - /// - IEnumerator ProcessOnMainThread(glTF gltf, IStorage storage, bool isLinear, glTFTextureSampler sampler); - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs.meta deleted file mode 100644 index a1aa6bbfe..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/ITextureLoader.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 4ffd8b31d371e024593b9aff2cf2495b -timeCreated: 1540300073 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/UnityWebRequestTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/UnityWebRequestTextureLoader.cs index 775f71375..226565715 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/UnityWebRequestTextureLoader.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/TextureLoader/UnityWebRequestTextureLoader.cs @@ -7,7 +7,7 @@ using UnityEngine.Networking; namespace UniGLTF { - public class UnityWebRequestTextureLoader : ITextureLoader + public class UnityWebRequestTextureLoader { public Texture2D Texture { diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs index 11f6cd43b..cadf7272c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using System.Threading.Tasks; +using UnityEngine; namespace UniGLTF { @@ -13,11 +14,11 @@ namespace UniGLTF m_hasVertexColor = hasVertexColor; } - public override Material GetOrCreate(GetTextureItemFunc getTexture) + public override async Task GetOrCreateAsync(GetTextureAsyncFunc getTexture) { if (getTexture == null) { - getTexture = _ => null; + getTexture = _ => Task.FromResult(null); } var material = CreateMaterial(ShaderName); @@ -25,11 +26,7 @@ namespace UniGLTF // texture if (m_src.pbrMetallicRoughness.baseColorTexture != null) { - var texture = getTexture(m_src.pbrMetallicRoughness.baseColorTexture.index); - if (texture != null) - { - material.mainTexture = texture.Texture; - } + material.mainTexture = await getTexture(GetTextureParam.Create(m_src.pbrMetallicRoughness.baseColorTexture.index)); // Texture Offset and Scale SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); diff --git a/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs b/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs index 42c7d34bf..0860a5199 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs @@ -32,7 +32,7 @@ namespace UniGLTF var gltfMaterial = materialExporter.ExportMaterial(srcMaterial, textureManager); gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions = gltfMaterial.pbrMetallicRoughness.baseColorTexture.extensions.Deserialize(); - var dstMaterial = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var dstMaterial = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual(dstMaterial.mainTextureOffset.x, offset.x, 0.3f); Assert.AreEqual(dstMaterial.mainTextureOffset.y, offset.y, 0.2f); @@ -80,7 +80,7 @@ namespace UniGLTF Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial)); - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } } @@ -99,7 +99,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -114,7 +114,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -130,7 +130,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -145,7 +145,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -160,7 +160,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -176,7 +176,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -191,7 +191,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -207,7 +207,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -217,7 +217,7 @@ namespace UniGLTF { extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreateForTest(); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } } @@ -225,7 +225,7 @@ namespace UniGLTF [Test] public void MaterialImportTest() { - var material = MaterialFactory.CreateMaterial(0, new glTFMaterial { }, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterial(0, new glTFMaterial { }, false).GetOrCreateForTest(); Assert.AreEqual("Standard", material.shader.name); } diff --git a/Assets/VRM.Samples/Scripts/VRMRuntimeExporter.cs b/Assets/VRM.Samples/Scripts/VRMRuntimeExporter.cs index 08cbcb036..1d4e3ac84 100644 --- a/Assets/VRM.Samples/Scripts/VRMRuntimeExporter.cs +++ b/Assets/VRM.Samples/Scripts/VRMRuntimeExporter.cs @@ -29,7 +29,7 @@ namespace VRM.Samples #region Load - void OnLoadClicked() + async void OnLoadClicked() { #if UNITY_STANDALONE_WIN var path = FileDialogForWindows.FileDialog("open VRM", ".vrm"); @@ -53,7 +53,7 @@ namespace VRM.Samples // metaを取得(todo: thumbnailテクスチャのロード) - var meta = context.ReadMeta(); + var meta = await context.ReadMetaAsync(); Debug.LogFormat("meta: title:{0}", meta.Title); // ParseしたJSONをシーンオブジェクトに変換していく diff --git a/Assets/VRM.Samples/Scripts/VRMRuntimeLoader.cs b/Assets/VRM.Samples/Scripts/VRMRuntimeLoader.cs index c9d20608a..4b6d85804 100644 --- a/Assets/VRM.Samples/Scripts/VRMRuntimeLoader.cs +++ b/Assets/VRM.Samples/Scripts/VRMRuntimeLoader.cs @@ -70,7 +70,7 @@ namespace VRM.Samples m_canvas.LoadBVHButton.onClick.AddListener(LoadBVHClicked); } - void LoadVRMClicked() + async void LoadVRMClicked() { #if UNITY_STANDALONE_WIN var path = FileDialogForWindows.FileDialog("open VRM", ".vrm"); @@ -94,7 +94,7 @@ namespace VRM.Samples // metaを取得(todo: thumbnailテクスチャのロード) - var meta = context.ReadMeta(); + var meta = await context.ReadMetaAsync(); Debug.LogFormat("meta: title:{0}", meta.Title); diff --git a/Assets/VRM.Samples/Scripts/ViewerUI.cs b/Assets/VRM.Samples/Scripts/ViewerUI.cs index 6de3d72ca..9c1e71288 100644 --- a/Assets/VRM.Samples/Scripts/ViewerUI.cs +++ b/Assets/VRM.Samples/Scripts/ViewerUI.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using System.Threading.Tasks; using UniHumanoid; using UnityEngine; using UnityEngine.UI; @@ -83,9 +84,9 @@ namespace VRM.Samples m_textDistributionOther.text = ""; } - public void UpdateMeta(VRMImporterContext context) + public async Task UpdateMetaAsync(VRMImporterContext context) { - var meta = context.ReadMeta(true); + var meta = await context.ReadMetaAsync(true); m_textModelTitle.text = meta.Title; m_textModelVersion.text = meta.Version; @@ -211,7 +212,7 @@ namespace VRM.Samples string[] cmds = System.Environment.GetCommandLineArgs(); if (cmds.Length > 1) { - LoadModel(cmds[1]); + LoadModelAsync(cmds[1]); } m_texts.Start(); @@ -282,7 +283,7 @@ namespace VRM.Samples case ".glb": case ".vrm": case ".zip": - LoadModel(path); + LoadModelAsync(path); break; case ".bvh": @@ -291,7 +292,7 @@ namespace VRM.Samples } } - void LoadModel(string path) + async void LoadModelAsync(string path) { if (!File.Exists(path)) { @@ -307,7 +308,7 @@ namespace VRM.Samples var context = new VRMImporterContext(); var file = File.ReadAllBytes(path); context.ParseGlb(file); - m_texts.UpdateMeta(context); + await m_texts.UpdateMetaAsync(context); context.Load(); context.ShowMeshes(); context.EnableUpdateWhenOffscreen(); diff --git a/Assets/VRM/Runtime/IO/VRMImporterContext.cs b/Assets/VRM/Runtime/IO/VRMImporterContext.cs index fc0c19780..76d8a2a5b 100644 --- a/Assets/VRM/Runtime/IO/VRMImporterContext.cs +++ b/Assets/VRM/Runtime/IO/VRMImporterContext.cs @@ -6,7 +6,7 @@ using UnityEngine; using System.IO; using System.Collections; using UniJSON; -using DepthFirstScheduler; +using System.Threading.Tasks; namespace VRM { @@ -58,7 +58,11 @@ namespace VRM using (MeasureTime("VRM LoadMeta")) { - LoadMeta(); + var task = LoadMetaAsync(); + while (!task.IsCompleted) + { + yield return null; + } } yield return null; @@ -87,9 +91,9 @@ namespace VRM } } - void LoadMeta() + async Task LoadMetaAsync() { - var meta = ReadMeta(); + var meta = await ReadMetaAsync(); var _meta = Root.AddComponent(); _meta.Meta = meta; Meta = meta; @@ -194,7 +198,9 @@ namespace VRM } } - var material = MaterialFactory.GetMaterials().FirstOrDefault(y => y.Name == x.materialName).GetOrCreate(MaterialFactory.GetTexture); + var material = MaterialFactory.GetMaterials() + .FirstOrDefault(y => y.Name == x.materialName) + .GetOrCreateAsync(MaterialFactory.GetTextureAsync).Result; var propertyName = x.propertyName; if (x.propertyName.FastEndsWith("_ST_S") || x.propertyName.FastEndsWith("_ST_T")) @@ -293,7 +299,7 @@ namespace VRM public BlendShapeAvatar BlendShapeAvatar; public VRMMetaObject Meta; - public VRMMetaObject ReadMeta(bool createThumbnail = false) + public async Task ReadMetaAsync(bool createThumbnail = false) { var meta = ScriptableObject.CreateInstance(); meta.name = "Meta"; @@ -305,24 +311,7 @@ namespace VRM meta.ContactInformation = gltfMeta.contactInformation; meta.Reference = gltfMeta.reference; meta.Title = gltfMeta.title; - - var thumbnail = MaterialFactory.GetTexture(gltfMeta.texture); - if (thumbnail != null) - { - // ロード済み - meta.Thumbnail = thumbnail.Texture; - } - else if (createThumbnail) - { - // 作成する(先行ロード用) - if (gltfMeta.texture >= 0 && gltfMeta.texture < GLTF.textures.Count) - { - var t = new TextureItem(gltfMeta.texture, MaterialFactory.CreateTextureLoader(gltfMeta.texture)); - t.ProcessOnMainThreadCoroutine(GLTF, Storage).CoroutineToEnd(); - meta.Thumbnail = t.Texture; - } - } - + meta.Thumbnail = await MaterialFactory.GetTextureAsync(GetTextureParam.Create(gltfMeta.texture)); meta.AllowedUser = gltfMeta.allowedUser; meta.ViolentUssage = gltfMeta.violentUssage; meta.SexualUssage = gltfMeta.sexualUssage; diff --git a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs index c758deb49..26caed56c 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs @@ -3,6 +3,7 @@ using UniGLTF; using UnityEngine; using System.Linq; using System; +using System.Threading.Tasks; namespace VRM { @@ -29,7 +30,7 @@ namespace VRM m_vrmMaterial = vrmMaterial; } - public override Material GetOrCreate(GetTextureItemFunc getTexture) + public override async Task GetOrCreateAsync(GetTextureAsyncFunc getTexture) { var item = m_vrmMaterial; var shaderName = item.shader; @@ -47,7 +48,7 @@ namespace VRM { Debug.LogWarningFormat("unknown shader {0}.", shaderName); } - return MaterialFactory.CreateMaterial(m_index, m_src, m_hasVertexColor).GetOrCreate(getTexture); + return await MaterialFactory.CreateMaterial(m_index, m_src, m_hasVertexColor).GetOrCreateAsync(getTexture); } // @@ -78,18 +79,10 @@ namespace VRM } foreach (var kv in item.textureProperties) { - var texture = getTexture(kv.Value); + var texture = await getTexture(new GetTextureParam(kv.Key, default, kv.Value, default, default, default, default, default)); if (texture != null) { - var converted = texture.ConvertTexture(kv.Key); - if (converted != null) - { - material.SetTexture(kv.Key, converted); - } - else - { - material.SetTexture(kv.Key, texture.Texture); - } + material.SetTexture(kv.Key, texture); } } foreach (var kv in item.keywordMap)