mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-12 05:48:47 -05:00
Merge pull request #1087 from ousttrue/fix/matrix_extraction
Nodeの行列分解時の負のスケールの限定対応
This commit is contained in:
@@ -180,6 +180,55 @@ namespace UniGLTF
|
||||
return scale;
|
||||
}
|
||||
|
||||
public static bool Nearly(in Matrix4x4 lhs, in Matrix4x4 rhs, float epsilon = 1e-3f)
|
||||
{
|
||||
if (Mathf.Abs(lhs.m00 - rhs.m00) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m01 - rhs.m01) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m02 - rhs.m02) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m03 - rhs.m03) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m10 - rhs.m10) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m11 - rhs.m11) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m12 - rhs.m12) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m13 - rhs.m13) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m20 - rhs.m20) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m21 - rhs.m21) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m22 - rhs.m22) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m23 - rhs.m23) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m30 - rhs.m30) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m31 - rhs.m31) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m32 - rhs.m32) > epsilon) return false;
|
||||
if (Mathf.Abs(lhs.m33 - rhs.m33) > epsilon) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static (Vector3 T, Quaternion R, Vector3 S) Extract(this Matrix4x4 m)
|
||||
{
|
||||
if (m.determinant < 0)
|
||||
{
|
||||
// ミラーリングを試行する
|
||||
|
||||
// -X
|
||||
{
|
||||
var mm = m * Matrix4x4.Scale(new Vector3(-1, 1, 1));
|
||||
var ss = mm.ExtractScale();
|
||||
mm = mm * Matrix4x4.Scale(new Vector3(1 / ss.x, 1 / ss.y, 1 / ss.z));
|
||||
var tt = mm.ExtractPosition();
|
||||
var rr = mm.ExtractRotation();
|
||||
ss.x = -ss.x;
|
||||
var mmm = Matrix4x4.TRS(tt, rr, ss);
|
||||
if (Nearly(m, mmm))
|
||||
{
|
||||
return (tt, rr, ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var s = m.ExtractScale();
|
||||
var t = m.ExtractPosition();
|
||||
var r = m.ExtractRotation();
|
||||
return (t, r, s);
|
||||
}
|
||||
|
||||
public static string RelativePathFrom(this Transform self, Transform root)
|
||||
{
|
||||
var path = new List<String>();
|
||||
|
||||
@@ -50,9 +50,7 @@ namespace UniGLTF
|
||||
if (node.matrix != null && node.matrix.Length > 0)
|
||||
{
|
||||
var m = UnityExtensions.MatrixFromArray(node.matrix);
|
||||
go.transform.localRotation = m.ExtractRotation();
|
||||
go.transform.localPosition = m.ExtractPosition();
|
||||
go.transform.localScale = m.ExtractScale();
|
||||
(go.transform.localPosition, go.transform.localRotation, go.transform.localScale) = m.Extract();
|
||||
}
|
||||
return go;
|
||||
}
|
||||
@@ -158,7 +156,7 @@ namespace UniGLTF
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetupSkinning(glTF gltf, List<TransformWithSkin> nodes, int i, IAxisInverter inverter)
|
||||
public static void SetupSkinning(glTF gltf, List<TransformWithSkin> nodes, int i, IAxisInverter inverter)
|
||||
{
|
||||
var x = nodes[i];
|
||||
var skinnedMeshRenderer = x.Transform.GetComponent<SkinnedMeshRenderer>();
|
||||
|
||||
71
Assets/UniGLTF/Tests/UniGLTF/MatrixTests.cs
Normal file
71
Assets/UniGLTF/Tests/UniGLTF/MatrixTests.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public class MatrixTests
|
||||
{
|
||||
static void AssertFloat(float expected, float value, string template, float epsilon = 1e-5f)
|
||||
{
|
||||
Assert.True(Mathf.Abs(value - expected) < epsilon, string.Format(template, expected, value));
|
||||
}
|
||||
|
||||
static void AssertQuaternion(in Quaternion expected, in Quaternion value, string message)
|
||||
{
|
||||
AssertFloat(expected.x, value.x, $"{message}" + ".X: {0} != {1}");
|
||||
AssertFloat(expected.y, value.y, $"{message}" + ".Y: {0} != {1}");
|
||||
AssertFloat(expected.z, value.z, $"{message}" + ".Z: {0} != {1}");
|
||||
AssertFloat(expected.w, value.w, $"{message}" + ".W: {0} != {1}");
|
||||
}
|
||||
|
||||
static void AssertVec3(in Vector3 expected, in Vector3 value, string message)
|
||||
{
|
||||
AssertFloat(expected.x, value.x, $"{message}" + ".X: {0} != {1}");
|
||||
AssertFloat(expected.y, value.y, $"{message}" + ".Y: {0} != {1}");
|
||||
AssertFloat(expected.z, value.z, $"{message}" + ".Z: {0} != {1}");
|
||||
}
|
||||
|
||||
static void AssertExtract(in Vector3 t, in Quaternion r, in Vector3 s)
|
||||
{
|
||||
var m = Matrix4x4.TRS(t, r, s);
|
||||
var (et, er, es) = m.Extract();
|
||||
AssertVec3(t, et, "T");
|
||||
AssertQuaternion(r, er, "R");
|
||||
AssertVec3(s, es, "S");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtractTest()
|
||||
{
|
||||
AssertExtract(new Vector3(1, 2, 3), Quaternion.Euler(0, 90, -90), new Vector3(1, 2, 3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtractMirror_MinusX()
|
||||
{
|
||||
AssertExtract(new Vector3(1, 2, 3), Quaternion.Euler(0, 90, -90), new Vector3(-1, 2, 3));
|
||||
}
|
||||
|
||||
#if false
|
||||
// TODO:
|
||||
[Test]
|
||||
public void ExtractMirror_MinusY()
|
||||
{
|
||||
|
||||
AssertExtract(new Vector3(1, 2, 3), Quaternion.Euler(0, 90, -90), new Vector3(1, -2, 3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtractMirror_MinusZ()
|
||||
{
|
||||
AssertExtract(new Vector3(1, 2, 3), Quaternion.Euler(0, 90, -90), new Vector3(1, 2, -3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtractMirror_MinusXYZ()
|
||||
{
|
||||
AssertExtract(new Vector3(1, 2, 3), Quaternion.Euler(0, 90, -90), new Vector3(-1, -2, -3));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Assets/UniGLTF/Tests/UniGLTF/MatrixTests.cs.meta
Normal file
11
Assets/UniGLTF/Tests/UniGLTF/MatrixTests.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6f1c95a9487fb44fb4a366eda22bd02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user