AxisInverter

This commit is contained in:
ousttrue
2021-02-22 16:21:47 +09:00
parent bd0e79d627
commit 10d17c2e13
6 changed files with 118 additions and 28 deletions

View File

@@ -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();

View File

@@ -0,0 +1,35 @@
using System;
using UnityEngine;
namespace UniGLTF
{
public enum Axises
{
Z,
X,
}
public struct AxisInverter
{
public Func<Vector3, Vector3> InvertVector3;
public Func<Vector4, Vector4> InvertVector4;
public Func<Quaternion, Quaternion> InvertQuaternion;
public Func<Matrix4x4, Matrix4x4> 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(),
};
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b3b7b9629a4da242bacf52f5ca0fd80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -56,6 +56,13 @@ namespace UniGLTF
public IStorage Storage => m_parser.Storage;
#endregion
// configuration
/// <summary>
/// GLTF から Unity に変換するときに反転させる軸
/// </summary>
public Axises InvertAxis = Axises.Z;
#region Load. Build unity objects
public virtual async Awaitable LoadAsync(Func<string, IDisposable> 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

View File

@@ -8,8 +8,6 @@ using UnityEngine;
namespace UniGLTF
{
public class MeshImporter
{
const float FRAME_WEIGHT = 100.0f;
@@ -109,7 +107,7 @@ namespace UniGLTF
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
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<Vector3>(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
/// <param name="ctx"></param>
/// <param name="gltfMesh"></param>
/// <returns></returns>
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<Vector3>(prim.attributes.POSITION).SelectInplace(x => x.ReverseZ()));
m_positions.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.POSITION).SelectInplace(inverter.InvertVector3));
// normal
if (prim.attributes.NORMAL != -1)
{
m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(x => x.ReverseZ()));
m_normals.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector3>(prim.attributes.NORMAL).SelectInplace(inverter.InvertVector3));
}
#if false
// tangent
if (prim.attributes.TANGENT != -1)
{
tangents.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT).SelectInplace(x => x.ReverseZ()));
tangents.AddRange(ctx.GLTF.GetArrayFromAccessor<Vector4>(prim.attributes.TANGENT).SelectInplace(inverter.InvertVector4));
}
#endif
@@ -403,17 +401,17 @@ namespace UniGLTF
if (primTarget.POSITION != -1)
{
blendShape.Positions.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.POSITION), x => x.ReverseZ());
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.POSITION), inverter.InvertVector3);
}
if (primTarget.NORMAL != -1)
{
blendShape.Normals.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), x => x.ReverseZ());
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.NORMAL), inverter.InvertVector3);
}
if (primTarget.TANGENT != -1)
{
blendShape.Tangents.Assign(
ctx.GLTF.GetArrayFromAccessor<Vector3>(primTarget.TANGENT), x => x.ReverseZ());
ctx.GLTF.GetArrayFromAccessor<Vector3>(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);

View File

@@ -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<TransformWithSkin> nodes)
public static void FixCoordinate(ImporterContext context, List<TransformWithSkin> 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<TransformWithSkin> nodes, int i)
public static void SetupSkinning(ImporterContext context, List<TransformWithSkin> nodes, int i, AxisInverter inverter)
{
var x = nodes[i];
var skinnedMeshRenderer = x.Transform.GetComponent<SkinnedMeshRenderer>();
@@ -181,7 +181,7 @@ namespace UniGLTF
if (skin.inverseBindMatrices != -1)
{
var bindPoses = context.GLTF.GetArrayFromAccessor<Matrix4x4>(skin.inverseBindMatrices)
.Select(y => y.ReverseZ())
.Select(inverter.InvertMat4)
.ToArray()
;
mesh.bindposes = bindPoses;