From 7629540348498f2eba039106f3a23db220359f13 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Tue, 21 May 2024 11:57:16 +0900 Subject: [PATCH 1/3] Add Vrm10.LoadGltfDataAsync API for advanced usage. --- Assets/VRM10/Runtime/IO/Vrm10.cs | 169 +++++++++++++++++++------------ 1 file changed, 104 insertions(+), 65 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index 73904892f..fc636e5c5 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; using UniGLTF; @@ -47,16 +48,17 @@ namespace UniVRM10 VrmMetaInformationCallback vrmMetaInformationCallback = null, CancellationToken ct = default) { - if (awaitCaller == null) - { - awaitCaller = Application.isPlaying - ? (IAwaitCaller)new RuntimeOnlyAwaitCaller() - : (IAwaitCaller)new ImmediateCaller(); - } + awaitCaller ??= Application.isPlaying + ? new RuntimeOnlyAwaitCaller() + : new ImmediateCaller(); + using var gltfData = await awaitCaller.Run(() => + { + var bytes = File.ReadAllBytes(path); + return new GlbLowLevelParser(path, bytes).Parse(); + }); return await LoadAsync( - path, - System.IO.File.ReadAllBytes(path), + gltfData, canLoadVrm0X, controlRigGenerationOption, showMeshes, @@ -94,16 +96,57 @@ namespace UniVRM10 VrmMetaInformationCallback vrmMetaInformationCallback = null, CancellationToken ct = default) { - if (awaitCaller == null) - { - awaitCaller = Application.isPlaying - ? (IAwaitCaller)new RuntimeOnlyAwaitCaller() - : (IAwaitCaller)new ImmediateCaller(); - } + awaitCaller ??= Application.isPlaying + ? new RuntimeOnlyAwaitCaller() + : new ImmediateCaller(); + + using var gltfData = await awaitCaller.Run(() => new GlbLowLevelParser(string.Empty, bytes).Parse()); + return await LoadAsync( + gltfData, + canLoadVrm0X, + controlRigGenerationOption, + showMeshes, + awaitCaller, + textureDeserializer, + materialGenerator, + vrmMetaInformationCallback, + ct); + } + + /// + /// For advanced usage. + /// Load the VRM file from the GltfData instance. + /// + /// You should call this on Unity main thread. + /// This will throw Exceptions (include OperationCanceledException). + /// + /// loading target. + /// if true, this loader can load the vrm-0.x model as vrm-1.0 model with migration. + /// the flag of generating the control rig provides bone manipulation unified between models. + /// if true, show meshes when loaded. + /// this loader use specified await strategy. + /// this loader use specified texture deserialization strategy. + /// this loader use specified material generation strategy. + /// return callback that notify meta information before loading. + /// CancellationToken + /// vrm-1.0 instance. Maybe return null if unexpected error was raised. + public static async Task LoadGltfDataAsync( + GltfData gltfData, + bool canLoadVrm0X = true, + ControlRigGenerationOption controlRigGenerationOption = ControlRigGenerationOption.Generate, + bool showMeshes = true, + IAwaitCaller awaitCaller = null, + ITextureDeserializer textureDeserializer = null, + IMaterialDescriptorGenerator materialGenerator = null, + VrmMetaInformationCallback vrmMetaInformationCallback = null, + CancellationToken ct = default) + { + awaitCaller ??= Application.isPlaying + ? new RuntimeOnlyAwaitCaller() + : new ImmediateCaller(); return await LoadAsync( - string.Empty, - bytes, + gltfData, canLoadVrm0X, controlRigGenerationOption, showMeshes, @@ -115,8 +158,7 @@ namespace UniVRM10 } private static async Task LoadAsync( - string name, - byte[] bytes, + GltfData gltfData, bool canLoadVrm0X, ControlRigGenerationOption controlRigGenerationOption, bool showMeshes, @@ -132,57 +174,54 @@ namespace UniVRM10 throw new ArgumentNullException(); } - using (var gltfData = new GlbLowLevelParser(name, bytes).Parse()) + // 1. Try loading as vrm-1.0 + var instance = await TryLoadingAsVrm10Async( + gltfData, + controlRigGenerationOption, + showMeshes, + awaitCaller, + textureDeserializer, + materialGenerator, + vrmMetaInformationCallback, + ct); + if (instance != null) { - // 1. Try loading as vrm-1.0 - var instance = await TryLoadingAsVrm10Async( - gltfData, - controlRigGenerationOption, - showMeshes, - awaitCaller, - textureDeserializer, - materialGenerator, - vrmMetaInformationCallback, - ct); - if (instance != null) + if (ct.IsCancellationRequested) { - if (ct.IsCancellationRequested) - { - UnityObjectDestroyer.DestroyRuntimeOrEditor(instance.gameObject); - ct.ThrowIfCancellationRequested(); - } - return instance; + UnityObjectDestroyer.DestroyRuntimeOrEditor(instance.gameObject); + ct.ThrowIfCancellationRequested(); } - - // 2. Stop loading if not allowed migration. - if (!canLoadVrm0X) - { - throw new Exception($"Failed to load as VRM 1.0: {name}"); - } - - // 3. Try migration from vrm-0.x into vrm-1.0 - var migratedInstance = await TryMigratingFromVrm0XAsync( - gltfData, - controlRigGenerationOption, - showMeshes, - awaitCaller, - textureDeserializer, - materialGenerator, - vrmMetaInformationCallback, - ct); - if (migratedInstance != null) - { - if (ct.IsCancellationRequested) - { - UnityObjectDestroyer.DestroyRuntimeOrEditor(migratedInstance.gameObject); - ct.ThrowIfCancellationRequested(); - } - return migratedInstance; - } - - // 4. Failed loading. - throw new Exception($"Failed to load: {name}"); + return instance; } + + // 2. Stop loading if not allowed migration. + if (!canLoadVrm0X) + { + throw new Exception($"Failed to load as VRM 1.0"); + } + + // 3. Try migration from vrm-0.x into vrm-1.0 + var migratedInstance = await TryMigratingFromVrm0XAsync( + gltfData, + controlRigGenerationOption, + showMeshes, + awaitCaller, + textureDeserializer, + materialGenerator, + vrmMetaInformationCallback, + ct); + if (migratedInstance != null) + { + if (ct.IsCancellationRequested) + { + UnityObjectDestroyer.DestroyRuntimeOrEditor(migratedInstance.gameObject); + ct.ThrowIfCancellationRequested(); + } + return migratedInstance; + } + + // 4. Failed loading. + throw new Exception($"Failed to load"); } private static async Task TryLoadingAsVrm10Async( From 3ec05a23465f293b08fba3fe8132b593aebe386e Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Tue, 21 May 2024 12:03:17 +0900 Subject: [PATCH 2/3] maintain compatibility --- Assets/VRM10/Runtime/IO/Vrm10.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index fc636e5c5..27be68bf4 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -52,11 +52,7 @@ namespace UniVRM10 ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(); - using var gltfData = await awaitCaller.Run(() => - { - var bytes = File.ReadAllBytes(path); - return new GlbLowLevelParser(path, bytes).Parse(); - }); + using var gltfData = new GlbLowLevelParser(path, await File.ReadAllBytesAsync(path, ct)).Parse(); return await LoadAsync( gltfData, canLoadVrm0X, @@ -100,7 +96,7 @@ namespace UniVRM10 ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(); - using var gltfData = await awaitCaller.Run(() => new GlbLowLevelParser(string.Empty, bytes).Parse()); + using var gltfData = new GlbLowLevelParser(string.Empty, bytes).Parse(); return await LoadAsync( gltfData, canLoadVrm0X, From 809135145c7ab9e3fb58ea466664e5fa59619cb0 Mon Sep 17 00:00:00 2001 From: Masataka SUMI Date: Tue, 21 May 2024 12:17:30 +0900 Subject: [PATCH 3/3] Fix error at the single thread environments --- Assets/VRM10/Runtime/IO/Vrm10.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/VRM10/Runtime/IO/Vrm10.cs b/Assets/VRM10/Runtime/IO/Vrm10.cs index 27be68bf4..80e6fa31a 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10.cs @@ -52,7 +52,7 @@ namespace UniVRM10 ? new RuntimeOnlyAwaitCaller() : new ImmediateCaller(); - using var gltfData = new GlbLowLevelParser(path, await File.ReadAllBytesAsync(path, ct)).Parse(); + using var gltfData = new GlbLowLevelParser(path, File.ReadAllBytes(path)).Parse(); return await LoadAsync( gltfData, canLoadVrm0X,