Merge pull request #1531 from ousttrue/fix/system_numerics_to_unityengine

Fix/system numerics to unityengine
This commit is contained in:
ousttrue
2022-02-22 18:13:44 +09:00
committed by GitHub
24 changed files with 237 additions and 304 deletions

View File

@@ -7,11 +7,6 @@ namespace UniGLTF
{
const float EPSILON = 1e-5f;
public static bool NearlyEqual(this float lhs, float rhs)
{
return Math.Abs(lhs - rhs) <= EPSILON;
}
public static bool NearlyEqual(this Vector3 lhs, Vector3 rhs)
{
if (Math.Abs(lhs.X - rhs.X) > EPSILON) return false;
@@ -31,10 +26,6 @@ namespace UniGLTF
public const float TO_RAD = (float)(Math.PI / 180.0);
public static Vector2 UVVerticalFlip(this Vector2 src)
{
return new Vector2(src.X, 1.0f - src.Y);
}
public static Vector3 ReverseX(this Vector3 src)
{
@@ -104,13 +95,6 @@ namespace UniGLTF
return ss * rr * tt;
}
public static (Vector3, Quaternion, Vector3) Decompose(this Matrix4x4 m)
{
var s = m.ExtractScale();
var mm = Matrix4x4.CreateScale(1.0f / s.X, 1.0f / s.Y, 1.0f / s.Z) * m;
return (mm.ExtractPosition(), mm.ExtractRotation(), s);
}
public static bool IsOnlyTranslation(this Matrix4x4 m)
{
if (m.M11 != 1.0f) return false;
@@ -124,51 +108,5 @@ namespace UniGLTF
if (m.M32 != 0) return false;
return true;
}
/// <summary>
/// 移動 z反転
/// 回転 z反転
/// 拡大 据え置き
///
/// これでいいのか?
/// </summary>
public static Matrix4x4 ReverseZ(this Matrix4x4 m)
{
if (m.IsOnlyTranslation())
{
var ret = m;
// R, R, R, 0
// R, R, R, 0
// R, R, R, 0
// T, T, T, 1
ret.M43 = -ret.M43;
return ret;
}
else
{
var (t, r, s) = m.Decompose();
return FromTRS(t.ReverseZ(), r.ReverseZ(), s);
}
}
public static Matrix4x4 ReverseX(this Matrix4x4 m)
{
if (m.IsOnlyTranslation())
{
var ret = m;
// R, R, R, 0
// R, R, R, 0
// R, R, R, 0
// T, T, T, 1
ret.M41 = -ret.M41;
return ret;
}
else
{
var (t, r, s) = m.Decompose();
return FromTRS(t.ReverseX(), r.ReverseX(), s);
}
}
}
}

View File

@@ -59,6 +59,42 @@ namespace UniGLTF
public static class UnityExtensions
{
const float EPSILON = 1e-5f;
public static bool NearlyEqual(this float lhs, float rhs)
{
return Math.Abs(lhs - rhs) <= EPSILON;
}
public static bool NearlyEqual(this Vector3 lhs, Vector3 rhs)
{
if (Math.Abs(lhs.x - rhs.x) > EPSILON) return false;
if (Math.Abs(lhs.y - rhs.y) > EPSILON) return false;
if (Math.Abs(lhs.z - rhs.z) > EPSILON) return false;
return true;
}
public static bool NearlyEqual(this Quaternion lhs, Quaternion rhs)
{
if (Math.Abs(lhs.x - rhs.x) > EPSILON) return false;
if (Math.Abs(lhs.y - rhs.y) > EPSILON) return false;
if (Math.Abs(lhs.z - rhs.z) > EPSILON) return false;
if (Math.Abs(lhs.w - rhs.w) > EPSILON) return false;
return true;
}
public static (Vector3, Quaternion, Vector3) Decompose(this Matrix4x4 m)
{
var s = m.ExtractScale();
var mm = Matrix4x4.Scale(new Vector3(1.0f / s.x, 1.0f / s.y, 1.0f / s.z)) * m;
return (mm.ExtractPosition(), mm.ExtractRotation(), s);
}
public static Vector2 UVVerticalFlip(this Vector2 src)
{
return new Vector2(src.x, 1.0f - src.y);
}
public static Vector4 ReverseZ(this Vector4 v)
{
return new Vector4(v.x, v.y, -v.z, v.w);

View File

@@ -28,15 +28,6 @@ namespace UniGLTF
Assert.AreEqual(new Vector3(1, 2, -3), r);
}
[Test]
[Category("Numerics")]
public void UVTest()
{
var v = new Vector2(0.1f, 0.2f);
var r = v.UVVerticalFlip();
Assert.AreEqual(new Vector2(0.1f, 0.8f), r);
}
[Test]
[Category("Numerics")]
public void MatrixTranslationTest()
@@ -71,21 +62,5 @@ namespace UniGLTF
var ex = m.ExtractScale();
Assert.AreEqual(s, ex);
}
[Test]
[Category("Numerics")]
public void MatrixTest()
{
var t = new Vector3(1, 2, 3);
var orgAxis = Vector3.Normalize(new Vector3(1, 2, 3));
var orgAngle = 90 * NumericsExtensions.TO_RAD;
var r = Quaternion.CreateFromAxisAngle(orgAxis, orgAngle);
var s = new Vector3(2, 3, 4);
var m = NumericsExtensions.FromTRS(t, r, s);
var (tt, rr, ss) = m.Decompose();
Assert.True(s.NearlyEqual(ss));
Assert.True(r.NearlyEqual(rr));
Assert.AreEqual(t, tt);
}
}
}

View File

@@ -735,5 +735,28 @@ namespace UniGLTF
Assert.NotNull(dummy.Value);
Assert.False(dummy.Value.Value);
}
[Test]
public void UVTest()
{
var v = new Vector2(0.1f, 0.2f);
var r = v.UVVerticalFlip();
Assert.AreEqual(new Vector2(0.1f, 0.8f), r);
}
[Test]
public void MatrixTest()
{
var t = new Vector3(1, 2, 3);
var orgAxis = Vector3.Normalize(new Vector3(1, 2, 3));
var orgAngle = 90 * NumericsExtensions.TO_RAD;
var r = Quaternion.AngleAxis(orgAngle, orgAxis);
var s = new Vector3(2, 3, 4);
var m = Matrix4x4.TRS(t, r, s);
var (tt, rr, ss) = m.Decompose();
Assert.True(s.NearlyEqual(ss));
Assert.True(r.NearlyEqual(rr));
Assert.AreEqual(t, tt);
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Runtime.InteropServices;
using NUnit.Framework;
namespace UniGLTF
{
public class UnityEngineNumerics
{
[Test]
public void Values()
{
var values = new float[16];
// T
{
var um = UnityEngine.Matrix4x4.Translate(new UnityEngine.Vector3(1, 2, 3));
using (var pin = Pin.Create(new[] { um }))
{
Marshal.Copy(pin.Ptr, values, 0, 16);
}
Assert.AreEqual(1, um.m03);
Assert.AreEqual(2, um.m13);
Assert.AreEqual(3, um.m23);
Assert.AreEqual(new UnityEngine.Vector4(1, 2, 3, 1), um.GetColumn(3));
Assert.AreEqual(new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 }, values);
var v = new UnityEngine.Vector4();
var m = new UnityEngine.Matrix4x4();
m.MultiplyVector(v);
// new UnityEngine.Matrix4x4.mul new UnityEngine.Vector3().mul
}
{
var nm = System.Numerics.Matrix4x4.CreateTranslation(1, 2, 3);
using (var pin = Pin.Create(new[] { nm }))
{
Marshal.Copy(pin.Ptr, values, 0, 16);
}
Assert.AreEqual(1, nm.M41);
Assert.AreEqual(2, nm.M42);
Assert.AreEqual(3, nm.M43);
Assert.AreEqual(new System.Numerics.Vector3(1, 2, 3), nm.Translation);
Assert.AreEqual(new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 }, values);
}
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: a20bf106ed875aa4f9d5cf91ad104d8f
guid: 352a9a8842c77a34f968dd0ee91b1186
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@@ -1,5 +1,5 @@
using System;
using System.Numerics;
using UnityEngine;
namespace UniVRM10
{
@@ -10,15 +10,15 @@ namespace UniVRM10
if (src.Length != 3) return defaultValue;
var v = new Vector3();
v.X = src[0];
v.Y = src[1];
v.Z = src[2];
v.x = src[0];
v.y = src[1];
v.z = src[2];
return v;
}
public static Quaternion ToQuaternion(this float[] src)
{
if (src.Length != 4) return Quaternion.Identity;
if (src.Length != 4) return Quaternion.identity;
var v = new Quaternion(src[0], src[1], src[2], src[3]);
return v;

View File

@@ -135,9 +135,9 @@ namespace UniVRM10
Dictionary<GameObject, VrmLib.Node> nodes)
{
// parentNode.SetMatrix(parentTransform.localToWorldMatrix.ToNumericsMatrix4x4(), false);
parentNode.LocalTranslation = parentTransform.localPosition.ToNumericsVector3();
parentNode.LocalRotation = parentTransform.localRotation.ToNumericsQuaternion();
parentNode.LocalScaling = parentTransform.localScale.ToNumericsVector3();
parentNode.LocalTranslation = parentTransform.localPosition;
parentNode.LocalRotation = parentTransform.localRotation;
parentNode.LocalScaling = parentTransform.localScale;
nodes.Add(parentTransform.gameObject, parentNode);
foreach (Transform child in parentTransform)

View File

@@ -1,45 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VrmLib;
using UnityEngine;
namespace UniVRM10
{
public static class UnityExtension
{
public static Vector3 ToUnityVector3(this System.Numerics.Vector3 value)
public static float[] ToFloat3(this Vector3 value)
{
return new Vector3(value.X, value.Y, value.Z);
return new[] { value.x, value.y, value.z };
}
public static float[] ToFloat3(this System.Numerics.Vector3 value)
public static float[] ToFloat4(this Quaternion value)
{
return new[] { value.X, value.Y, value.Z };
}
public static Quaternion ToUnityQuaternion(this System.Numerics.Quaternion value)
{
return new Quaternion(value.X, value.Y, value.Z, value.W);
}
public static float[] ToFloat4(this System.Numerics.Quaternion value)
{
return new float[] { value.X, value.Y, value.Z, value.W };
}
public static System.Numerics.Vector2 ToNumericsVector2(this Vector2 value)
{
return new System.Numerics.Vector2(value.x, value.y);
}
public static System.Numerics.Vector3 ToNumericsVector3(this Vector3 value)
{
return new System.Numerics.Vector3(value.x, value.y, value.z);
}
public static System.Numerics.Quaternion ToNumericsQuaternion(this Quaternion value)
{
return new System.Numerics.Quaternion(value.x, value.y, value.z, value.w);
return new float[] { value.x, value.y, value.z, value.w };
}
}
}

View File

@@ -1,11 +1,11 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Numerics;
using UniGLTF;
using VrmLib;
using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
namespace UniVRM10
{
@@ -364,10 +364,10 @@ namespace UniVRM10
if (x.rotation != null && x.rotation.Length > 0) throw new Exception("matrix with rotation");
if (x.scale != null && x.scale.Length > 0) throw new Exception("matrix with scale");
var m = new Matrix4x4(
x.matrix[0], x.matrix[1], x.matrix[2], x.matrix[3],
x.matrix[4], x.matrix[5], x.matrix[6], x.matrix[7],
x.matrix[8], x.matrix[9], x.matrix[10], x.matrix[11],
x.matrix[12], x.matrix[13], x.matrix[14], x.matrix[15]
new Vector4(x.matrix[0], x.matrix[4], x.matrix[8], x.matrix[12]),
new Vector4(x.matrix[1], x.matrix[5], x.matrix[9], x.matrix[13]),
new Vector4(x.matrix[2], x.matrix[6], x.matrix[10], x.matrix[14]),
new Vector4(x.matrix[3], x.matrix[7], x.matrix[11], x.matrix[15])
);
node.SetLocalMatrix(m, true);
@@ -384,7 +384,7 @@ namespace UniVRM10
}
if (x.scale != null && x.scale.Length == 3)
{
node.LocalScaling = x.scale.ToVector3(Vector3.One);
node.LocalScaling = x.scale.ToVector3(Vector3.one);
}
}
return node;

View File

@@ -691,13 +691,13 @@ namespace UniVRM10
nodes.Add(node, go);
// world
go.transform.SetPositionAndRotation(node.Translation.ToUnityVector3(), node.Rotation.ToUnityQuaternion());
go.transform.SetPositionAndRotation(node.Translation, node.Rotation);
if (parent != null)
{
go.transform.SetParent(parent.transform, true);
}
// local
go.transform.localScale = node.LocalScaling.ToUnityVector3();
go.transform.localScale = node.LocalScaling;
if (node.Children.Count > 0)
{

View File

@@ -30,7 +30,7 @@ namespace UniVRM10.Migration
}
/// <summary>
/// VRM0.X version meta. This class has meta before migrate.
/// VRM0.x version meta. This class has meta before migrate.
/// </summary>
public class Vrm0Meta
{

View File

@@ -72,12 +72,12 @@ namespace UniVRM10.Test
Assert.AreEqual(color1.a, color2.a, 0.001f);
}
void EqualVector4(System.Numerics.Vector4 vec1, System.Numerics.Vector4 vec2)
void EqualVector4(Vector4 vec1, Vector4 vec2)
{
Assert.AreEqual(vec1.X, vec2.X, 0.001f);
Assert.AreEqual(vec1.Y, vec2.Y, 0.001f);
Assert.AreEqual(vec1.Z, vec2.Z, 0.001f);
Assert.AreEqual(vec1.W, vec2.W, 0.001f);
Assert.AreEqual(vec1.x, vec2.x, 0.001f);
Assert.AreEqual(vec1.y, vec2.y, 0.001f);
Assert.AreEqual(vec1.z, vec2.z, 0.001f);
Assert.AreEqual(vec1.w, vec2.w, 0.001f);
}
#region Color

View File

@@ -92,8 +92,8 @@ namespace UniVRM10
};
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());
Assert.AreEqual(new Vector3(-1, 2, -3), node.translation.ToVector3());
Assert.AreEqual(new Vector3(1, 2, 3), node.scale.ToVector3());
// var result = node.rotation.ToQuaternion().ToUnityQuaternion().eulerAngles;
// Debug.LogFormat($"{result}");

View File

@@ -2,7 +2,7 @@ using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using UnityEngine;
/// <summary>
@@ -182,7 +182,7 @@ namespace VrmLib
public (bool, string) Y180()
{
var sb = new System.Text.StringBuilder();
Hips.LocalRotation = Quaternion.CreateFromYawPitchRoll(MathFWrap.PI, 0, 0);
Hips.LocalRotation = Quaternion.Euler(0, MathFWrap.PI, 0);
Hips.CalcWorldMatrix();
return (true, sb.ToString());
}
@@ -198,22 +198,22 @@ namespace VrmLib
// hipsのforward を -Z に向ける
// hipsのforward は (left.leg - right.leg) cross (0, 1, 0)
var left = Vector3.Normalize(LeftLeg.Upper.Translation - RightLeg.Upper.Translation);
var forward = Vector3.Cross(left, Vector3.UnitY);
if (Vector3.Dot(forward, -Vector3.UnitZ) < 1.0f - 0.1f)
var forward = Vector3.Cross(left, Vector3.up);
if (Vector3.Dot(forward, -Vector3.forward) < 1.0f - 0.1f)
{
Hips.RotateFromTo(forward, -Vector3.UnitZ);
Hips.RotateFromTo(forward, -Vector3.forward);
modified = true;
}
if (Vector3.Dot(LeftArm.Direction, -Vector3.UnitX) < 1.0f - 0.1f)
if (Vector3.Dot(LeftArm.Direction, -Vector3.right) < 1.0f - 0.1f)
{
LeftArm.DirectTo(-Vector3.UnitX);
LeftArm.DirectTo(-Vector3.right);
sb.Append("(fix left arm)");
modified = true;
}
if (Vector3.Dot(RightArm.Direction, Vector3.UnitX) < 1.0f - 0.1f)
if (Vector3.Dot(RightArm.Direction, Vector3.right) < 1.0f - 0.1f)
{
RightArm.DirectTo(Vector3.UnitX);
RightArm.DirectTo(Vector3.right);
sb.Append("(fix right arm)");
modified = true;
}
@@ -230,7 +230,7 @@ namespace VrmLib
if (dst.TryGetValue(kv.Key, out Node node))
{
// var t = tposeNode.LocalRotation;
// var t = Quaternion.Identity;
// var t = Quaternion.identity;
// node.LocalRotationWithoutUpdate = Quaternion.Inverse(t) * kv.Value.LocalRotation;
// node.LocalRotationWithoutUpdate = kv.Value.LocalRotation * Quaternion.Inverse(t);

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using UnityEngine;
namespace VrmLib
{
@@ -35,25 +35,25 @@ namespace VrmLib
static void GetSpineAndHips(Node hips, out Node spine, out Node leg_L, out Node leg_R)
{
if (hips.Children.Count != 3) throw new System.Exception("Hips require 3 children");
spine = SelectBone((l, r) => l.CenterOfDescendant().Y > r.SkeletonLocalPosition.Y, hips);
spine = SelectBone((l, r) => l.CenterOfDescendant().y > r.SkeletonLocalPosition.y, hips);
var s = spine;
try
{
leg_L = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().X < r.SkeletonLocalPosition.X, hips);
leg_R = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().X > r.SkeletonLocalPosition.X, hips);
leg_L = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().x < r.SkeletonLocalPosition.x, hips);
leg_R = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().x > r.SkeletonLocalPosition.x, hips);
}
catch (Exception)
{
// Z軸で左右を代用
leg_L = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().Z < r.SkeletonLocalPosition.Z, hips);
leg_R = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().Z > r.SkeletonLocalPosition.Z, hips);
leg_L = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().z < r.SkeletonLocalPosition.z, hips);
leg_R = SelectBone((l, r) => !l.Equals(s) && l.CenterOfDescendant().z > r.SkeletonLocalPosition.z, hips);
}
}
static void GetNeckAndArms(Node chest, out Node neck, out Node arm_L, out Node arm_R, Func<Vector3, Vector3, bool> isLeft)
{
if (chest.Children.Count != 3) throw new System.Exception("Chest require 3 children");
neck = SelectBone((l, r) => l.CenterOfDescendant().Y > r.SkeletonLocalPosition.Y, chest);
neck = SelectBone((l, r) => l.CenterOfDescendant().y > r.SkeletonLocalPosition.y, chest);
var n = neck;
arm_L = SelectBone((l, r) => !l.Equals(n) && isLeft(l.CenterOfDescendant(), r.SkeletonLocalPosition), chest);
arm_R = SelectBone((l, r) => !l.Equals(n) && !isLeft(l.CenterOfDescendant(), r.SkeletonLocalPosition), chest);
@@ -189,13 +189,13 @@ namespace VrmLib
}
Func<Vector3, Vector3, bool> isLeft = default(Func<Vector3, Vector3, bool>);
if (legLeft.UpperLeg.SkeletonLocalPosition.Z == legRight.UpperLeg.SkeletonLocalPosition.Z)
if (legLeft.UpperLeg.SkeletonLocalPosition.z == legRight.UpperLeg.SkeletonLocalPosition.z)
{
isLeft = (l, r) => l.X < r.X;
isLeft = (l, r) => l.x < r.x;
}
else
{
isLeft = (l, r) => l.Z < r.Z;
isLeft = (l, r) => l.z < r.z;
}
Node neck, shoulder_L, shoulder_R;

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using UnityEngine;
namespace VrmLib
{
@@ -68,7 +68,7 @@ namespace VrmLib
{
AddBone(head.SkeletonLocalPosition, tail.SkeletonLocalPosition, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth);
}
else if (headTail.TailOffset != Vector3.Zero)
else if (headTail.TailOffset != Vector3.zero)
{
AddBone(head.SkeletonLocalPosition, head.SkeletonLocalPosition + headTail.TailOffset, bones.IndexOf(head), headTail.XWidth, headTail.ZWidth);
}
@@ -86,19 +86,19 @@ namespace VrmLib
void AddBone(Vector3 head, Vector3 tail, int boneIndex, float xWidth, float zWidth)
{
var yaxis = Vector3.Normalize(tail - head);
var yaxis = (tail - head).normalized;
Vector3 xaxis;
Vector3 zaxis;
if (Vector3.Dot(yaxis, Vector3.UnitZ) >= 1.0f - float.Epsilon)
if (Vector3.Dot(yaxis, Vector3.forward) >= 1.0f - float.Epsilon)
{
// ほぼZ軸
xaxis = Vector3.UnitX;
zaxis = -Vector3.UnitY;
xaxis = Vector3.right;
zaxis = -Vector3.up;
}
else
{
xaxis = Vector3.Normalize(Vector3.Cross(yaxis, Vector3.UnitZ));
zaxis = Vector3.UnitZ;
xaxis = Vector3.Normalize(Vector3.Cross(yaxis, Vector3.forward));
zaxis = Vector3.forward;
}
AddBox((head + tail) * 0.5f,
xaxis * xWidth,
@@ -150,25 +150,25 @@ namespace VrmLib
void AddQuad(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, int boneIndex, bool reverse = false)
{
var i = m_positioins.Count;
if (float.IsNaN(v0.X) || float.IsNaN(v0.Y) || float.IsNaN(v0.Z))
if (float.IsNaN(v0.x) || float.IsNaN(v0.y) || float.IsNaN(v0.z))
{
throw new Exception();
}
m_positioins.Add(v0);
if (float.IsNaN(v1.X) || float.IsNaN(v1.Y) || float.IsNaN(v1.Z))
if (float.IsNaN(v1.x) || float.IsNaN(v1.y) || float.IsNaN(v1.z))
{
throw new Exception();
}
m_positioins.Add(v1);
if (float.IsNaN(v2.X) || float.IsNaN(v2.Y) || float.IsNaN(v2.Z))
if (float.IsNaN(v2.x) || float.IsNaN(v2.y) || float.IsNaN(v2.z))
{
throw new Exception();
}
m_positioins.Add(v2);
if (float.IsNaN(v3.X) || float.IsNaN(v3.Y) || float.IsNaN(v3.Z))
if (float.IsNaN(v3.x) || float.IsNaN(v3.y) || float.IsNaN(v3.z))
{
throw new Exception();
}
@@ -219,7 +219,7 @@ namespace VrmLib
{
Head = head;
Tail = tail;
TailOffset = Vector3.Zero;
TailOffset = Vector3.zero;
XWidth = xWidth;
ZWidth = zWidth;
}

View File

@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using UniGLTF;
using Unity.Collections;
using UnityEngine;
namespace VrmLib
{
@@ -112,7 +110,7 @@ namespace VrmLib
// Skin.Normalize
public void ApplyRotationAndScaling(Matrix4x4 m)
{
m.Translation = Vector3.Zero;
m.SetColumn(3, new Vector4(0, 0, 0, 1));
var position = VertexBuffer.Positions.Bytes.Reinterpret<Vector3>(1);
var normal = VertexBuffer.Normals.Bytes.Reinterpret<Vector3>(1);
@@ -120,12 +118,10 @@ namespace VrmLib
for (int i = 0; i < position.Length; ++i)
{
{
var dst = Vector4.Transform(new Vector4(position[i], 1), m);
position[i] = new Vector3(dst.X, dst.Y, dst.Z);
position[i] = m.MultiplyPoint(position[i]);
}
{
var dst = Vector4.Transform(new Vector4(normal[i], 0), m);
normal[i] = new Vector3(dst.X, dst.Y, dst.Z);
normal[i] = m.MultiplyVector(normal[i]);
}
}
}

View File

@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using UniGLTF;
using Unity.Collections;
using UnityEngine;
namespace VrmLib
{
@@ -182,7 +182,7 @@ namespace VrmLib
// 回転・拡縮を除去
if (m_positionMap.TryGetValue(node, out Vector3 pos))
{
var t = Matrix4x4.CreateTranslation(pos);
var t = Matrix4x4.Translate(pos);
node.SetMatrix(t, false);
}
}

View File

@@ -2,8 +2,8 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using UnityEngine;
using UniGLTF;
namespace VrmLib
{
@@ -35,7 +35,7 @@ namespace VrmLib
//
// Localで値を保持する
//
public Vector3 LocalTranslationWithoutUpdate = Vector3.Zero;
public Vector3 LocalTranslationWithoutUpdate = Vector3.zero;
public Vector3 LocalTranslation
{
get => LocalTranslationWithoutUpdate;
@@ -43,11 +43,11 @@ namespace VrmLib
{
if (LocalTranslationWithoutUpdate == value) return;
LocalTranslationWithoutUpdate = value;
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.Identity);
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.identity);
}
}
public Quaternion LocalRotationWithoutUpdate = Quaternion.Identity;
public Quaternion LocalRotationWithoutUpdate = Quaternion.identity;
public Quaternion LocalRotation
{
get => LocalRotationWithoutUpdate;
@@ -55,11 +55,11 @@ namespace VrmLib
{
if (LocalRotationWithoutUpdate == value) return;
LocalRotationWithoutUpdate = value;
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.Identity);
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.identity);
}
}
public Vector3 LocalScalingWithoutUpdate = Vector3.One;
public Vector3 LocalScalingWithoutUpdate = Vector3.one;
public Vector3 LocalScaling
{
get => LocalScalingWithoutUpdate;
@@ -67,44 +67,35 @@ namespace VrmLib
{
if (LocalScalingWithoutUpdate == value) return;
LocalScalingWithoutUpdate = value;
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.Identity);
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.identity);
}
}
public Matrix4x4 LocalMatrix
{
get => Matrix4x4.CreateScale(LocalScaling)
* Matrix4x4.CreateFromQuaternion(LocalRotation)
* Matrix4x4.CreateTranslation(LocalTranslation);
get => Matrix4x4.Translate(LocalTranslation)
* Matrix4x4.Rotate(LocalRotation)
* Matrix4x4.Scale(LocalScaling)
;
}
public void SetLocalMatrix(Matrix4x4 value, bool calcWorldMatrix)
{
if (Matrix4x4.Decompose(value, out LocalScalingWithoutUpdate, out LocalRotationWithoutUpdate, out LocalTranslationWithoutUpdate))
{
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.Identity, calcWorldMatrix);
}
else
{
throw new Exception($"fail to decompose matrix: {Name}");
}
(LocalTranslationWithoutUpdate, LocalRotationWithoutUpdate, LocalScalingWithoutUpdate) = value.Decompose();
CalcWorldMatrix(Parent != null ? Parent.Matrix : Matrix4x4.identity, calcWorldMatrix);
}
Matrix4x4 m_matrix = Matrix4x4.Identity;
Matrix4x4 m_matrix = Matrix4x4.identity;
public Matrix4x4 Matrix
{
get => m_matrix;
}
// public void SetMatrixWithoutUpdate(Matrix4x4 m)
// {
// m_matrix = m;
// }
public Quaternion Rotation
{
get
{
return Quaternion.CreateFromRotationMatrix(Matrix);
return Matrix.rotation;
}
set
{
@@ -135,12 +126,7 @@ namespace VrmLib
{
get
{
Matrix4x4 inverted = Matrix4x4.Identity;
if (!Matrix4x4.Invert(Matrix, out inverted))
{
throw new Exception();
}
return inverted;
return Matrix.inverse;
}
}
@@ -148,7 +134,7 @@ namespace VrmLib
{
if (Parent == null)
{
CalcWorldMatrix(Matrix4x4.Identity, calcChildren);
CalcWorldMatrix(Matrix4x4.identity, calcChildren);
}
else
{
@@ -159,15 +145,10 @@ namespace VrmLib
public void CalcWorldMatrix(Matrix4x4 parent, bool calcChildren = true)
{
var value = LocalMatrix * parent;
// if (value == m_matrix) return;
m_matrix = value;
RaiseMatrixUpdated();
// if (float.IsNaN(m_matrix.M11))
// {
// var a = 0;
// }
if (calcChildren)
{
foreach (var child in Children)
@@ -189,7 +170,7 @@ namespace VrmLib
public Vector3 Translation
{
get => Matrix.Translation;
get => Matrix.GetColumn(3);
set
{
if (Parent == null)
@@ -198,8 +179,7 @@ namespace VrmLib
}
else
{
var localPosition = Vector4.Transform(value, Parent.InverseMatrix);
LocalTranslation = new Vector3(localPosition.X, localPosition.Y, localPosition.Z);
LocalTranslation = Parent.InverseMatrix.MultiplyPoint(value);
}
}
}
@@ -318,25 +298,25 @@ namespace VrmLib
public void RotateFromTo(Vector3 worldSrc, Vector3 worldDst)
{
// world to local
var src = Vector3.Transform(Vector3.Normalize(worldSrc), Quaternion.Inverse(Rotation));
var dst = Vector3.Transform(Vector3.Normalize(worldDst), Quaternion.Inverse(Rotation));
var src = Quaternion.Inverse(Rotation) * worldSrc.normalized;
var dst = Quaternion.Inverse(Rotation) * worldDst.normalized;
var dot = Vector3.Dot(src, dst);
Quaternion rot;
if (Math.Abs(1.0f - dot) < float.Epsilon)
{
// 0degree
rot = Quaternion.Identity;
rot = Quaternion.identity;
}
else if (Math.Abs(-1.0f - dot) < float.Epsilon)
{
// 180degree
rot = Quaternion.CreateFromYawPitchRoll(MathFWrap.PI, 0, 0);
rot = Quaternion.Euler(0, MathFWrap.PI, 0);
}
else
{
var axis = Vector3.Normalize(Vector3.Cross(src, dst));
rot = Quaternion.CreateFromAxisAngle(axis, (float)Math.Acos(dot));
rot = Quaternion.AngleAxis((float)Math.Acos(dot), axis);
}
LocalRotation = rot;
@@ -346,11 +326,11 @@ namespace VrmLib
{
if (HumanoidBone.HasValue)
{
return $"{Name}[{HumanoidBone.Value}]: {LocalTranslation.X:0.00}, {LocalTranslation.Y:0.00}, {LocalTranslation.Z:0.00}";
return $"{Name}[{HumanoidBone.Value}]: {LocalTranslation.x:0.00}, {LocalTranslation.y:0.00}, {LocalTranslation.z:0.00}";
}
else
{
return $"{Name}: {LocalTranslation.X:0.00}, {LocalTranslation.Y:0.00}, {LocalTranslation.Z:0.00}";
return $"{Name}: {LocalTranslation.x:0.00}, {LocalTranslation.y:0.00}, {LocalTranslation.z:0.00}";
}
}
}
@@ -371,7 +351,7 @@ namespace VrmLib
public static Vector3 CenterOfDescendant(this Node self)
{
var sum = Vector3.Zero;
var sum = Vector3.zero;
int i = 0;
foreach (var x in self.Traverse())
{

View File

@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.InteropServices;
using UniGLTF;
using UnityEngine;
namespace VrmLib
{

View File

@@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using UniGLTF;
using Unity.Collections;
using UnityEngine;
namespace VrmLib
{
@@ -120,7 +120,7 @@ namespace VrmLib
var j = joints[i];
var w = weights[i];
var sum = (w.X + w.Y + w.Z + w.W);
var sum = (w.x + w.y + w.z + w.w);
float factor;
if (sum > 0)
{
@@ -132,31 +132,31 @@ namespace VrmLib
j = new SkinJoints(m_indexOfRoot, 0, 0, 0);
w = new Vector4(1, 0, 0, 0);
}
if (j.Joint0 == ushort.MaxValue) w.X = 0;
if (j.Joint1 == ushort.MaxValue) w.Y = 0;
if (j.Joint2 == ushort.MaxValue) w.Z = 0;
if (j.Joint3 == ushort.MaxValue) w.W = 0;
if (j.Joint0 == ushort.MaxValue) w.x = 0;
if (j.Joint1 == ushort.MaxValue) w.y = 0;
if (j.Joint2 == ushort.MaxValue) w.z = 0;
if (j.Joint3 == ushort.MaxValue) w.w = 0;
{
var src = new Vector4(position[i], 1); // 位置ベクトル
var dst = Vector4.Zero;
if (w.X > 0) dst += Vector4.Transform(src, m_matrices[j.Joint0]) * w.X * factor;
if (w.Y > 0) dst += Vector4.Transform(src, m_matrices[j.Joint1]) * w.Y * factor;
if (w.Z > 0) dst += Vector4.Transform(src, m_matrices[j.Joint2]) * w.Z * factor;
if (w.W > 0) dst += Vector4.Transform(src, m_matrices[j.Joint3]) * w.W * factor;
dstPosition[i] = new Vector3(dst.X, dst.Y, dst.Z);
var src = position[i]; // 位置ベクトル
var dst = Vector3.zero;
if (w.x > 0) dst += m_matrices[j.Joint0].MultiplyPoint(src) * w.x * factor;
if (w.y > 0) dst += m_matrices[j.Joint1].MultiplyPoint(src) * w.y * factor;
if (w.z > 0) dst += m_matrices[j.Joint2].MultiplyPoint(src) * w.z * factor;
if (w.w > 0) dst += m_matrices[j.Joint3].MultiplyPoint(src) * w.w * factor;
dstPosition[i] = new Vector3(dst.x, dst.y, dst.z);
}
if (useNormal)
{
var normalBuffer = vertexBuffer.Normals;
var normal = normalBuffer != null ? normalBuffer.Bytes.Reinterpret<Vector3>(1) : dstNormal;
var src = new Vector4(normal[i], 0); // 方向ベクトル
var dst = Vector4.Zero;
if (w.X > 0) dst += Vector4.Transform(src, m_matrices[j.Joint0]) * w.X * factor;
if (w.Y > 0) dst += Vector4.Transform(src, m_matrices[j.Joint1]) * w.Y * factor;
if (w.Z > 0) dst += Vector4.Transform(src, m_matrices[j.Joint2]) * w.Z * factor;
if (w.W > 0) dst += Vector4.Transform(src, m_matrices[j.Joint3]) * w.W * factor;
dstNormal[i] = new Vector3(dst.X, dst.Y, dst.Z);
var src = normal[i]; // 方向ベクトル
var dst = Vector3.zero;
if (w.x > 0) dst += m_matrices[j.Joint0].MultiplyVector(src) * w.x * factor;
if (w.y > 0) dst += m_matrices[j.Joint1].MultiplyVector(src) * w.y * factor;
if (w.z > 0) dst += m_matrices[j.Joint2].MultiplyVector(src) * w.z * factor;
if (w.w > 0) dst += m_matrices[j.Joint3].MultiplyVector(src) * w.w * factor;
dstNormal[i] = new Vector3(dst.x, dst.y, dst.z);
}
}
}
@@ -166,10 +166,10 @@ namespace VrmLib
{
// 回転・スケール・しあー
if (
m.M11 == 1 && m.M12 == 0 && m.M13 == 0 && m.M14 == 0
&& m.M21 == 0 && m.M22 == 1 && m.M23 == 0 && m.M24 == 0
&& m.M31 == 0 && m.M32 == 0 && m.M33 == 1 && m.M34 == 0
&& m.M44 == 1
m.m00 == 1 && m.m10 == 0 && m.m20 == 0 && m.m30 == 0
&& m.m01 == 0 && m.m11 == 1 && m.m21 == 0 && m.m31 == 0
&& m.m02 == 0 && m.m12 == 0 && m.m22 == 1 && m.m32 == 0
&& m.m33 == 1
)
{
@@ -179,9 +179,10 @@ namespace VrmLib
return false;
}
if (Math.Abs(m.M41) > 1e-5f) return false;
if (Math.Abs(m.M42) > 1e-5f) return false;
if (Math.Abs(m.M43) > 1e-5f) return false;
// translate
if (Math.Abs(m.m03) > 1e-5f) return false;
if (Math.Abs(m.m13) > 1e-5f) return false;
if (Math.Abs(m.m23) > 1e-5f) return false;
return true;
}
@@ -193,7 +194,7 @@ namespace VrmLib
var sb = new StringBuilder();
var matrices = InverseMatrices.Bytes.Reinterpret<Matrix4x4>(1);
var count = 0;
// var rootMatrix = Matrix4x4.Identity;
// var rootMatrix = Matrix4x4.identity;
// if (Root != null)
// {
// rootMatrix = Root.InverseMatrix;
@@ -241,7 +242,7 @@ namespace VrmLib
// {
// root = Joints[0].Ancestors().Last();
// }
// root.CalcWorldMatrix(Matrix4x4.Identity, true);
// root.CalcWorldMatrix(Matrix4x4.identity, true);
// calc inverse bind matrices
var matricesBytes = arrayManager.CreateNativeArray<Byte>(Marshal.SizeOf(typeof(Matrix4x4)) * Joints.Count);

View File

@@ -1,6 +1,6 @@
using System.Numerics;
using VrmLib;
using NUnit.Framework;
using UnityEngine;
namespace VrmLibTests
{
@@ -12,10 +12,10 @@ namespace VrmLibTests
var root = new Node("root");
var child = new Node("child")
{
LocalTranslation = Vector3.UnitX
LocalTranslation = Vector3.right
};
root.Add(child);
root.LocalTranslation = Vector3.UnitX;
root.LocalTranslation = Vector3.right;
Assert.AreEqual(new Vector3(2, 0, 0), child.Translation);
}

View File

@@ -1,34 +0,0 @@
using System.Numerics;
using VrmLib;
using NUnit.Framework;
using System.IO;
namespace VrmLibTests
{
public class ModelModifierTests
{
[Test]
public void ModifierTest()
{
var model = new Model(Coordinates.Vrm1);
var node0 = new Node("node0");
model.NodeAdd(node0);
Assert.AreEqual(1, model.Nodes.Count);
var node1 = new Node("node1");
model.NodeAdd(node1, node0);
Assert.AreEqual(2, model.Nodes.Count);
// var node2 = new Node("node2");
// model.NodeReplace(node0, node2);
// Assert.AreEqual(2, model.Nodes.Count);
// Assert.AreEqual(node2, model.Nodes[1]);
// Assert.AreEqual(1, node2.Children.Count);
// model.NodeRemove(node1);
// Assert.AreEqual(1, model.Nodes.Count);
// Assert.AreEqual(0, node2.Children.Count);
}
}
}