mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-09-30 14:53:09 -05:00
AxisInverter
This commit is contained in:
@@ -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();
|
||||
|
||||
35
Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs
Normal file
35
Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs
Normal 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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
11
Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta
Normal file
11
Assets/UniGLTF/Runtime/UniGLTF/IO/Axises.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b3b7b9629a4da242bacf52f5ca0fd80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user