From 10d17c2e13c427358be709b87d525727ff12a648 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Mon, 22 Feb 2021 16:21:47 +0900 Subject: [PATCH] AxisInverter --- .../Runtime/Extensions/UnityExtensions.cs | 24 +++++++++++++ Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs | 35 ++++++++++++++++++ .../UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta | 11 ++++++ .../Runtime/UniGLTF/IO/ImporterContext.cs | 28 +++++++++++++-- .../Runtime/UniGLTF/IO/MeshImporter.cs | 36 +++++++++---------- .../Runtime/UniGLTF/IO/NodeImporter.cs | 12 +++---- 6 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta diff --git a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs index 7f0202668..e56fb7729 100644 --- a/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs +++ b/Assets/UniGLTF/Runtime/Extensions/UnityExtensions.cs @@ -45,11 +45,21 @@ namespace UniGLTF return new Vector4(v.x, v.y, -v.z, v.w); } + public static Vector4 ReverseX(this Vector4 v) + { + return new Vector4(-v.x, v.y, v.z, v.w); + } + public static Vector3 ReverseZ(this Vector3 v) { return new Vector3(v.x, v.y, -v.z); } + public static Vector3 ReverseX(this Vector3 v) + { + return new Vector3(-v.x, v.y, v.z); + } + [Obsolete] public static Vector2 ReverseY(this Vector2 v) { @@ -69,6 +79,14 @@ namespace UniGLTF return Quaternion.AngleAxis(-angle, ReverseZ(axis)); } + public static Quaternion ReverseX(this Quaternion q) + { + float angle; + Vector3 axis; + q.ToAngleAxis(out angle, out axis); + return Quaternion.AngleAxis(-angle, ReverseX(axis)); + } + public static Matrix4x4 Matrix4x4FromColumns(Vector4 c0, Vector4 c1, Vector4 c2, Vector4 c3) { #if UNITY_2017_1_OR_NEWER @@ -100,6 +118,12 @@ namespace UniGLTF return m; } + public static Matrix4x4 ReverseX(this Matrix4x4 m) + { + m.SetTRS(m.ExtractPosition().ReverseX(), m.ExtractRotation().ReverseX(), m.ExtractScale()); + return m; + } + public static Matrix4x4 MatrixFromArray(float[] values) { var m = new Matrix4x4(); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs new file mode 100644 index 000000000..9096e708f --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs @@ -0,0 +1,35 @@ +using System; +using UnityEngine; + +namespace UniGLTF +{ + public enum Axises + { + Z, + X, + } + + public struct AxisInverter + { + public Func InvertVector3; + public Func InvertVector4; + public Func InvertQuaternion; + public Func InvertMat4; + + public static AxisInverter ReverseZ => new AxisInverter + { + InvertVector3 = x => x.ReverseZ(), + InvertVector4 = x => x.ReverseZ(), + InvertQuaternion = x => x.ReverseZ(), + InvertMat4 = x => x.ReverseZ(), + }; + + public static AxisInverter ReverseX => new AxisInverter + { + InvertVector3 = x => x.ReverseX(), + InvertVector4 = x => x.ReverseX(), + InvertQuaternion = x => x.ReverseX(), + InvertMat4 = x => x.ReverseX(), + }; + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta new file mode 100644 index 000000000..1af1e98ff --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b3b7b9629a4da242bacf52f5ca0fd80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index 20c1a9631..7151e9c2b 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -56,6 +56,13 @@ namespace UniGLTF public IStorage Storage => m_parser.Storage; #endregion + // configuration + + /// + /// GLTF から Unity に変換するときに反転させる軸 + /// + public Axises InvertAxis = Axises.Z; + #region Load. Build unity objects public virtual async Awaitable LoadAsync(Func MeasureTime = null) { @@ -64,6 +71,21 @@ namespace UniGLTF MeasureTime = new ImporterContextSpeedLog().MeasureTime; } + AxisInverter inverter = default; + switch (InvertAxis) + { + case Axises.Z: + inverter = AxisInverter.ReverseZ; + break; + + case Axises.X: + inverter = AxisInverter.ReverseX; + break; + + default: + throw new NotImplementedException(); + } + if (Root == null) { Root = new GameObject("GLTF"); @@ -85,7 +107,7 @@ namespace UniGLTF var index = i; using (MeasureTime("ReadMesh")) { - var x = meshImporter.ReadMesh(this, index); + var x = meshImporter.ReadMesh(this, index, inverter); var y = await BuildMeshAsync(MeasureTime, x, index); Meshes.Add(y); } @@ -108,12 +130,12 @@ namespace UniGLTF nodes.Add(NodeImporter.BuildHierarchy(this, i)); } - NodeImporter.FixCoordinate(this, nodes); + NodeImporter.FixCoordinate(this, nodes, inverter); // skinning for (int i = 0; i < nodes.Count; ++i) { - NodeImporter.SetupSkinning(this, nodes, i); + NodeImporter.SetupSkinning(this, nodes, i, inverter); } // connect root diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs index 8e7402316..b3490ac34 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs @@ -8,8 +8,6 @@ using UnityEngine; namespace UniGLTF { - - public class MeshImporter { const float FRAME_WEIGHT = 100.0f; @@ -109,7 +107,7 @@ namespace UniGLTF /// /// /// - public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) + public void ImportMeshIndependentVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh, AxisInverter inverter) { foreach (var prim in gltfMesh.primitives) { @@ -119,7 +117,7 @@ namespace UniGLTF // position は必ずある var positions = ctx.GLTF.GetArrayFromAccessor(prim.attributes.POSITION); var fillLength = m_positions.Count; - m_positions.AddRange(positions.Select(x => x.ReverseZ())); + m_positions.AddRange(positions.Select(inverter.InvertVector3)); // normal if (prim.attributes.NORMAL != -1) @@ -130,7 +128,7 @@ namespace UniGLTF throw new Exception("different length"); } FillZero(m_normals, fillLength); - m_normals.AddRange(normals.Select(x => x.ReverseZ())); + m_normals.AddRange(normals.Select(inverter.InvertVector3)); } #if false @@ -142,7 +140,7 @@ namespace UniGLTF throw new Exception("different length"); } FillZero(tangetns, fillLength); - tangents.AddRange(.Select(x => x.ReverseZ())); + tangents.AddRange(.Select(inverter.InvertVector4)); } #endif @@ -242,7 +240,7 @@ namespace UniGLTF throw new Exception("different length"); } FillZero(blendShape.Positions, fillLength); - blendShape.Positions.AddRange(array.Select(x => x.ReverseZ()).ToArray()); + blendShape.Positions.AddRange(array.Select(inverter.InvertVector3).ToArray()); } if (primTarget.NORMAL != -1) { @@ -252,7 +250,7 @@ namespace UniGLTF throw new Exception("different length"); } FillZero(blendShape.Normals, fillLength); - blendShape.Normals.AddRange(array.Select(x => x.ReverseZ()).ToArray()); + blendShape.Normals.AddRange(array.Select(inverter.InvertVector3).ToArray()); } if (primTarget.TANGENT != -1) { @@ -262,7 +260,7 @@ namespace UniGLTF throw new Exception("different length"); } FillZero(blendShape.Tangents, fillLength); - blendShape.Tangents.AddRange(array.Select(x => x.ReverseZ()).ToArray()); + blendShape.Tangents.AddRange(array.Select(inverter.InvertVector3).ToArray()); } m_blendShapes.Add(blendShape); } @@ -293,24 +291,24 @@ namespace UniGLTF /// /// /// - public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh) + public void ImportMeshSharingVertexBuffer(ImporterContext ctx, glTFMesh gltfMesh, AxisInverter inverter) { { // 同じVertexBufferを共有しているので先頭のモノを使う var prim = gltfMesh.primitives.First(); - m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ())); + m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3)); // normal if (prim.attributes.NORMAL != -1) { - m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ())); + m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3)); } #if false // tangent if (prim.attributes.TANGENT != -1) { - tangents.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ())); + tangents.AddRange(ctx.GLTF.GetArrayFromAccessor(prim.attributes.TANGENT).SelectInplace(inverter.InvertVector4)); } #endif @@ -403,17 +401,17 @@ namespace UniGLTF if (primTarget.POSITION != -1) { blendShape.Positions.Assign( - ctx.GLTF.GetArrayFromAccessor(primTarget.POSITION), x => x.ReverseZ()); + ctx.GLTF.GetArrayFromAccessor(primTarget.POSITION), inverter.InvertVector3); } if (primTarget.NORMAL != -1) { blendShape.Normals.Assign( - ctx.GLTF.GetArrayFromAccessor(primTarget.NORMAL), x => x.ReverseZ()); + ctx.GLTF.GetArrayFromAccessor(primTarget.NORMAL), inverter.InvertVector3); } if (primTarget.TANGENT != -1) { blendShape.Tangents.Assign( - ctx.GLTF.GetArrayFromAccessor(primTarget.TANGENT), x => x.ReverseZ()); + ctx.GLTF.GetArrayFromAccessor(primTarget.TANGENT), inverter.InvertVector3); } } } @@ -509,18 +507,18 @@ namespace UniGLTF return sharedAttributes; } - public MeshContext ReadMesh(ImporterContext ctx, int meshIndex) + public MeshContext ReadMesh(ImporterContext ctx, int meshIndex, AxisInverter inverter) { var gltfMesh = ctx.GLTF.meshes[meshIndex]; var meshContext = new MeshContext(gltfMesh.name, meshIndex); if (HasSharedVertexBuffer(gltfMesh)) { - meshContext.ImportMeshSharingVertexBuffer(ctx, gltfMesh); + meshContext.ImportMeshSharingVertexBuffer(ctx, gltfMesh, inverter); } else { - meshContext.ImportMeshIndependentVertexBuffer(ctx, gltfMesh); + meshContext.ImportMeshIndependentVertexBuffer(ctx, gltfMesh, inverter); } meshContext.RenameBlendShape(gltfMesh); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/NodeImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/NodeImporter.cs index b0782b1fa..da02b9272 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/NodeImporter.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/NodeImporter.cs @@ -16,7 +16,7 @@ namespace UniGLTF Debug.LogWarningFormat("node {0} contains /. replace _", node.name); nodeName = nodeName.Replace("/", "_"); } - if(string.IsNullOrEmpty(nodeName)) + if (string.IsNullOrEmpty(nodeName)) { nodeName = string.Format("nodeIndex_{0}", nodeIndex); } @@ -131,7 +131,7 @@ namespace UniGLTF // // fix node's coordinate. z-back to z-forward // - public static void FixCoordinate(ImporterContext context, List nodes) + public static void FixCoordinate(ImporterContext context, List nodes, AxisInverter inverter) { var globalTransformMap = nodes.ToDictionary(x => x.Transform, x => new PosRot { @@ -148,13 +148,13 @@ namespace UniGLTF foreach (var transform in t.Traverse()) { var g = globalTransformMap[transform]; - transform.position = g.Position.ReverseZ(); - transform.rotation = g.Rotation.ReverseZ(); + transform.position = inverter.InvertVector3(g.Position); + transform.rotation = inverter.InvertQuaternion(g.Rotation); } } } - public static void SetupSkinning(ImporterContext context, List nodes, int i) + public static void SetupSkinning(ImporterContext context, List nodes, int i, AxisInverter inverter) { var x = nodes[i]; var skinnedMeshRenderer = x.Transform.GetComponent(); @@ -181,7 +181,7 @@ namespace UniGLTF if (skin.inverseBindMatrices != -1) { var bindPoses = context.GLTF.GetArrayFromAccessor(skin.inverseBindMatrices) - .Select(y => y.ReverseZ()) + .Select(inverter.InvertMat4) .ToArray() ; mesh.bindposes = bindPoses;