TextureFactory manipulate ExternalObjectMap

This commit is contained in:
ousttrue 2021-02-24 16:02:45 +09:00
parent b4f71fed84
commit bdadbc9f80
5 changed files with 83 additions and 45 deletions

View File

@ -25,28 +25,25 @@ namespace UniGLTF
parser.ParsePath(ctx.assetPath);
// Build Unity Model
var context = new ImporterContext(parser);
var context = new ImporterContext(parser, GetExternalObjectMap()
.Select(kv => new KeyValuePair<string, UnityEngine.Object>(kv.Key.name, kv.Value)));
context.Load();
context.ShowMeshes();
// Texture
var externalTextures = this.GetExternalUnityObjects<UnityEngine.Texture2D>();
foreach (var texture in context.Textures)
foreach (var info in context.TextureFactory.Textures)
{
if (texture == null)
{
throw new Exception();
}
if (!externalTextures.ContainsValue(texture))
if (!info.UseExternal)
{
var texture = info.Texture;
ctx.AddObjectToAsset(texture.name, texture);
}
}
// Material
var externalMaterials = this.GetExternalUnityObjects<UnityEngine.Material>();
foreach (var material in context.Materials)
foreach (var material in context.MaterialFactory.Materials)
{
if (material == null)
{

View File

@ -19,19 +19,15 @@ namespace UniGLTF
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel("Materials And Textures");
GUI.enabled = !(importer.GetExternalUnityObjects<UnityEngine.Material>().Any()
&& importer.GetExternalUnityObjects<UnityEngine.Texture2D>().Any());
if (GUILayout.Button("Extract"))
{
importer.ExtractMaterialsAndTextures();
}
GUI.enabled = !GUI.enabled;
if (GUILayout.Button("Clear"))
{
importer.ClearExternalObjects<UnityEngine.Material>();
importer.ClearExternalObjects<UnityEngine.Texture2D>();
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
// ObjectMap

View File

@ -37,16 +37,14 @@ namespace UniGLTF
MaterialFactory m_materialFactory;
public MaterialFactory MaterialFactory => m_materialFactory;
public IEnumerable<Material> Materials => m_materialFactory.Materials;
TextureFactory m_textureFactory;
public TextureFactory TextureFactory => m_textureFactory;
public IEnumerable<Texture2D> Textures => m_textureFactory.Textures;
public ImporterContext(GltfParser parser)
public ImporterContext(GltfParser parser, IEnumerable<KeyValuePair<string, UnityEngine.Object>> externalObjectMap = null)
{
m_parser = parser;
m_textureFactory = new TextureFactory(GLTF, Storage);
m_textureFactory = new TextureFactory(GLTF, Storage, externalObjectMap);
m_materialFactory = new MaterialFactory(GLTF, Storage);
}

View File

@ -11,7 +11,7 @@ namespace UniGLTF
{
if (getTexture == null)
{
getTexture = _ => Awaitable.FromResult<Texture2D>(null);
getTexture = _ => Awaitable.FromResult<Texture2D>(default);
}
var material = MaterialFactory.CreateMaterial(i, src, ShaderName);

View File

@ -1,23 +1,43 @@
using System;
using System.Collections.Generic;
using UniGLTF.AltTask;
using UnityEditor;
using UnityEngine;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UniGLTF
{
public struct TextureLoadInfo
{
public readonly Texture2D Texture;
public readonly bool UseExternal;
public TextureLoadInfo(Texture2D texture, bool useExternal)
{
Texture = texture;
UseExternal = useExternal;
}
}
public delegate Awaitable<Texture2D> GetTextureAsyncFunc(GetTextureParam param);
public class TextureFactory : IDisposable
{
glTF m_gltf;
IStorage m_storage;
Dictionary<string, Texture2D> m_externalMap;
public UnityPath ImageBaseDir { get; set; }
public TextureFactory(glTF gltf, IStorage storage)
public TextureFactory(glTF gltf, IStorage storage, IEnumerable<KeyValuePair<string, UnityEngine.Object>> externalMap)
{
m_gltf = gltf;
m_storage = storage;
m_externalMap = externalMap
.Select(kv => (kv.Key, kv.Value as Texture2D))
.Where(kv => kv.Item2 != null)
.ToDictionary(kv => kv.Item1, kv => kv.Item2);
}
public void Dispose()
@ -32,22 +52,42 @@ namespace UniGLTF
{
foreach (var kv in m_textureCache)
{
yield return kv.Value;
yield return kv.Value.Texture;
}
}
Dictionary<GetTextureParam, Texture2D> m_textureCache = new Dictionary<GetTextureParam, Texture2D>();
public IEnumerable<Texture2D> Textures => m_textureCache.Values;
Dictionary<GetTextureParam, TextureLoadInfo> m_textureCache = new Dictionary<GetTextureParam, TextureLoadInfo>();
public virtual Awaitable<Texture2D> LoadTextureAsync(int index)
public IEnumerable<TextureLoadInfo> Textures => m_textureCache.Values;
public virtual async Awaitable<TextureLoadInfo> LoadTextureAsync(int index)
{
#if UNIGLTF_USE_WEBREQUEST_TEXTURELOADER
return UnityWebRequestTextureLoader.LoadTextureAsync(index);
#else
return GltfTextureLoader.LoadTextureAsync(m_gltf, m_storage, index);
var texture = await GltfTextureLoader.LoadTextureAsync(m_gltf, m_storage, index);
return new TextureLoadInfo(texture, false);
#endif
}
public bool TryGetExternal(GetTextureParam param, out Texture2D external)
{
if (param.Index0.HasValue && m_externalMap != null)
{
var gltfTexture = m_gltf.textures[param.Index0.Value];
m_gltf.GetImageBytes(m_storage, gltfTexture.source, out string textureName);
if (m_externalMap.TryGetValue(textureName, out external))
{
Debug.Log($"use external: {textureName}");
m_textureCache.Add(param, new TextureLoadInfo(external, true));
return external;
}
}
external = default;
return false;
}
/// <summary>
/// テクスチャーをロード、必要であれば変換して返す。
/// 同じものはキャッシュを返す
@ -58,17 +98,21 @@ namespace UniGLTF
/// <returns></returns>
public async Awaitable<Texture2D> GetTextureAsync(GetTextureParam param)
{
if (m_textureCache.TryGetValue(param, out Texture2D texture))
if (m_textureCache.TryGetValue(param, out TextureLoadInfo info))
{
return texture;
return info.Texture;
}
if (TryGetExternal(param, out Texture2D external))
{
return external;
}
{
var defaultParam = GetTextureParam.Create(param.Index0.Value);
if (!m_textureCache.TryGetValue(defaultParam, out texture))
if (!m_textureCache.TryGetValue(defaultParam, out info))
{
texture = await LoadTextureAsync(param.Index0.Value);
m_textureCache.Add(defaultParam, texture);
info = await LoadTextureAsync(param.Index0.Value);
m_textureCache.Add(defaultParam, info);
}
}
@ -78,49 +122,52 @@ namespace UniGLTF
{
if (Application.isPlaying)
{
var converted = new NormalConverter().GetImportTexture(texture);
m_textureCache.Add(param, converted);
var converted = new NormalConverter().GetImportTexture(info.Texture);
converted.name = $"{converted.name}.{GetTextureParam.NORMAL_PROP}";
return converted;
info = new TextureLoadInfo(converted, false);
m_textureCache.Add(param, info);
return info.Texture;
}
else
{
#if UNITY_EDITOR
var textureAssetPath = AssetDatabase.GetAssetPath(texture);
var textureAssetPath = AssetDatabase.GetAssetPath(info.Texture);
if (!string.IsNullOrEmpty(textureAssetPath))
{
TextureIO.MarkTextureAssetAsNormalMap(textureAssetPath);
texture.name = $"{texture.name}.{GetTextureParam.NORMAL_PROP}";
info.Texture.name = $"{info.Texture.name}.{GetTextureParam.NORMAL_PROP}";
}
else
{
Debug.LogWarningFormat("no asset for {0}", texture);
Debug.LogWarningFormat("no asset for {0}", info);
}
#endif
m_textureCache.Add(param, texture);
return texture;
m_textureCache.Add(param, info);
return info.Texture;
}
}
case GetTextureParam.METALLIC_GLOSS_PROP:
{
// Bake roughnessFactor values into a texture.
var converted = new MetallicRoughnessConverter(param.MetallicFactor).GetImportTexture(texture);
var converted = new MetallicRoughnessConverter(param.MetallicFactor).GetImportTexture(info.Texture);
converted.name = $"{converted.name}.{GetTextureParam.METALLIC_GLOSS_PROP}";
m_textureCache.Add(param, converted);
return converted;
info = new TextureLoadInfo(converted, false);
m_textureCache.Add(param, info);
return info.Texture;
}
case GetTextureParam.OCCLUSION_PROP:
{
var converted = new OcclusionConverter().GetImportTexture(texture);
var converted = new OcclusionConverter().GetImportTexture(info.Texture);
converted.name = $"{converted.name}.{GetTextureParam.OCCLUSION_PROP}";
m_textureCache.Add(param, converted);
return converted;
info = new TextureLoadInfo(converted, false);
m_textureCache.Add(param, info);
return info.Texture;
}
default:
return texture;
return info.Texture;
}
throw new NotImplementedException();