242 lines
10 KiB
C#
242 lines
10 KiB
C#
using NUnit.Framework;
|
|
using System.IO;
|
|
using UniGLTF;
|
|
using UniGLTF.MeshUtility;
|
|
using UniJSON;
|
|
using UnityEngine;
|
|
using System;
|
|
using VRMShaders;
|
|
|
|
namespace VRM.Samples
|
|
{
|
|
public static class JsonExtensions
|
|
{
|
|
public static void SetValue<T>(this JsonNode node, string key, T value, Action<JsonFormatter, T> serialize)
|
|
{
|
|
var f = new JsonFormatter();
|
|
serialize(f, value);
|
|
var p = Utf8String.From(key);
|
|
var bytes = f.GetStoreBytes();
|
|
node.SetValue(p, bytes);
|
|
}
|
|
|
|
public static string ToJson(this glTF self)
|
|
{
|
|
var f = new JsonFormatter();
|
|
GltfSerializer.Serialize(f, self);
|
|
return f.ToString();
|
|
}
|
|
}
|
|
|
|
public class VRMImportExportTests
|
|
{
|
|
static string AliciaPath
|
|
{
|
|
get
|
|
{
|
|
return Path.GetFullPath(Application.dataPath + "/../Tests/Models/Alicia_vrm-0.51/AliciaSolid_vrm-0.51.vrm")
|
|
.Replace("\\", "/");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ImportExportTest()
|
|
{
|
|
var path = AliciaPath;
|
|
using (var data = new GlbFileParser(path).Parse())
|
|
using (var context = new VRMImporterContext(new VRMData(data)))
|
|
using (var loaded = context.Load())
|
|
{
|
|
loaded.ShowMeshes();
|
|
loaded.EnableUpdateWhenOffscreen();
|
|
|
|
// mesh
|
|
{
|
|
foreach (var renderer in loaded.GetComponentsInChildren<Renderer>())
|
|
{
|
|
Mesh mesh = default;
|
|
if (renderer is MeshRenderer)
|
|
{
|
|
var f = renderer.GetComponent<MeshFilter>();
|
|
mesh = f.sharedMesh;
|
|
}
|
|
else if (renderer is SkinnedMeshRenderer smr)
|
|
{
|
|
mesh = smr.sharedMesh;
|
|
}
|
|
|
|
var gltfMesh = data.GLTF.meshes.Find(x => x.name == mesh.name);
|
|
Assert.AreEqual(gltfMesh.name, mesh.name);
|
|
|
|
// materials
|
|
foreach (var material in renderer.sharedMaterials)
|
|
{
|
|
var gltfMaterial = data.GLTF.materials.Find(x => x.name == material.name);
|
|
Assert.AreEqual(gltfMaterial.name, material.name);
|
|
|
|
var materialIndex = data.GLTF.materials.IndexOf(gltfMaterial);
|
|
var vrmMaterial = context.VRM.materialProperties[materialIndex];
|
|
// Debug.Log($"shaderName: '{vrmMaterial.shader}'");
|
|
if (vrmMaterial.shader == "VRM/MToon")
|
|
{
|
|
// MToon
|
|
// Debug.Log($"{material.name} is MToon");
|
|
foreach (var kv in vrmMaterial.textureProperties)
|
|
{
|
|
var texture = material.GetTexture(kv.Key);
|
|
// Debug.Log($"{kv.Key}: {texture}");
|
|
Assert.NotNull(texture);
|
|
}
|
|
}
|
|
else if (glTF_KHR_materials_unlit.IsEnable(gltfMaterial))
|
|
{
|
|
// Unlit
|
|
// Debug.Log($"{material.name} is unlit");
|
|
throw new NotImplementedException();
|
|
}
|
|
else
|
|
{
|
|
// PBR
|
|
// Debug.Log($"{material.name} is PBR");
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// meta
|
|
{
|
|
var meta = loaded.GetComponent<VRMMeta>();
|
|
}
|
|
|
|
// humanoid
|
|
{
|
|
var animator = loaded.GetComponent<Animator>();
|
|
}
|
|
|
|
|
|
// blendshape
|
|
{
|
|
var blendshapeProxy = loaded.GetComponent<VRMBlendShapeProxy>();
|
|
for (int i = 0; i < context.VRM.blendShapeMaster.blendShapeGroups.Count; ++i)
|
|
{
|
|
var gltfBlendShapeClip = context.VRM.blendShapeMaster.blendShapeGroups[i];
|
|
var unityBlendShapeClip = blendshapeProxy.BlendShapeAvatar.Clips[i];
|
|
Assert.AreEqual(Enum.Parse(typeof(BlendShapePreset), gltfBlendShapeClip.presetName, true), unityBlendShapeClip.Preset);
|
|
}
|
|
}
|
|
|
|
var importedJson = JsonParser.Parse(context.Json);
|
|
importedJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION, (f, x) => f.Value(x));
|
|
importedJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION, (f, x) => f.Value(x));
|
|
importedJson.SetValue("/scene", 0, (f, x) => f.Value(x));
|
|
importedJson.SetValue("/materials/*/doubleSided", false, (f, x) => f.Value(x));
|
|
//importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0);
|
|
//importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 });
|
|
importedJson.SetValue("/accessors/*/normalized", false, (f, x) => f.Value(x));
|
|
importedJson.RemoveValue(Utf8String.From("/nodes/*/extras"));
|
|
/*
|
|
importJson.SetValue("/bufferViews/12/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/13/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/14/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/15/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/22/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/29/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/45/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/46/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/47/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/201/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/202/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/203/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/204/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/211/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/212/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/213/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/214/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/215/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/243/byteStride", 4);
|
|
importJson.SetValue("/bufferViews/247/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/248/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/249/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/250/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/251/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/252/byteStride", 64);
|
|
importJson.SetValue("/bufferViews/253/byteStride", 64);
|
|
*/
|
|
importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
|
|
|
|
var vrm = VRMExporter.Export(new GltfExportSettings(), loaded.gameObject, new EditorTextureSerializer());
|
|
|
|
// TODO: Check contents in JSON
|
|
/*var exportJson = */
|
|
JsonParser.Parse(vrm.Gltf.ToJson());
|
|
|
|
// TODO: Check contents in JSON
|
|
/*var newExportedJson = */
|
|
// JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
|
|
|
|
/*
|
|
foreach (var kv in importJson.Diff(exportJson))
|
|
{
|
|
Debug.Log(kv);
|
|
}
|
|
|
|
Assert.AreEqual(importJson, exportJson);
|
|
*/
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void MeshCopyTest()
|
|
{
|
|
var path = AliciaPath;
|
|
using (var data = new GlbFileParser(path).Parse())
|
|
using (var context = new VRMImporterContext(new VRMData(data)))
|
|
using (var loaded = context.Load())
|
|
{
|
|
loaded.ShowMeshes();
|
|
loaded.EnableUpdateWhenOffscreen();
|
|
foreach (var mesh in context.Meshes)
|
|
{
|
|
var src = mesh.Mesh;
|
|
var dst = src.Copy(true);
|
|
MeshTests.MeshEquals(src, dst);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SerializerCompare()
|
|
{
|
|
// Aliciaを古いデシリアライザでロードする
|
|
var path = AliciaPath;
|
|
|
|
using (var data = new GlbFileParser(path).Parse())
|
|
using (var context = new VRMImporterContext(new VRMData(data)))
|
|
{
|
|
var oldJson = context.GLTF.ToJson().ParseAsJson().ToString(" ");
|
|
|
|
// 生成シリアライザでJSON化する
|
|
var f = new JsonFormatter();
|
|
GltfSerializer.Serialize(f, context.GLTF);
|
|
var parsed = f.ToString().ParseAsJson();
|
|
var newJson = parsed.ToString(" ");
|
|
|
|
// File.WriteAllText("old.json", oldJson);
|
|
// File.WriteAllText("new.json", newJson);
|
|
|
|
// 比較
|
|
Assert.AreEqual(oldJson.ParseAsJson().ToString(), newJson.ParseAsJson().ToString());
|
|
|
|
// 生成デシリアライザでロードする
|
|
var ff = new JsonFormatter();
|
|
var des = GltfDeserializer.Deserialize(parsed);
|
|
ff.Clear();
|
|
GltfSerializer.Serialize(ff, des);
|
|
var desJson = ff.ToString().ParseAsJson().ToString(" ");
|
|
Assert.AreEqual(oldJson.ParseAsJson().ToString(), desJson.ParseAsJson().ToString());
|
|
}
|
|
}
|
|
}
|
|
}
|