diff --git a/Assets/UniGLTF/Runtime/DepthFirstScheduler/IEnumeratorExtensions.cs b/Assets/UniGLTF/Runtime/DepthFirstScheduler/IEnumeratorExtensions.cs index 30bd9f66d..cb89c4c9b 100644 --- a/Assets/UniGLTF/Runtime/DepthFirstScheduler/IEnumeratorExtensions.cs +++ b/Assets/UniGLTF/Runtime/DepthFirstScheduler/IEnumeratorExtensions.cs @@ -3,8 +3,7 @@ using System.Collections; using System.Collections.Generic; -namespace - DepthFirstScheduler +namespace DepthFirstScheduler { public static class IEnumeratorExtensions { diff --git a/Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs new file mode 100644 index 000000000..f20c48fc8 --- /dev/null +++ b/Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; + +namespace UniGLTF +{ + /// + /// work around + /// + /// https://forum.unity.com/threads/async-await-in-editor-script.481276/ + /// + /// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Scripting/UnitySynchronizationContext.cs + /// + /// + /// + /// + public static class TaskExtensions + { + delegate void ExecFunc(); + + static ExecFunc s_exec; + + static void Invoke() + { + if (s_exec == null) + { + var context = SynchronizationContext.Current; + var t = context.GetType(); + var execMethod = t.GetMethod("Exec", BindingFlags.NonPublic | BindingFlags.Instance); + var exec = execMethod.CreateDelegate(typeof(ExecFunc), context); + s_exec = (ExecFunc)exec; + } + s_exec(); + } + + public static IEnumerable AsIEnumerator(this Task task) + { + while (!task.IsCompleted) + { + yield return null; + +#if UNITY_EDITOR + if (!UnityEngine.Application.isPlaying) + { + Invoke(); + } +#endif + } + + if (task.IsFaulted) + { + throw task.Exception; + } + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs.meta b/Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs.meta similarity index 83% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs.meta rename to Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs.meta index d6713eb21..b42a81728 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs.meta +++ b/Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f49a88d3a0e6eb24e91af983452f59f6 +guid: 54481e2d4da20ec4fa15376518f2e938 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 12622452e..25f231224 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -105,13 +105,11 @@ namespace UniGLTF #endregion - MaterialFactory m_materialFactory = new MaterialFactory(); + MaterialFactory m_materialFactory; public MaterialFactory MaterialFactory => m_materialFactory; - public ImporterContext(MaterialImporter materialImporter) - { - m_materialFactory.MaterialImporter = materialImporter; - } + TextureFactory m_textureFactory; + public TextureFactory TextureFactory => m_textureFactory; public ImporterContext() { @@ -267,12 +265,14 @@ 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_textureFactory = new TextureFactory(GLTF, Storage); + m_materialFactory = new MaterialFactory(GLTF, Storage); + // Version Compatibility RestoreOlderVersionValues(); @@ -501,11 +501,15 @@ namespace UniGLTF Schedulable.Create() .AddTask(Scheduler.ThreadPool, () => { - m_materialFactory.Prepare(GLTF); + // root task. do nothing + }) + .ContinueWithCoroutine(Scheduler.MainThread, () => + { + using (MeasureTime("LoadMaterials")) + { + return m_materialFactory.LoadMaterials(m_textureFactory.GetTextureAsync); + } }) - .ContinueWithCoroutine(Scheduler.ThreadPool, () => m_materialFactory.TexturesProcessOnAnyThread(GLTF, Storage)) - .ContinueWithCoroutine(Scheduler.MainThread, () => m_materialFactory.TexturesProcessOnMainThread(GLTF)) - .ContinueWithCoroutine(Scheduler.MainThread, () => m_materialFactory.LoadMaterials(GLTF)) .OnExecute(Scheduler.ThreadPool, parent => { // UniGLTF does not support draco @@ -696,16 +700,14 @@ namespace UniGLTF protected virtual IEnumerable ObjectsForSubAsset() { - HashSet textures = new HashSet(); - foreach (var x in MaterialFactory.GetTextures().SelectMany(y => y.GetTexturesForSaveAssets())) + foreach (var x in TextureFactory.ObjectsForSubAsset()) { - if (!textures.Contains(x)) - { - textures.Add(x); - } + yield return x; + } + foreach (var x in MaterialFactory.ObjectsForSubAsset()) + { + 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; } } @@ -896,7 +898,8 @@ namespace UniGLTF AssetDatabase.Refresh(); } - m_materialFactory.CreateTextureItems(GLTF, prefabParentDir); + // texture will load from assets + m_textureFactory.ImageBaseDir = prefabParentDir; } #endregion #endif @@ -939,10 +942,16 @@ namespace UniGLTF if (Root != null) GameObject.Destroy(Root); // Remove resources. materials, textures meshes etc... - foreach (var o in ObjectsForSubAsset()) + foreach (var x in Meshes) { - UnityEngine.Object.DestroyImmediate(o, true); + UnityEngine.Object.DestroyImmediate(x.Mesh, true); } + foreach (var x in AnimationClips) + { + UnityEngine.Object.DestroyImmediate(x, true); + } + MaterialFactory.Dispose(); + TextureFactory.Dispose(); } #if UNITY_EDITOR diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader.meta similarity index 100% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs new file mode 100644 index 000000000..c4e63eeb2 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using UnityEngine; + +namespace UniGLTF +{ + public class MaterialFactory : IDisposable + { + glTF m_gltf; + IStorage m_storage; + public MaterialFactory(glTF gltf, IStorage storage) + { + m_gltf = gltf; + m_storage = storage; + } + + public delegate Task CreateMaterialAsyncFunc(glTF glTF, int i, GetTextureAsyncFunc getTexture); + CreateMaterialAsyncFunc m_createMaterialAsync; + public CreateMaterialAsyncFunc CreateMaterialAsync + { + set + { + m_createMaterialAsync = value; + } + get + { + if (m_createMaterialAsync == null) + { + m_createMaterialAsync = MaterialFactory.DefaultCreateMaterialAsync; + } + return m_createMaterialAsync; + } + } + + List m_materials = new List(); + public IReadOnlyList Materials => m_materials; + public void Dispose() + { + foreach (var x in ObjectsForSubAsset()) + { + UnityEngine.Object.DestroyImmediate(x, true); + } + } + + public IEnumerable ObjectsForSubAsset() + { + foreach (var x in m_materials) + { + yield return x; + } + } + + public void AddMaterial(Material material) + { + var originalName = material.name; + int j = 2; + while (m_materials.Any(x => x.name == material.name)) + { + material.name = string.Format("{0}({1})", originalName, j++); + } + m_materials.Add(material); + } + public Material GetMaterial(int index) + { + if (index < 0) return null; + if (index >= m_materials.Count) return null; + return m_materials[index]; + } + + public IEnumerator LoadMaterials(GetTextureAsyncFunc getTexture) + { + if (m_gltf.materials == null || m_gltf.materials.Count == 0) + { + var task = CreateMaterialAsync(m_gltf, 0, getTexture); + + foreach (var x in task.AsIEnumerator()) + { + yield return x; + } + + AddMaterial(task.Result); + } + else + { + for (int i = 0; i < m_gltf.materials.Count; ++i) + { + var task = CreateMaterialAsync(m_gltf, i, getTexture); + foreach (var x in task.AsIEnumerator()) + { + yield return null; + } + + AddMaterial(task.Result); + } + } + yield return null; + } + + public static Material CreateMaterial(int index, glTFMaterial src, string shaderName) + { + var material = new Material(Shader.Find(shaderName)); +#if UNITY_EDITOR + // textureImporter.SaveAndReimport(); may destroy this material + material.hideFlags = HideFlags.DontUnloadUnusedAsset; +#endif + material.name = (src == null || string.IsNullOrEmpty(src.name)) + ? string.Format("material_{0:00}", index) + : src.name + ; + + return material; + } + + public static void SetTextureOffsetAndScale(Material material, glTFTextureInfo textureInfo, string propertyName) + { + if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform)) + { + Vector2 offset = new Vector2(0, 0); + Vector2 scale = new Vector2(1, 1); + if (textureTransform.offset != null && textureTransform.offset.Length == 2) + { + offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]); + } + if (textureTransform.scale != null && textureTransform.scale.Length == 2) + { + scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]); + } + + offset.y = (offset.y + scale.y - 1.0f) * -1.0f; + + material.SetTextureOffset(propertyName, offset); + material.SetTextureScale(propertyName, scale); + } + } + + public static Task DefaultCreateMaterialAsync(glTF gltf, int i, GetTextureAsyncFunc getTexture) + { + + if (i < 0 || i >= gltf.materials.Count) + { + UnityEngine.Debug.LogWarning("glTFMaterial is empty"); + return PBRMaterialItem.CreateAsync(i, null, getTexture); + } + var x = gltf.materials[i]; + + if (glTF_KHR_materials_unlit.IsEnable(x)) + { + var hasVertexColor = gltf.MaterialHasVertexColor(i); + return UnlitMaterialItem.CreateAsync(i, x, getTexture, hasVertexColor); + } + + return PBRMaterialItem.CreateAsync(i, x, getTexture); + } + + /// + /// for unittest + /// + /// + /// + /// + /// + public static Material CreateMaterialForTest(int i, glTFMaterial material) + { + var gltf = new glTF + { + materials = new System.Collections.Generic.List { material }, + }; + var task = DefaultCreateMaterialAsync(gltf, i, null); + return task.Result; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs.meta similarity index 100% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/PBRMaterialItem.cs similarity index 60% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/PBRMaterialItem.cs index d8e0e06ac..444353f98 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/PBRMaterialItem.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using System.Threading.Tasks; +using UnityEngine; namespace UniGLTF { @@ -29,7 +30,7 @@ namespace UniGLTF /// _SrcBlend /// _DstBlend /// _ZWrite - public class PBRMaterialItem : MaterialItemBase + public static class PBRMaterialItem { public const string ShaderName = "Standard"; @@ -41,51 +42,44 @@ namespace UniGLTF Transparent } - public PBRMaterialItem(int i, glTFMaterial src) : base(i, src) - { - } - - public override Material GetOrCreate(GetTextureItemFunc getTexture) + public static async Task CreateAsync(int i, glTFMaterial src, GetTextureAsyncFunc getTexture) { if (getTexture == null) { - getTexture = _ => null; + getTexture = _ => Task.FromResult(null); } - var material = CreateMaterial(ShaderName); + var material = MaterialFactory.CreateMaterial(i, src, ShaderName); // PBR material - if (m_src != null) + if (src != null) { - if (m_src.pbrMetallicRoughness != null) + if (src.pbrMetallicRoughness != null) { - if (m_src.pbrMetallicRoughness.baseColorFactor != null && m_src.pbrMetallicRoughness.baseColorFactor.Length == 4) + if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) { - var color = m_src.pbrMetallicRoughness.baseColorFactor; + var color = src.pbrMetallicRoughness.baseColorFactor; material.color = (new Color(color[0], color[1], color[2], color[3])).gamma; } - if (m_src.pbrMetallicRoughness.baseColorTexture != null && m_src.pbrMetallicRoughness.baseColorTexture.index != -1) + if (src.pbrMetallicRoughness.baseColorTexture != null && 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(src.pbrMetallicRoughness.baseColorTexture.index)); // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); + MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); } - if (m_src.pbrMetallicRoughness.metallicRoughnessTexture != null && m_src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) + if (src.pbrMetallicRoughness.metallicRoughnessTexture != null && src.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) { material.EnableKeyword("_METALLICGLOSSMAP"); - var texture = getTexture(m_src.pbrMetallicRoughness.metallicRoughnessTexture.index); + + var texture = await getTexture(GetTextureParam.CreateMetallic( + src.pbrMetallicRoughness.metallicRoughnessTexture.index, + 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); @@ -93,71 +87,69 @@ namespace UniGLTF material.SetFloat("_GlossMapScale", 1.0f); // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap"); + MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.metallicRoughnessTexture, "_MetallicGlossMap"); } else { - material.SetFloat("_Metallic", m_src.pbrMetallicRoughness.metallicFactor); - material.SetFloat("_Glossiness", 1.0f - m_src.pbrMetallicRoughness.roughnessFactor); + material.SetFloat("_Metallic", src.pbrMetallicRoughness.metallicFactor); + material.SetFloat("_Glossiness", 1.0f - src.pbrMetallicRoughness.roughnessFactor); } } - if (m_src.normalTexture != null && m_src.normalTexture.index != -1) + if (src.normalTexture != null && src.normalTexture.index != -1) { material.EnableKeyword("_NORMALMAP"); - var texture = getTexture(m_src.normalTexture.index); + var texture = await getTexture(GetTextureParam.CreateNormal(src.normalTexture.index)); if (texture != null) { - var prop = "_BumpMap"; - material.SetTexture(prop, texture.ConvertTexture(prop)); - material.SetFloat("_BumpScale", m_src.normalTexture.scale); + material.SetTexture(GetTextureParam.NORMAL_PROP, texture); + material.SetFloat("_BumpScale", src.normalTexture.scale); } // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.normalTexture, "_BumpMap"); + MaterialFactory.SetTextureOffsetAndScale(material, src.normalTexture, "_BumpMap"); } - if (m_src.occlusionTexture != null && m_src.occlusionTexture.index != -1) + if (src.occlusionTexture != null && src.occlusionTexture.index != -1) { - var texture = getTexture(m_src.occlusionTexture.index); + var texture = await getTexture(GetTextureParam.CreateOcclusion(src.occlusionTexture.index)); if (texture != null) { - var prop = "_OcclusionMap"; - material.SetTexture(prop, texture.ConvertTexture(prop)); - material.SetFloat("_OcclusionStrength", m_src.occlusionTexture.strength); + material.SetTexture(GetTextureParam.OCCLUSION_PROP, texture); + material.SetFloat("_OcclusionStrength", src.occlusionTexture.strength); } // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.occlusionTexture, "_OcclusionMap"); + MaterialFactory.SetTextureOffsetAndScale(material, src.occlusionTexture, "_OcclusionMap"); } - if (m_src.emissiveFactor != null - || (m_src.emissiveTexture != null && m_src.emissiveTexture.index != -1)) + if (src.emissiveFactor != null + || (src.emissiveTexture != null && src.emissiveTexture.index != -1)) { material.EnableKeyword("_EMISSION"); material.globalIlluminationFlags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack; - if (m_src.emissiveFactor != null && m_src.emissiveFactor.Length == 3) + if (src.emissiveFactor != null && src.emissiveFactor.Length == 3) { - material.SetColor("_EmissionColor", new Color(m_src.emissiveFactor[0], m_src.emissiveFactor[1], m_src.emissiveFactor[2])); + material.SetColor("_EmissionColor", new Color(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2])); } - if (m_src.emissiveTexture != null && m_src.emissiveTexture.index != -1) + if (src.emissiveTexture != null && src.emissiveTexture.index != -1) { - var texture = getTexture(m_src.emissiveTexture.index); + var texture = await getTexture(GetTextureParam.Create(src.emissiveTexture.index)); if (texture != null) { - material.SetTexture("_EmissionMap", texture.Texture); + material.SetTexture("_EmissionMap", texture); } // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.emissiveTexture, "_EmissionMap"); + MaterialFactory.SetTextureOffsetAndScale(material, src.emissiveTexture, "_EmissionMap"); } } BlendMode blendMode = BlendMode.Opaque; // https://forum.unity.com/threads/standard-material-shader-ignoring-setfloat-property-_mode.344557/#post-2229980 - switch (m_src.alphaMode) + switch (src.alphaMode) { case "BLEND": blendMode = BlendMode.Fade; @@ -177,7 +169,7 @@ namespace UniGLTF material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); material.SetInt("_ZWrite", 1); - material.SetFloat("_Cutoff", m_src.alphaCutoff); + material.SetFloat("_Cutoff", src.alphaCutoff); material.EnableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/PBRMaterialItem.cs.meta similarity index 100% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/PBRMaterialItem.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/PBRMaterialItem.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/UnlitMaterialItem.cs similarity index 53% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/UnlitMaterialItem.cs index 11f6cd43b..f39da4366 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/UnlitMaterialItem.cs @@ -1,60 +1,50 @@ -using UnityEngine; +using System.Threading.Tasks; +using UnityEngine; namespace UniGLTF { - public class UnlitMaterialItem : MaterialItemBase + public static class UnlitMaterialItem { public const string ShaderName = "UniGLTF/UniUnlit"; - bool m_hasVertexColor; - - public UnlitMaterialItem(int i, glTFMaterial src, bool hasVertexColor) : base(i, src) - { - m_hasVertexColor = hasVertexColor; - } - - public override Material GetOrCreate(GetTextureItemFunc getTexture) + public static async Task CreateAsync(int i, glTFMaterial src, GetTextureAsyncFunc getTexture, bool hasVertexColor) { if (getTexture == null) { - getTexture = _ => null; + getTexture = _ => Task.FromResult(null); } - var material = CreateMaterial(ShaderName); + var material = MaterialFactory.CreateMaterial(i, src, ShaderName); // texture - if (m_src.pbrMetallicRoughness.baseColorTexture != null) + if (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(src.pbrMetallicRoughness.baseColorTexture.index)); // Texture Offset and Scale - SetTextureOffsetAndScale(material, m_src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); + MaterialFactory.SetTextureOffsetAndScale(material, src.pbrMetallicRoughness.baseColorTexture, "_MainTex"); } // color - if (m_src.pbrMetallicRoughness.baseColorFactor != null && m_src.pbrMetallicRoughness.baseColorFactor.Length == 4) + if (src.pbrMetallicRoughness.baseColorFactor != null && src.pbrMetallicRoughness.baseColorFactor.Length == 4) { - var color = m_src.pbrMetallicRoughness.baseColorFactor; + var color = src.pbrMetallicRoughness.baseColorFactor; material.color = (new Color(color[0], color[1], color[2], color[3])).gamma; } //renderMode - if (m_src.alphaMode == "OPAQUE") + if (src.alphaMode == "OPAQUE") { UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Opaque); } - else if (m_src.alphaMode == "BLEND") + else if (src.alphaMode == "BLEND") { UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Transparent); } - else if (m_src.alphaMode == "MASK") + else if (src.alphaMode == "MASK") { UniUnlit.Utils.SetRenderMode(material, UniUnlit.UniUnlitRenderMode.Cutout); - material.SetFloat("_Cutoff", m_src.alphaCutoff); + material.SetFloat("_Cutoff", src.alphaCutoff); } else { @@ -63,7 +53,7 @@ namespace UniGLTF } // culling - if (m_src.doubleSided) + if (src.doubleSided) { UniUnlit.Utils.SetCullMode(material, UniUnlit.UniUnlitCullMode.Off); } @@ -73,7 +63,7 @@ namespace UniGLTF } // VColor - if (m_hasVertexColor) + if (hasVertexColor) { UniUnlit.Utils.SetVColBlendMode(material, UniUnlit.UniUnlitVertexColorBlendOp.Multiply); } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/UnlitMaterialItem.cs.meta similarity index 100% rename from Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/UnlitMaterialItem.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/UnlitMaterialItem.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs index 305a47bdc..0f2701cc8 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)).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)).ToArray() }; yield return null; diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureConverter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureConverter.cs index d6323588a..3b400d799 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureConverter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureConverter.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using UnityEngine; +using System.IO; #if UNITY_EDITOR using UnityEditor; #endif @@ -20,7 +21,7 @@ namespace UniGLTF public static Texture2D Convert(Texture2D texture, glTFTextureTypes textureType, ColorConversion colorConversion, Material convertMaterial) { - var copyTexture = TextureItem.CopyTexture(texture, TextureIO.GetColorSpace(textureType), convertMaterial); + var copyTexture = CopyTexture(texture, TextureIO.GetColorSpace(textureType), convertMaterial); if (colorConversion != null) { copyTexture.SetPixels32(copyTexture.GetPixels32().Select(x => colorConversion(x)).ToArray()); @@ -45,6 +46,150 @@ namespace UniGLTF texture.name = texture.name.Replace(extension, ""); } } + + struct ColorSpaceScope : IDisposable + { + bool m_sRGBWrite; + + public ColorSpaceScope(RenderTextureReadWrite colorSpace) + { + m_sRGBWrite = GL.sRGBWrite; + switch (colorSpace) + { + case RenderTextureReadWrite.Linear: + GL.sRGBWrite = false; + break; + + case RenderTextureReadWrite.sRGB: + default: + GL.sRGBWrite = true; + break; + } + } + public ColorSpaceScope(bool sRGBWrite) + { + m_sRGBWrite = GL.sRGBWrite; + GL.sRGBWrite = sRGBWrite; + } + + public void Dispose() + { + GL.sRGBWrite = m_sRGBWrite; + } + } + +#if UNITY_EDITOR && VRM_DEVELOP + [MenuItem("Assets/CopySRGBWrite", true)] + static bool CopySRGBWriteIsEnable() + { + return Selection.activeObject is Texture; + } + + [MenuItem("Assets/CopySRGBWrite")] + static void CopySRGBWrite() + { + CopySRGBWrite(true); + } + + [MenuItem("Assets/CopyNotSRGBWrite", true)] + static bool CopyNotSRGBWriteIsEnable() + { + return Selection.activeObject is Texture; + } + + [MenuItem("Assets/CopyNotSRGBWrite")] + static void CopyNotSRGBWrite() + { + CopySRGBWrite(false); + } + + static string AddPath(string path, string add) + { + return string.Format("{0}/{1}{2}{3}", + Path.GetDirectoryName(path), + Path.GetFileNameWithoutExtension(path), + add, + Path.GetExtension(path)); + } + + static void CopySRGBWrite(bool isSRGB) + { + var src = Selection.activeObject as Texture; + var texturePath = UnityPath.FromAsset(src); + + var path = EditorUtility.SaveFilePanel("save prefab", "Assets", + Path.GetFileNameWithoutExtension(AddPath(texturePath.FullPath, ".sRGB")), "prefab"); + var assetPath = UnityPath.FromFullpath(path); + if (!assetPath.IsUnderAssetsFolder) + { + return; + } + Debug.LogFormat("[CopySRGBWrite] {0} => {1}", texturePath, assetPath); + + var renderTexture = new RenderTexture(src.width, src.height, 0, + RenderTextureFormat.ARGB32, + RenderTextureReadWrite.sRGB); + using (var scope = new ColorSpaceScope(isSRGB)) + { + Graphics.Blit(src, renderTexture); + } + + var dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, + RenderTextureReadWrite.sRGB == RenderTextureReadWrite.Linear); + dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); + dst.Apply(); + + RenderTexture.active = null; + + assetPath.CreateAsset(dst); + + GameObject.DestroyImmediate(renderTexture); + } +#endif + + public static Texture2D CopyTexture(Texture src, RenderTextureReadWrite colorSpace, Material material) + { + Texture2D dst = null; + + var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, colorSpace); + + using (var scope = new ColorSpaceScope(colorSpace)) + { + if (material != null) + { + Graphics.Blit(src, renderTexture, material); + } + else + { + Graphics.Blit(src, renderTexture); + } + } + + dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, colorSpace == RenderTextureReadWrite.Linear); + dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); + dst.name = src.name; + dst.anisoLevel = src.anisoLevel; + dst.filterMode = src.filterMode; + dst.mipMapBias = src.mipMapBias; + dst.wrapMode = src.wrapMode; +#if UNITY_2017_1_OR_NEWER + dst.wrapModeU = src.wrapModeU; + dst.wrapModeV = src.wrapModeV; + dst.wrapModeW = src.wrapModeW; +#endif + dst.Apply(); + + RenderTexture.active = null; + if (Application.isEditor) + { + GameObject.DestroyImmediate(renderTexture); + } + else + { + GameObject.Destroy(renderTexture); + } + return dst; + } } public class MetallicRoughnessConverter : ITextureConverter diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureExportManager.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureExportManager.cs index 6a1baad95..54806083e 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureExportManager.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureExportManager.cs @@ -66,7 +66,7 @@ namespace UniGLTF #endif // ToDo: may already exists - m_exportTextures[index] = TextureItem.CopyTexture(texture, readWrite, null); + m_exportTextures[index] = TextureConverter.CopyTexture(texture, readWrite, null); return index; } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO.cs index ff01045bf..61b160eed 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureIO.cs @@ -52,7 +52,7 @@ namespace UniGLTF { foreach (var material in glTf.materials) { - var textureInfo = material.GetTextures().FirstOrDefault(x => (x!=null) && x.index == textureIndex); + var textureInfo = material.GetTextures().FirstOrDefault(x => (x != null) && x.index == textureIndex); if (textureInfo != null) { return textureInfo.TextureType; @@ -109,10 +109,10 @@ namespace UniGLTF var getSizeMethod = typeof(TextureImporter).GetMethod("GetWidthAndHeight", BindingFlags.NonPublic | BindingFlags.Instance); if (textureImporter != null && getSizeMethod != null) { - var args = new object[2] {0, 0}; + var args = new object[2] { 0, 0 }; getSizeMethod.Invoke(textureImporter, args); - var originalWidth = (int) args[0]; - var originalHeight = (int) args[1]; + var originalWidth = (int)args[0]; + var originalHeight = (int)args[1]; var originalSize = Mathf.Max(originalWidth, originalHeight); var requiredMaxSize = textureImporter.maxTextureSize; @@ -122,12 +122,12 @@ namespace UniGLTF { return ( - TextureItem.CopyTexture(texture, GetColorSpace(textureType), null).EncodeToPNG(), + TextureConverter.CopyTexture(texture, GetColorSpace(textureType), null).EncodeToPNG(), "image/png" ); } } - + if (path.Extension == ".png") { return @@ -149,7 +149,7 @@ namespace UniGLTF return ( - TextureItem.CopyTexture(texture, TextureIO.GetColorSpace(textureType), null).EncodeToPNG(), + TextureConverter.CopyTexture(texture, TextureIO.GetColorSpace(textureType), null).EncodeToPNG(), "image/png" ); } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs deleted file mode 100644 index cc03b6cb5..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs +++ /dev/null @@ -1,315 +0,0 @@ -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 - - -namespace UniGLTF -{ - public 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 - { - private 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."); - } - } - -#if UNITY_EDITOR - /// - /// Texture from asset - /// - /// - /// - /// - public TextureItem(int index, UnityPath assetPath, string textureName) - { - m_textureIndex = index; - IsAsset = true; - m_textureLoader = new AssetTextureLoader(assetPath, textureName); - } -#endif - - #region Process - ITextureLoader m_textureLoader; - - public void Process(glTF gltf, IStorage storage) - { - ProcessOnAnyThread(gltf, storage); - ProcessOnMainThreadCoroutine(gltf).CoroutineToEnd(); - } - - public IEnumerator ProcessCoroutine(glTF gltf, IStorage storage) - { - ProcessOnAnyThread(gltf, storage); - yield return ProcessOnMainThreadCoroutine(gltf); - } - - public void ProcessOnAnyThread(glTF gltf, IStorage storage) - { - m_textureLoader.ProcessOnAnyThread(gltf, storage); - } - - public IEnumerator ProcessOnMainThreadCoroutine(glTF gltf) - { - 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(isLinear, gltf.GetSamplerFromTextureIndex(m_textureIndex)); - } - } - #endregion - - struct ColorSpaceScope : IDisposable - { - bool m_sRGBWrite; - - public ColorSpaceScope(RenderTextureReadWrite colorSpace) - { - m_sRGBWrite = GL.sRGBWrite; - switch (colorSpace) - { - case RenderTextureReadWrite.Linear: - GL.sRGBWrite = false; - break; - - case RenderTextureReadWrite.sRGB: - default: - GL.sRGBWrite = true; - break; - } - } - public ColorSpaceScope(bool sRGBWrite) - { - m_sRGBWrite = GL.sRGBWrite; - GL.sRGBWrite = sRGBWrite; - } - - public void Dispose() - { - GL.sRGBWrite = m_sRGBWrite; - } - } - -#if UNITY_EDITOR && VRM_DEVELOP - [MenuItem("Assets/CopySRGBWrite", true)] - static bool CopySRGBWriteIsEnable() - { - return Selection.activeObject is Texture; - } - - [MenuItem("Assets/CopySRGBWrite")] - static void CopySRGBWrite() - { - CopySRGBWrite(true); - } - - [MenuItem("Assets/CopyNotSRGBWrite", true)] - static bool CopyNotSRGBWriteIsEnable() - { - return Selection.activeObject is Texture; - } - - [MenuItem("Assets/CopyNotSRGBWrite")] - static void CopyNotSRGBWrite() - { - CopySRGBWrite(false); - } - - static string AddPath(string path, string add) - { - return string.Format("{0}/{1}{2}{3}", - Path.GetDirectoryName(path), - Path.GetFileNameWithoutExtension(path), - add, - Path.GetExtension(path)); - } - - static void CopySRGBWrite(bool isSRGB) - { - var src = Selection.activeObject as Texture; - var texturePath = UnityPath.FromAsset(src); - - var path = EditorUtility.SaveFilePanel("save prefab", "Assets", - Path.GetFileNameWithoutExtension(AddPath(texturePath.FullPath, ".sRGB")), "prefab"); - var assetPath = UnityPath.FromFullpath(path); - if (!assetPath.IsUnderAssetsFolder) - { - return; - } - Debug.LogFormat("[CopySRGBWrite] {0} => {1}", texturePath, assetPath); - - var renderTexture = new RenderTexture(src.width, src.height, 0, - RenderTextureFormat.ARGB32, - RenderTextureReadWrite.sRGB); - using (var scope = new ColorSpaceScope(isSRGB)) - { - Graphics.Blit(src, renderTexture); - } - - var dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, - RenderTextureReadWrite.sRGB == RenderTextureReadWrite.Linear); - dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); - dst.Apply(); - - RenderTexture.active = null; - - assetPath.CreateAsset(dst); - - GameObject.DestroyImmediate(renderTexture); - } -#endif - - public static Texture2D CopyTexture(Texture src, RenderTextureReadWrite colorSpace, Material material) - { - Texture2D dst = null; - - var renderTexture = new RenderTexture(src.width, src.height, 0, RenderTextureFormat.ARGB32, colorSpace); - - using (var scope = new ColorSpaceScope(colorSpace)) - { - if (material != null) - { - Graphics.Blit(src, renderTexture, material); - } - else - { - Graphics.Blit(src, renderTexture); - } - } - - dst = new Texture2D(src.width, src.height, TextureFormat.ARGB32, false, colorSpace == RenderTextureReadWrite.Linear); - dst.ReadPixels(new Rect(0, 0, src.width, src.height), 0, 0); - dst.name = src.name; - dst.anisoLevel = src.anisoLevel; - dst.filterMode = src.filterMode; - dst.mipMapBias = src.mipMapBias; - dst.wrapMode = src.wrapMode; -#if UNITY_2017_1_OR_NEWER - dst.wrapModeU = src.wrapModeU; - dst.wrapModeV = src.wrapModeV; - dst.wrapModeW = src.wrapModeW; -#endif - dst.Apply(); - - RenderTexture.active = null; - if (Application.isEditor) - { - GameObject.DestroyImmediate(renderTexture); - } - else - { - GameObject.Destroy(renderTexture); - } - return dst; - } - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs deleted file mode 100644 index ee4ecf663..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs +++ /dev/null @@ -1,348 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using UnityEngine; -using UnityEngine.Networking; -#if UNITY_EDITOR -using UnityEditor; -#endif - - -namespace UniGLTF -{ - public interface ITextureLoader : IDisposable - { - Texture2D Texture { get; } - - /// - /// Call from any thread - /// - /// - /// - void ProcessOnAnyThread(glTF gltf, IStorage storage); - - /// - /// Call from unity main thread - /// - /// - /// - /// - IEnumerator ProcessOnMainThread(bool isLinear, glTFTextureSampler sampler); - } - -#if UNITY_EDITOR - public class AssetTextureLoader : ITextureLoader - { - public Texture2D Texture - { - private set; - get; - } - - UnityPath m_assetPath; - - public AssetTextureLoader(UnityPath assetPath, string _) - { - m_assetPath = assetPath; - } - - public void Dispose() - { - } - - public void ProcessOnAnyThread(glTF gltf, IStorage storage) - { - } - - public IEnumerator ProcessOnMainThread(bool isLinear, glTFTextureSampler sampler) - { - // - // texture from assets - // - m_assetPath.ImportAsset(); - var importer = m_assetPath.GetImporter(); - if (importer == null) - { - Debug.LogWarningFormat("fail to get TextureImporter: {0}", m_assetPath); - } - importer.maxTextureSize = 8192; - importer.sRGBTexture = !isLinear; - - importer.SaveAndReimport(); - - Texture = m_assetPath.LoadAsset(); - - //Texture.name = m_textureName; - if (Texture == null) - { - Debug.LogWarningFormat("fail to Load Texture2D: {0}", m_assetPath); - } - - else - { - var maxSize = Mathf.Max(Texture.width, Texture.height); - - importer.maxTextureSize - = maxSize > 4096 ? 8192 : - maxSize > 2048 ? 4096 : - maxSize > 1024 ? 2048 : - maxSize > 512 ? 1024 : - 512; - - importer.SaveAndReimport(); - } - - if (sampler != null) - { - TextureSamplerUtil.SetSampler(Texture, sampler); - } - - yield break; - } - } -#endif - - public class TextureLoader : ITextureLoader - { - int m_textureIndex; - public TextureLoader(int textureIndex) - { - m_textureIndex = textureIndex; - } - - public Texture2D Texture - { - private set; - get; - } - - public void Dispose() - { - } - - static Byte[] ToArray(ArraySegment bytes) - { - if (bytes.Array == null) - { - return new byte[] { }; - } - else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length) - { - return bytes.Array; - } - else - { - Byte[] result = new byte[bytes.Count]; - Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); - return result; - } - } - - Byte[] m_imageBytes; - string m_textureName; - public void ProcessOnAnyThread(glTF gltf, IStorage storage) - { - var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); - var segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); - m_imageBytes = ToArray(segments); - } - - public IEnumerator ProcessOnMainThread(bool isLinear, glTFTextureSampler sampler) - { - // - // texture from image(png etc) bytes - // - Texture = new Texture2D(2, 2, TextureFormat.ARGB32, false, isLinear); - Texture.name = m_textureName; - if (m_imageBytes != null) - { - Texture.LoadImage(m_imageBytes); - } - if (sampler != null) - { - TextureSamplerUtil.SetSampler(Texture, sampler); - } - yield break; - } - } - - public class UnityWebRequestTextureLoader : ITextureLoader - { - public Texture2D Texture - { - private set; - get; - } - - int m_textureIndex; - - public UnityWebRequestTextureLoader(int textureIndex) - { - m_textureIndex = textureIndex; - } - - UnityWebRequest m_uwr; - public void Dispose() - { - if (m_uwr != null) - { - m_uwr.Dispose(); - m_uwr = null; - } - } - - ArraySegment m_segments; - string m_textureName; - public void ProcessOnAnyThread(glTF gltf, IStorage storage) - { - var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); - m_segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); - } - -#if false - HttpHost m_http; - class HttpHost : IDisposable - { - TcpListener m_listener; - Socket m_connection; - - public HttpHost(int port) - { - m_listener = new TcpListener(IPAddress.Loopback, port); - m_listener.Start(); - m_listener.BeginAcceptSocket(OnAccepted, m_listener); - } - - void OnAccepted(IAsyncResult ar) - { - var l = ar.AsyncState as TcpListener; - if (l == null) return; - m_connection = l.EndAcceptSocket(ar); - // 次の接続受付はしない - - BeginRead(m_connection, new byte[8192]); - } - - void BeginRead(Socket c, byte[] buffer) - { - AsyncCallback callback = ar => - { - var s = ar.AsyncState as Socket; - if (s == null) return; - var size = s.EndReceive(ar); - if (size > 0) - { - OnRead(buffer, size); - } - BeginRead(s, buffer); - }; - m_connection.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, callback, m_connection); - } - - List m_buffer = new List(); - void OnRead(byte[] buffer, int len) - { - m_buffer.AddRange(buffer.Take(len)); - } - - public string Url - { - get - { - - } - } - - public void Dispose() - { - if (m_connection != null) - { - m_connection.Dispose(); - m_connection = null; - } - if(m_listener != null) - { - m_listener.Stop(); - m_listener = null; - } - } - } -#endif - - class Deleter : IDisposable - { - string m_path; - public Deleter(string path) - { - m_path = path; - } - public void Dispose() - { - if (File.Exists(m_path)) - { - File.Delete(m_path); - } - } - } - - public IEnumerator ProcessOnMainThread(bool isLinear, glTFTextureSampler sampler) - { - // tmp file - var tmp = Path.GetTempFileName(); - using (var f = new FileStream(tmp, FileMode.Create)) - { - f.Write(m_segments.Array, m_segments.Offset, m_segments.Count); - } - - using (var d = new Deleter(tmp)) - { - var url = "file:///" + tmp.Replace("\\", "/"); - Debug.LogFormat("UnityWebRequest: {0}", url); -#if UNITY_2017_1_OR_NEWER - using (var m_uwr = UnityWebRequestTexture.GetTexture(url, true)) - { - yield return m_uwr.SendWebRequest(); - - if (m_uwr.isNetworkError || m_uwr.isHttpError) - { - Debug.LogWarning(m_uwr.error); - } - else - { - // Get downloaded asset bundle - Texture = ((DownloadHandlerTexture)m_uwr.downloadHandler).texture; - Texture.name = m_textureName; - } - } -#elif UNITY_5 - using (var m_uwr = new WWW(url)) - { - yield return m_uwr; - - // wait for request - while (!m_uwr.isDone) - { - yield return null; - } - - if (!string.IsNullOrEmpty(m_uwr.error)) - { - Debug.Log(m_uwr.error); - yield break; - } - - // Get downloaded asset bundle - Texture = m_uwr.textureNonReadable; - Texture.name = m_textureName; - } -#else -#error Unsupported Unity version -#endif - } - if (sampler != null) - { - TextureSamplerUtil.SetSampler(Texture, sampler); - } - } - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.meta new file mode 100644 index 000000000..1ef61d2aa --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a4bd2e8f388fb204186d743f337ddb83 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs new file mode 100644 index 000000000..352f0396e --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs @@ -0,0 +1,57 @@ +using System.Collections; +using System.Threading.Tasks; +using UnityEngine; + +namespace UniGLTF +{ +#if UNITY_EDITOR + public static class AssetTextureLoader + { + public static Task LoadTaskAsync(UnityPath m_assetPath, + bool isLinear, glTFTextureSampler sampler) + { + // + // texture from assets + // + m_assetPath.ImportAsset(); + var importer = m_assetPath.GetImporter(); + if (importer == null) + { + Debug.LogWarningFormat("fail to get TextureImporter: {0}", m_assetPath); + } + importer.maxTextureSize = 8192; + importer.sRGBTexture = !isLinear; + + importer.SaveAndReimport(); + + var Texture = m_assetPath.LoadAsset(); + + if (Texture == null) + { + Debug.LogWarningFormat("fail to Load Texture2D: {0}", m_assetPath); + } + + else + { + var maxSize = Mathf.Max(Texture.width, Texture.height); + + importer.maxTextureSize + = maxSize > 4096 ? 8192 : + maxSize > 2048 ? 4096 : + maxSize > 1024 ? 2048 : + maxSize > 512 ? 1024 : + 512; + + importer.SaveAndReimport(); + } + + if (sampler != null) + { + TextureSamplerUtil.SetSampler(Texture, sampler); + } + + return Task.FromResult(Texture); + } + } +#endif +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs.meta similarity index 71% rename from Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs.meta index 880411948..c32ca741a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureItem.cs.meta +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/AssetTextureLoader.cs.meta @@ -1,7 +1,5 @@ fileFormatVersion: 2 -guid: 09cdeb503b1e8234faf528b6ae134e7a -timeCreated: 1519799583 -licenseType: Free +guid: 748452d292d79304da4c271f584ab985 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs new file mode 100644 index 000000000..c2bce5fbc --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs @@ -0,0 +1,54 @@ +using System.Threading.Tasks; +using UnityEngine; + +namespace UniGLTF +{ + 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); + } + } + +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs.meta similarity index 69% rename from Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs.meta rename to Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs.meta index a1aa6bbfe..cdeb33876 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader.cs.meta +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GetTextureParam.cs.meta @@ -1,8 +1,7 @@ fileFormatVersion: 2 -guid: 4ffd8b31d371e024593b9aff2cf2495b -timeCreated: 1540300073 -licenseType: Free +guid: 405597f56d6540347bbecb1203aba033 MonoImporter: + externalObjects: {} serializedVersion: 2 defaultReferences: [] executionOrder: 0 diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs new file mode 100644 index 000000000..0ba1a2583 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs @@ -0,0 +1,59 @@ +using System; +using System.Threading.Tasks; +using UnityEngine; + +namespace UniGLTF +{ + public static class GltfTextureLoader + { + static Byte[] ToArray(ArraySegment bytes) + { + if (bytes.Array == null) + { + return new byte[] { }; + } + else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length) + { + return bytes.Array; + } + else + { + Byte[] result = new byte[bytes.Count]; + Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); + return result; + } + } + + public static async Task LoadTextureAsync(glTF gltf, IStorage storage, int index) + { + string m_textureName = default; + + var imageBytes = await Task.Run(() => + { + var imageIndex = gltf.GetImageIndexFromTextureIndex(index); + var segments = gltf.GetImageBytes(storage, imageIndex, out m_textureName); + return ToArray(segments); + }); + + // + // texture from image(png etc) bytes + // + 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); + } + if (sampler != null) + { + TextureSamplerUtil.SetSampler(texture, sampler); + } + return texture; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs.meta new file mode 100644 index 000000000..28ea0287a --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/GltfTextureLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c541795ac7ae51d468dfff535e5333cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs new file mode 100644 index 000000000..fc20ef08e --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace UniGLTF +{ + public delegate Task GetTextureAsyncFunc(GetTextureParam param); + public class TextureFactory : IDisposable + + { + glTF m_gltf; + IStorage m_storage; + + public UnityPath ImageBaseDir { get; set; } + + public TextureFactory(glTF gltf, IStorage storage) + { + m_gltf = gltf; + m_storage = storage; + } + + List m_textuers = new List(); + public void Dispose() + { + foreach (var x in ObjectsForSubAsset()) + { + UnityEngine.Object.DestroyImmediate(x, true); + } + } + + public IEnumerable ObjectsForSubAsset() + { + foreach (var kv in m_textureCache) + { + yield return kv.Value; + } + } + + Dictionary m_textureCache = new Dictionary(); + + public virtual Task LoadTextureAsync(int index) + { +#if UNIGLTF_USE_WEBREQUEST_TEXTURELOADER + return UnityWebRequestTextureLoader.LoadTextureAsync(index); +#else + return GltfTextureLoader.LoadTextureAsync(m_gltf, m_storage, index); +#endif + } + + /// + /// テクスチャーをロード、必要であれば変換して返す。 + /// 同じものはキャッシュを返す + /// + /// 変換の有無を判断する: METALLIC_GLOSS_PROP + /// METALLIC_GLOSS_PROPの追加パラメーター + /// gltf の texture index + /// + public async Task GetTextureAsync(GetTextureParam param) + { + if (m_textureCache.TryGetValue(param, out Texture2D texture)) + { + return texture; + } + + { + var defaultParam = GetTextureParam.Create(param.Index0.Value); + if (!m_textureCache.TryGetValue(defaultParam, out texture)) + { + texture = await LoadTextureAsync(param.Index0.Value); + m_textureCache.Add(defaultParam, 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(); + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs.meta new file mode 100644 index 000000000..58a2c5064 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/TextureFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4d6069f2bfbfc0c4c9276e8a5f8b0789 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs new file mode 100644 index 000000000..347fa074e --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; +using System.IO; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.Networking; + +namespace UniGLTF +{ + public class UnityWebRequestTextureLoader + { + public Texture2D Texture + { + private set; + get; + } + + int m_textureIndex; + + public UnityWebRequestTextureLoader(int textureIndex) + { + m_textureIndex = textureIndex; + } + + UnityWebRequest m_uwr; + public void Dispose() + { + if (m_uwr != null) + { + m_uwr.Dispose(); + m_uwr = null; + } + } + + string m_textureName; + public void ProcessOnAnyThread() + { + } + + class Deleter : IDisposable + { + string m_path; + public Deleter(string path) + { + m_path = path; + } + public void Dispose() + { + if (File.Exists(m_path)) + { + File.Delete(m_path); + } + } + } + + public IEnumerator ProcessOnMainThread(glTF gltf, IStorage storage, bool isLinear, glTFTextureSampler sampler) + { + var imageIndex = gltf.GetImageIndexFromTextureIndex(m_textureIndex); + var bytes = gltf.GetImageBytes(storage, imageIndex, out m_textureName); + + // tmp file + var tmp = Path.GetTempFileName(); + using (var f = new FileStream(tmp, FileMode.Create)) + { + f.Write(bytes.Array, bytes.Offset, bytes.Count); + } + + using (var d = new Deleter(tmp)) + { + var url = "file:///" + tmp.Replace("\\", "/"); + Debug.LogFormat("UnityWebRequest: {0}", url); +#if UNITY_2017_1_OR_NEWER + using (var m_uwr = UnityWebRequestTexture.GetTexture(url, true)) + { + yield return m_uwr.SendWebRequest(); + + if (m_uwr.isNetworkError || m_uwr.isHttpError) + { + Debug.LogWarning(m_uwr.error); + } + else + { + // Get downloaded asset bundle + Texture = ((DownloadHandlerTexture)m_uwr.downloadHandler).texture; + Texture.name = m_textureName; + } + } +#elif UNITY_5 + using (var m_uwr = new WWW(url)) + { + yield return m_uwr; + + // wait for request + while (!m_uwr.isDone) + { + yield return null; + } + + if (!string.IsNullOrEmpty(m_uwr.error)) + { + Debug.Log(m_uwr.error); + yield break; + } + + // Get downloaded asset bundle + Texture = m_uwr.textureNonReadable; + Texture.name = m_textureName; + } +#else +#error Unsupported Unity version +#endif + } + if (sampler != null) + { + TextureSamplerUtil.SetSampler(Texture, sampler); + } + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs.meta new file mode 100644 index 000000000..d3369dfbc --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/TextureLoader/UnityWebRequestTextureLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b91b7b42ddfd6284a9303a0901fccaa3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs deleted file mode 100644 index 22cd4788a..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialFactory.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; - -namespace UniGLTF -{ - public delegate TextureItem GetTextureItemFunc(int i); - public delegate Shader GetShaderFunc(); - public delegate MaterialItemBase MaterialImporter(int i, glTFMaterial x, bool hasVertexColor); - - - public class MaterialFactory - { - MaterialImporter m_materialImporter; - public MaterialImporter MaterialImporter - { - set - { - m_materialImporter = value; - } - get - { - if (m_materialImporter == null) - { - m_materialImporter = CreateMaterial; - } - return m_materialImporter; - } - } - - List m_textures = new List(); - public IList GetTextures() - { - return m_textures; - } - public TextureItem GetTexture(int i) - { - if (i < 0 || i >= m_textures.Count) - { - return null; - } - return m_textures[i]; - } - public void AddTexture(TextureItem item) - { - m_textures.Add(item); - } - - List m_materials = new List(); - public void AddMaterial(MaterialItemBase material) - { - var originalName = material.Name; - int j = 2; - while (m_materials.Any(x => x.Name == material.Name)) - { - material.Name = string.Format("{0}({1})", originalName, j++); - } - m_materials.Add(material); - } - public IList GetMaterials() - { - return m_materials; - } - public MaterialItemBase GetMaterial(int index) - { - if (index < 0) return null; - if (index >= m_materials.Count) return null; - return m_materials[index]; - } - - public virtual ITextureLoader CreateTextureLoader(int index) - { -#if UNIGLTF_USE_WEBREQUEST_TEXTURELOADER - return new UnityWebRequestTextureLoader(index); -#else - return new TextureLoader(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, assetPath, textureName); - } - else -#endif - { - item = new TextureItem(i, CreateTextureLoader(i)); - } - - AddTexture(item); - } - } - - public IEnumerator TexturesProcessOnAnyThread(glTF gltf, IStorage storage) - { - // using (MeasureTime("TexturesProcessOnAnyThread")) - { - foreach (var x in GetTextures()) - { - x.ProcessOnAnyThread(gltf, storage); - yield return null; - } - } - } - - public IEnumerator TexturesProcessOnMainThread(glTF gltf) - { - // using (MeasureTime("TexturesProcessOnMainThread")) - { - foreach (var x in GetTextures()) - { - yield return x.ProcessOnMainThreadCoroutine(gltf); - } - } - } - - public IEnumerator LoadMaterials(glTF gltf) - { - // using (MeasureTime("LoadMaterials")) - { - if (gltf.materials == null || !gltf.materials.Any()) - { - AddMaterial(MaterialImporter(0, null, false)); - } - else - { - for (int i = 0; i < gltf.materials.Count; ++i) - { - AddMaterial(MaterialImporter(i, gltf.materials[i], gltf.MaterialHasVertexColor(i))); - } - } - } - yield return null; - } - - public static MaterialItemBase CreateMaterial(int i, glTFMaterial x, bool hasVertexColor) - { - if (x == null) - { - UnityEngine.Debug.LogWarning("glTFMaterial is empty"); - return new PBRMaterialItem(i, x); - } - - if (glTF_KHR_materials_unlit.IsEnable(x)) - { - return new UnlitMaterialItem(i, x, hasVertexColor); - } - - return new PBRMaterialItem(i, x); - } - } -} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs b/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs deleted file mode 100644 index ad551e149..000000000 --- a/Assets/UniGLTF/Runtime/UniGLTF/MaterialFacotry/MaterialItemBase.cs +++ /dev/null @@ -1,59 +0,0 @@ -using UnityEngine; - - -namespace UniGLTF -{ - public abstract class MaterialItemBase - { - protected int m_index; - protected glTFMaterial m_src; - - public string Name { get; set; } - - public MaterialItemBase(int i, glTFMaterial src) - { - m_index = i; - m_src = src; - Name = src != null ? m_src.name : ""; - } - - public abstract Material GetOrCreate(GetTextureItemFunc getTexture); - - protected Material CreateMaterial(string shaderName) - { - var material = new Material(Shader.Find(shaderName)); -#if UNITY_EDITOR - // textureImporter.SaveAndReimport(); may destroy this material - material.hideFlags = HideFlags.DontUnloadUnusedAsset; -#endif - material.name = (m_src == null || string.IsNullOrEmpty(m_src.name)) - ? string.Format("material_{0:00}", m_index) - : m_src.name - ; - - return material; - } - - protected static void SetTextureOffsetAndScale(Material material, glTFTextureInfo textureInfo, string propertyName) - { - if (glTF_KHR_texture_transform.TryGet(textureInfo, out glTF_KHR_texture_transform textureTransform)) - { - Vector2 offset = new Vector2(0, 0); - Vector2 scale = new Vector2(1, 1); - if (textureTransform.offset != null && textureTransform.offset.Length == 2) - { - offset = new Vector2(textureTransform.offset[0], textureTransform.offset[1]); - } - if (textureTransform.scale != null && textureTransform.scale.Length == 2) - { - scale = new Vector2(textureTransform.scale[0], textureTransform.scale[1]); - } - - offset.y = (offset.y + scale.y - 1.0f) * -1.0f; - - material.SetTextureOffset(propertyName, offset); - material.SetTextureScale(propertyName, scale); - } - } - } -} diff --git a/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs b/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs index 42c7d34bf..d37a0e54c 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/MaterialTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using UnityEngine; using UniJSON; using System.Linq; +using System.Threading.Tasks; namespace UniGLTF { @@ -32,7 +33,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.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual(dstMaterial.mainTextureOffset.x, offset.x, 0.3f); Assert.AreEqual(dstMaterial.mainTextureOffset.y, offset.y, 0.2f); @@ -80,7 +81,7 @@ namespace UniGLTF Assert.IsTrue(glTF_KHR_materials_unlit.IsEnable(gltfMaterial)); - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } } @@ -99,7 +100,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -114,7 +115,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -130,7 +131,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -145,7 +146,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -160,7 +161,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -176,7 +177,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -191,7 +192,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -207,7 +208,7 @@ namespace UniGLTF }, extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } @@ -217,7 +218,7 @@ namespace UniGLTF { extensions = glTF_KHR_materials_unlit.Serialize().Deserialize(), }; - var material = MaterialFactory.CreateMaterial(0, gltfMaterial, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, gltfMaterial); Assert.AreEqual("UniGLTF/UniUnlit", material.shader.name); } } @@ -225,7 +226,7 @@ namespace UniGLTF [Test] public void MaterialImportTest() { - var material = MaterialFactory.CreateMaterial(0, new glTFMaterial { }, false).GetOrCreate(null); + var material = MaterialFactory.CreateMaterialForTest(0, new glTFMaterial { }); 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 50d6ff0d2..c15c9995c 100644 --- a/Assets/VRM/Runtime/IO/VRMImporterContext.cs +++ b/Assets/VRM/Runtime/IO/VRMImporterContext.cs @@ -6,6 +6,7 @@ using UnityEngine; using System.IO; using System.Collections; using UniJSON; +using System.Threading.Tasks; namespace VRM { @@ -42,7 +43,7 @@ namespace VRM { VRM = vrm; // override material importer - MaterialFactory.MaterialImporter = new VRMMaterialImporter(VRM.materialProperties).CreateMaterial; + MaterialFactory.CreateMaterialAsync = new VRMMaterialImporter(VRM.materialProperties).CreateMaterial; } else { @@ -57,7 +58,11 @@ namespace VRM using (MeasureTime("VRM LoadMeta")) { - LoadMeta(); + var task = LoadMetaAsync(); + foreach (var x in task.AsIEnumerator()) + { + yield return x; + } } yield return null; @@ -86,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; @@ -193,7 +198,8 @@ namespace VRM } } - var material = MaterialFactory.GetMaterials().FirstOrDefault(y => y.Name == x.materialName).GetOrCreate(MaterialFactory.GetTexture); + var material = MaterialFactory.Materials + .FirstOrDefault(y => y.name == x.materialName); var propertyName = x.propertyName; if (x.propertyName.FastEndsWith("_ST_S") || x.propertyName.FastEndsWith("_ST_T")) @@ -292,7 +298,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"; @@ -304,24 +310,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.Process(GLTF, Storage); - meta.Thumbnail = t.Texture; - } - } - + meta.Thumbnail = await TextureFactory.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..145ee7338 100644 --- a/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs +++ b/Assets/VRM/Runtime/IO/VRMMaterialImporter.cs @@ -3,10 +3,11 @@ using UniGLTF; using UnityEngine; using System.Linq; using System; +using System.Threading.Tasks; namespace VRM { - public class MToonMaterialItem : MaterialItemBase + public static class MToonMaterialItem { static string[] VRM_SHADER_NAMES = { @@ -20,18 +21,9 @@ namespace VRM "VRM/UnlitTransparentZWrite", }; - glTF_VRM_Material m_vrmMaterial; - bool m_hasVertexColor; - - public MToonMaterialItem(int i, glTFMaterial src, bool hasVertexColor, glTF_VRM_Material vrmMaterial) : base(i, src) + public static async Task CreateAsync(glTF gltf, int m_index, glTF_VRM_Material vrmMaterial, GetTextureAsyncFunc getTexture) { - m_hasVertexColor = hasVertexColor; - m_vrmMaterial = vrmMaterial; - } - - public override Material GetOrCreate(GetTextureItemFunc getTexture) - { - var item = m_vrmMaterial; + var item = vrmMaterial; var shaderName = item.shader; var shader = Shader.Find(shaderName); if (shader == null) @@ -47,7 +39,7 @@ namespace VRM { Debug.LogWarningFormat("unknown shader {0}.", shaderName); } - return MaterialFactory.CreateMaterial(m_index, m_src, m_hasVertexColor).GetOrCreate(getTexture); + return await MaterialFactory.DefaultCreateMaterialAsync(gltf, m_index, getTexture); } // @@ -78,18 +70,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) @@ -127,15 +111,15 @@ namespace VRM m_materials = materials; } - public MaterialItemBase CreateMaterial(int i, glTFMaterial src, bool hasVertexColor) + public Task CreateMaterial(glTF gltf, int i, GetTextureAsyncFunc getTexture) { if (i == 0 && m_materials.Count == 0) { // dummy - return new PBRMaterialItem(i, src); + return MaterialFactory.DefaultCreateMaterialAsync(gltf, i, getTexture); } - return new MToonMaterialItem(i, src, hasVertexColor, m_materials[i]); + return MToonMaterialItem.CreateAsync(gltf, i, m_materials[i], getTexture); } } }