Vrm10Parser を導入して、ここで extension の取り出しと migrate を呼び出すようにした。

This commit is contained in:
ousttrue 2021-06-09 13:16:04 +09:00
parent b07eda0caa
commit e7d461fac1
9 changed files with 162 additions and 116 deletions

View File

@ -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();

View File

@ -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;

View File

@ -16,83 +16,13 @@ namespace UniVRM10
{
public static class VrmScriptedImporterImpl
{
/// <summary>
/// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする
/// </summary>
/// <param name="path"></param>
/// <param name="migrateToVrm1"></param>
/// <returns></returns>
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())

View File

@ -23,11 +23,22 @@ namespace UniVRM10
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> m_externalMap;
public Vrm10Importer(
UniGLTF.GltfParser parser,
UniGLTF.GltfParser parser, UniGLTF.Extensions.VRMC_vrm.VRMC_vrm vrm,
IReadOnlyDictionary<SubAssetKey, UnityEngine.Object> 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<SubAssetKey, UnityEngine.Object>();
}
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<VrmLib.Node, GameObject> Nodes = new Dictionary<VrmLib.Node, GameObject>();

View File

@ -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);
}
/// <summary>
/// VRM1 で パースし、失敗したら Migration してから VRM1 でパースする
/// </summary>
/// <param name="path"></param>
/// <param name="doMigrate"></param>
/// <returns></returns>
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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e4bece9378632bd4682bf5551630fafe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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();

View File

@ -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<VRMShaders.MaterialFactory.MaterialLoadInfo>) 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<VRMShaders.MaterialFactory.MaterialLoadInfo>) ToUnity(GltfParser parser)
private (GameObject, IReadOnlyList<VRMShaders.MaterialFactory.MaterialLoadInfo>) 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();

View File

@ -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