From e7d461fac1919e2690c87a95e88e42d4e6776d23 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Wed, 9 Jun 2021 13:16:04 +0900 Subject: [PATCH] =?UTF-8?q?Vrm10Parser=20=E3=82=92=E5=B0=8E=E5=85=A5?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=80=81=E3=81=93=E3=81=93=E3=81=A7=20extens?= =?UTF-8?q?ion=20=E3=81=AE=E5=8F=96=E3=82=8A=E5=87=BA=E3=81=97=E3=81=A8=20?= =?UTF-8?q?migrate=20=E3=82=92=E5=91=BC=E3=81=B3=E5=87=BA=E3=81=99?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=97=E3=81=9F=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/VRM10.Samples/Runtime/ViewerUI.cs | 7 +- .../VrmScriptedImporterEditorGUI.cs | 2 +- .../VrmScriptedImporterImpl.cs | 74 +----------- Assets/VRM10/Runtime/IO/Vrm10Importer.cs | 43 +++---- Assets/VRM10/Runtime/IO/Vrm10Parser.cs | 109 ++++++++++++++++++ Assets/VRM10/Runtime/IO/Vrm10Parser.cs.meta | 11 ++ Assets/VRM10/Runtime/Scenes/Sample.cs | 7 +- Assets/VRM10/Tests.PlayMode/MaterialTests.cs | 13 ++- Assets/VRM10/Tests/ApiSampleTests.cs | 12 +- 9 files changed, 162 insertions(+), 116 deletions(-) create mode 100644 Assets/VRM10/Runtime/IO/Vrm10Parser.cs create mode 100644 Assets/VRM10/Runtime/IO/Vrm10Parser.cs.meta diff --git a/Assets/VRM10.Samples/Runtime/ViewerUI.cs b/Assets/VRM10.Samples/Runtime/ViewerUI.cs index d879d40a2..35b441433 100644 --- a/Assets/VRM10.Samples/Runtime/ViewerUI.cs +++ b/Assets/VRM10.Samples/Runtime/ViewerUI.cs @@ -308,7 +308,12 @@ namespace UniVRM10.Samples { case ".vrm": { - using (var loader = Vrm10Importer.OpenOrMigrate(path)) + if(!Vrm10Parser.TryParseOrMigrate(path, doMigrate: true, out Vrm10Parser.Result result, out string error)) + { + Debug.LogError(error); + return; + } + using (var loader = new Vrm10Importer(result.Parser, result.Vrm)) { loader.Load(); loader.ShowMeshes(); diff --git a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterEditorGUI.cs b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterEditorGUI.cs index 443cc4dba..99d71171d 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterEditorGUI.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterEditorGUI.cs @@ -27,7 +27,7 @@ namespace UniVRM10 base.OnEnable(); m_importer = target as VrmScriptedImporter; - if (!VrmScriptedImporterImpl.TryParseOrMigrate(m_importer.assetPath, m_importer.MigrateToVrm1, out m_parser, out m_message)) + if (!Vrm10Parser.TryParseOrMigrate(m_importer.assetPath, m_importer.MigrateToVrm1, out Vrm10Parser.Result result, out m_message)) { // error return; diff --git a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs index 1107ec3b9..948295c4f 100644 --- a/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs +++ b/Assets/VRM10/Editor/ScriptedImporter/VrmScriptedImporterImpl.cs @@ -16,83 +16,13 @@ namespace UniVRM10 { public static class VrmScriptedImporterImpl { - /// - /// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする - /// - /// - /// - /// - public static bool TryParseOrMigrate(string path, bool migrateToVrm1, out GltfParser parser, out string error) - { - // - // Parse(parse glb, parser gltf json) - // - parser = new GltfParser(); - parser.ParsePath(path); - if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) - { - // success - error = default; - return true; - } - - if (!migrateToVrm1) - { - error = "vrm1 not found"; - return false; - } - - // try migrateion - Byte[] migrated = default; - try - { - var src = File.ReadAllBytes(path); - var glb = UniGLTF.Glb.Parse(src); - var json = glb.Json.Bytes.ParseAsJson(); - if (!json.TryGet("extensions", out JsonNode extensions)) - { - error = "no gltf.extensions"; - return false; - } - if (!extensions.TryGet("VRM", out JsonNode vrm0)) - { - error = "vrm0 not found"; - return false; - } - - migrated = MigrationVrm.Migrate(json, glb.Binary.Bytes); - if (migrated == null) - { - error = "cannot migrate"; - return false; - } - } - catch (Exception ex) - { - error = $"migration error: {ex}"; - return false; - } - - parser = new GltfParser(); - parser.Parse(path, migrated); - if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out vrm)) - { - // success - error = default; - return true; - } - - error = "migrate but no vrm1. unknown"; - return false; - } - public static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, bool migrateToVrm1) { #if VRM_DEVELOP Debug.Log("OnImportAsset to " + scriptedImporter.assetPath); #endif - if (!TryParseOrMigrate(scriptedImporter.assetPath, migrateToVrm1, out GltfParser parser, out string message)) + if (!Vrm10Parser.TryParseOrMigrate(scriptedImporter.assetPath, migrateToVrm1, out Vrm10Parser.Result result, out string message)) { // fail to parse vrm1 return; @@ -104,7 +34,7 @@ namespace UniVRM10 var extractedObjects = scriptedImporter.GetExternalObjectMap() .ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value); - using (var loader = new Vrm10Importer(parser, extractedObjects)) + using (var loader = new Vrm10Importer(result.Parser, result.Vrm, extractedObjects)) { // settings TextureImporters foreach (var textureInfo in loader.TextureDescriptorGenerator.Get().GetEnumerable()) diff --git a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs index ab19bd18f..1e96fe11c 100644 --- a/Assets/VRM10/Runtime/IO/Vrm10Importer.cs +++ b/Assets/VRM10/Runtime/IO/Vrm10Importer.cs @@ -23,11 +23,22 @@ namespace UniVRM10 IReadOnlyDictionary m_externalMap; public Vrm10Importer( - UniGLTF.GltfParser parser, + UniGLTF.GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm, IReadOnlyDictionary externalObjectMap = null, ITextureDeserializer textureDeserializer = null) : base(parser, externalObjectMap, textureDeserializer) { + if (parser == null) + { + throw new ArgumentNullException("parser"); + } + + if (vrm == null) + { + throw new ArgumentNullException("vrm"); + } + m_vrm = vrm; + TextureDescriptorGenerator = new Vrm10TextureDescriptorGenerator(parser); MaterialDescriptorGenerator = new Vrm10MaterialDescriptorGenerator(); @@ -36,12 +47,9 @@ namespace UniVRM10 { m_externalMap = new Dictionary(); } - m_model = ModelReader.Read(parser); - if (!UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out m_vrm)) - { - throw new Vrm10NoExtensionException(); - } + // bin に対して右手左手変換を破壊的に実行することに注意 !(bin が変換済みになる) + m_model = ModelReader.Read(parser); // assign humanoid bones if (m_vrm.Humanoid != null) @@ -104,29 +112,6 @@ namespace UniVRM10 } } - public static Vrm10Importer OpenOrMigrate(byte[] bytes, string path) - { - try - { - var parser = new GltfParser(); - parser.Parse(path, bytes); - return new Vrm10Importer(parser); - } - catch (Vrm10NoExtensionException) - { - Debug.Log("vrm1 not found. try migration..."); - bytes = MigrationVrm.Migrate(bytes); - var parser = new GltfParser(); - parser.Parse(path, bytes); - return new Vrm10Importer(parser); - } - } - - public static Vrm10Importer OpenOrMigrate(string path) - { - return OpenOrMigrate(File.ReadAllBytes(path), path); - } - public class ModelMap { public readonly Dictionary Nodes = new Dictionary(); diff --git a/Assets/VRM10/Runtime/IO/Vrm10Parser.cs b/Assets/VRM10/Runtime/IO/Vrm10Parser.cs new file mode 100644 index 000000000..e9e876b03 --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Vrm10Parser.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using UniGLTF; +using UniGLTF.Extensions.VRMC_vrm; +using UniJSON; + +namespace UniVRM10 +{ + public static class Vrm10Parser + { + public readonly struct Result + { + public readonly GltfParser Parser; + public readonly VRMC_vrm Vrm; + + public Result(GltfParser parser, VRMC_vrm vrm) + { + Parser = parser; + Vrm = vrm; + } + } + + public static bool TryParseOrMigrate(string path, bool doMigrate, out Result result, out string error) + { + return TryParseOrMigrate(path, File.ReadAllBytes(path), doMigrate, out result, out error); + } + + /// + /// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする + /// + /// + /// + /// + public static bool TryParseOrMigrate(string path, byte[] bytes, bool doMigrate, out Result result, out string error) + { + // + // Parse(parse glb, parser gltf json) + // + { + var parser = new GltfParser(); + parser.Parse(path, bytes); + if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm)) + { + // success + error = default; + result = new Result(parser, vrm); + return true; + } + } + + if (!doMigrate) + { + error = "vrm1 not found"; + result = default; + return false; + } + + // try migrateion + byte[] migrated = default; + try + { + var glb = UniGLTF.Glb.Parse(bytes); + var json = glb.Json.Bytes.ParseAsJson(); + if (!json.TryGet("extensions", out JsonNode extensions)) + { + error = "no gltf.extensions"; + result = default; + return false; + } + if (!extensions.TryGet("VRM", out JsonNode vrm0)) + { + error = "vrm0 not found"; + result = default; + return false; + } + + migrated = MigrationVrm.Migrate(json, glb.Binary.Bytes); + if (migrated == null) + { + error = "cannot migrate"; + result = default; + return false; + } + } + catch (Exception ex) + { + error = $"migration error: {ex}"; + result = default; + return false; + } + + { + var parser = new GltfParser(); + parser.Parse(path, migrated); + if (UniGLTF.Extensions.VRMC_vrm.GltfDeserializer.TryGet(parser.GLTF.extensions, out VRMC_vrm vrm)) + { + // success + error = default; + result = new Result(parser, vrm); + return true; + } + } + + error = "migrate but no vrm1. unknown"; + result = default; + return false; + } + } +} diff --git a/Assets/VRM10/Runtime/IO/Vrm10Parser.cs.meta b/Assets/VRM10/Runtime/IO/Vrm10Parser.cs.meta new file mode 100644 index 000000000..551bbe96c --- /dev/null +++ b/Assets/VRM10/Runtime/IO/Vrm10Parser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4bece9378632bd4682bf5551630fafe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/VRM10/Runtime/Scenes/Sample.cs b/Assets/VRM10/Runtime/Scenes/Sample.cs index 1b509341e..211d1ce36 100644 --- a/Assets/VRM10/Runtime/Scenes/Sample.cs +++ b/Assets/VRM10/Runtime/Scenes/Sample.cs @@ -15,7 +15,12 @@ namespace UniVRM10.Sample static GameObject Import(byte[] bytes, FileInfo path) { - using (var loader = Vrm10Importer.OpenOrMigrate(bytes, path.FullName)) + if (!Vrm10Parser.TryParseOrMigrate(path.FullName, bytes, doMigrate: true, out Vrm10Parser.Result result, out string message)) + { + return null; + } + + using (var loader = new Vrm10Importer(result.Parser, result.Vrm)) { loader.Load(); loader.ShowMeshes(); diff --git a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs index 7103cc7bf..55a099959 100644 --- a/Assets/VRM10/Tests.PlayMode/MaterialTests.cs +++ b/Assets/VRM10/Tests.PlayMode/MaterialTests.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using NUnit.Framework; using UniGLTF; +using UniGLTF.Extensions.VRMC_vrm; using UnityEngine; using UnityEngine.TestTools; using UniVRM10; @@ -30,16 +31,18 @@ namespace UniVRM10.Test private (GameObject, IReadOnlyList) ToUnity(byte[] bytes) { // Vrm => Model - var parser = new UniGLTF.GltfParser(); - parser.Parse("tmp.vrm", bytes); + if(!Vrm10Parser.TryParseOrMigrate("tpm.vrm", bytes, true, out Vrm10Parser.Result result, out string error)) + { + throw new Exception(); + } - return ToUnity(parser); + return ToUnity(result.Parser, result.Vrm); } - private (GameObject, IReadOnlyList) ToUnity(GltfParser parser) + private (GameObject, IReadOnlyList) ToUnity(GltfParser parser, VRMC_vrm vrm) { // Model => Unity - using (var loader = new Vrm10Importer(parser)) + using (var loader = new Vrm10Importer(parser, vrm)) { loader.Load(); loader.DisposeOnGameObjectDestroyed(); diff --git a/Assets/VRM10/Tests/ApiSampleTests.cs b/Assets/VRM10/Tests/ApiSampleTests.cs index 4e80f29a3..e4d1c722a 100644 --- a/Assets/VRM10/Tests/ApiSampleTests.cs +++ b/Assets/VRM10/Tests/ApiSampleTests.cs @@ -1,6 +1,7 @@ using System.IO; using NUnit.Framework; using UniGLTF; +using UniGLTF.Extensions.VRMC_vrm; using UnityEngine; using VRMShaders; @@ -19,9 +20,9 @@ namespace UniVRM10.Test return model; } - GameObject BuildGameObject(GltfParser parser, bool showMesh) + GameObject BuildGameObject(GltfParser parser, VRMC_vrm vrm, bool showMesh) { - using (var loader = new Vrm10Importer(parser)) + using (var loader = new Vrm10Importer(parser, vrm)) { loader.Load(); if (showMesh) @@ -39,12 +40,9 @@ namespace UniVRM10.Test var path = "Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm"; Debug.Log($"load: {path}"); - var migrated = MigrationVrm.Migrate(File.ReadAllBytes(path)); + Assert.IsTrue(Vrm10Parser.TryParseOrMigrate(path, true, out Vrm10Parser.Result result, out string error)); - var parser = new GltfParser(); - parser.Parse(path, migrated); - - var go = BuildGameObject(parser, true); + var go = BuildGameObject(result.Parser, result.Vrm, true); Debug.Log(go); // export