This commit is contained in:
ousttrue
2021-02-08 22:51:39 +09:00
parent dadf45865c
commit 65ee54543a
6 changed files with 159 additions and 15 deletions

View File

@@ -16,8 +16,14 @@ namespace UniVRM10
var json = glb.Json.Bytes.ParseAsJson();
var gltf = UniGLTF.GltfDeserializer.Deserialize(json);
// attach glb bin to buffer
foreach (var buffer in gltf.buffers)
{
buffer.OpenStorage(new UniGLTF.SimpleStorage(glb.Binary.Bytes));
}
// https://github.com/vrm-c/vrm-specification/issues/205
SceneRotator.Rotate(gltf);
RotateY180.Rotate(gltf);
var extensions = new UniGLTF.glTFExtensionExport();
{

View File

@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using UniGLTF;
namespace UniVRM10
{
/// <summary>
/// x, y, z => -x, y, -z
/// </summary>
public static class RotateY180
{
public static void Rotate(glTFNode node)
{
if (node.matrix != null && node.matrix.Length == 16)
{
throw new NotImplementedException("matrix not implemented !");
}
else
{
if (node.translation != null && node.translation.Length == 3)
{
var t = node.translation;
t[0] = -t[0];
t[2] = -t[2];
}
if (node.rotation != null && node.rotation.Length == 4)
{
// throw new NotImplementedException("not normlaized !");
}
if (node.scale != null && node.rotation.Length == 3)
{
// do nothing
}
}
}
static void ReverseVector3Array(glTF gltf, int accessorIndex, HashSet<int> used)
{
if (!used.Add(accessorIndex))
{
return;
}
var accessor = gltf.accessors[accessorIndex];
var buffer = gltf.GetViewBytes(accessor.bufferView);
var span = VrmLib.SpanLike.Wrap<UnityEngine.Vector3>(buffer);
for (int i = 0; i < span.Length; ++i)
{
span[i] = span[i].RotateY180();
}
}
/// <summary>
/// シーンをY軸で180度回転する
/// </summary>
/// <param name="gltf"></param>
public static void Rotate(glTF gltf)
{
foreach (var node in gltf.nodes)
{
Rotate(node);
}
var used = new HashSet<int>();
foreach (var mesh in gltf.meshes)
{
foreach (var prim in mesh.primitives)
{
ReverseVector3Array(gltf, prim.attributes.POSITION, used);
ReverseVector3Array(gltf, prim.attributes.NORMAL, used);
foreach (var target in prim.targets)
{
ReverseVector3Array(gltf, target.POSITION, used);
ReverseVector3Array(gltf, target.NORMAL, used);
}
}
}
foreach (var skin in gltf.skins)
{
if (!used.Add(skin.inverseBindMatrices))
{
var accessor = gltf.accessors[skin.inverseBindMatrices];
var buffer = gltf.GetViewBytes(accessor.bufferView);
var span = VrmLib.SpanLike.Wrap<UnityEngine.Matrix4x4>(buffer);
for (int i = 0; i < span.Length; ++i)
{
// span[i] = span[i].RotateY180();
}
}
}
}
}
}

View File

@@ -1,14 +0,0 @@
namespace UniVRM10
{
public static class SceneRotator
{
/// <summary>
/// シーンをY軸で180度回転する
/// </summary>
/// <param name="gltf"></param>
public static void Rotate(UniGLTF.glTF gltf)
{
}
}
}

View File

@@ -40,11 +40,21 @@ namespace UniVRM10
public static class UnityExtensions
{
public static Vector4 RotateY180(this Vector4 v)
{
return new Vector4(-v.x, v.y, -v.z, v.w);
}
public static Vector4 ReverseZ(this Vector4 v)
{
return new Vector4(v.x, v.y, -v.z, v.w);
}
public static Vector3 RotateY180(this Vector3 v)
{
return new Vector3(-v.x, v.y, -v.z);
}
public static Vector3 ReverseZ(this Vector3 v)
{
return new Vector3(v.x, v.y, -v.z);
@@ -94,6 +104,14 @@ namespace UniVRM10
#endif
}
public static Matrix4x4 RotateY180(this Matrix4x4 m)
{
var t = m.GetColumn(3);
var tt = RotateY180(t);
m.SetColumn(3, tt);
return m;
}
public static Matrix4x4 ReverseZ(this Matrix4x4 m)
{
m.SetTRS(m.ExtractPosition().ReverseZ(), m.ExtractRotation().ReverseZ(), m.ExtractScale());

View File

@@ -3,6 +3,7 @@ using NUnit.Framework;
using UnityEngine;
using UniJSON;
using System;
using UniGLTF;
namespace UniVRM10
{
@@ -56,5 +57,44 @@ namespace UniVRM10
MigrationVrm.Check(vrm0Json, GetExtension(gltf.extensions, UniGLTF.Extensions.VRMC_springBone.VRMC_springBone.ExtensionNameUtf8,
UniGLTF.Extensions.VRMC_springBone.GltfDeserializer.Deserialize), gltf.nodes);
}
const float EPS = 1e-4f;
static bool Nearly(float l, float r)
{
return Mathf.Abs(l - r) <= EPS;
}
static bool Nearly(Vector3 l, Vector3 r)
{
if (!Nearly(l.x, r.x)) return false;
if (!Nearly(l.y, r.y)) return false;
if (!Nearly(l.z, r.z)) return false;
return true;
}
[Test]
public void RotateTest()
{
var euler = new Vector3(0, 10, 20);
var r = Quaternion.Euler(euler);
var node = new glTFNode
{
translation = new float[] { 1, 2, 3 },
rotation = new float[] { r.x, r.y, r.z, r.w },
scale = new float[] { 1, 2, 3 },
};
RotateY180.Rotate(node);
Assert.AreEqual(new Vector3(-1, 2, 3), node.translation.ToVector3().ToUnityVector3());
Assert.AreEqual(new Vector3(1, 2, 3), node.scale.ToVector3().ToUnityVector3());
var result = node.rotation.ToQuaternion().ToUnityQuaternion().eulerAngles;
Debug.LogFormat($"{result}");
Assert.True(Nearly(0, result.x));
Assert.True(Nearly(360 - 10, result.y));
Assert.True(Nearly(360 - 20, result.z));
}
}
}