Skip to content

Commit

Permalink
Merge pull request #744 from ousttrue/feature/refactor_textureitem
Browse files Browse the repository at this point in the history
Feature/refactor textureitem
  • Loading branch information
ousttrue authored Feb 15, 2021
2 parents 95a5dd5 + da7d1db commit df8e554
Show file tree
Hide file tree
Showing 36 changed files with 988 additions and 1,105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
using System.Collections.Generic;


namespace
DepthFirstScheduler
namespace DepthFirstScheduler
{
public static class IEnumeratorExtensions
{
Expand Down
58 changes: 58 additions & 0 deletions Assets/UniGLTF/Runtime/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using System.Collections;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

namespace UniGLTF
{
/// <summary>
/// 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
///
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
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;
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 30 additions & 21 deletions Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,11 @@ public IAnimationImporter AnimationImporter

#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()
{
Expand Down Expand Up @@ -267,12 +265,14 @@ public virtual void ParseJson(string json, IStorage storage)
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();

Expand Down Expand Up @@ -501,11 +501,15 @@ protected virtual Schedulable<Unit> LoadAsync()
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
Expand Down Expand Up @@ -696,16 +700,14 @@ public void EnableUpdateWhenOffscreen()

protected virtual IEnumerable<UnityEngine.Object> ObjectsForSubAsset()
{
HashSet<Texture2D> textures = new HashSet<Texture2D>();
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; }
}
Expand Down Expand Up @@ -896,7 +898,8 @@ public void ExtractImages(UnityPath prefabPath)
AssetDatabase.Refresh();
}

m_materialFactory.CreateTextureItems(GLTF, prefabParentDir);
// texture will load from assets
m_textureFactory.ImageBaseDir = prefabParentDir;
}
#endregion
#endif
Expand Down Expand Up @@ -939,10 +942,16 @@ public void DestroyRootAndResources()
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
Expand Down
175 changes: 175 additions & 0 deletions Assets/UniGLTF/Runtime/UniGLTF/IO/MaterialLoader/MaterialFactory.cs
Original file line number Diff line number Diff line change
@@ -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<Material> 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<Material> m_materials = new List<Material>();
public IReadOnlyList<Material> Materials => m_materials;
public void Dispose()
{
foreach (var x in ObjectsForSubAsset())
{
UnityEngine.Object.DestroyImmediate(x, true);
}
}

public IEnumerable<UnityEngine.Object> 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<Material> 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);
}

/// <summary>
/// for unittest
/// </summary>
/// <param name="i"></param>
/// <param name="material"></param>
/// <param name="getTexture"></param>
/// <returns></returns>
public static Material CreateMaterialForTest(int i, glTFMaterial material)
{
var gltf = new glTF
{
materials = new System.Collections.Generic.List<glTFMaterial> { material },
};
var task = DefaultCreateMaterialAsync(gltf, i, null);
return task.Result;
}
}
}
Loading

0 comments on commit df8e554

Please sign in to comment.