using GLTF;
using GLTF.Schema;
using Unity.Mathematics;
using UnityEngine;
namespace UnityGLTF.Extensions
{
public static class SchemaExtensions
{
///
/// Define the transformation between Unity coordinate space and glTF.
/// glTF is a right-handed coordinate system, where the 'right' direction is -X relative to
/// Unity's coordinate system.
/// glTF matrix: column vectors, column-major storage, +Y up, +Z forward, -X right, right-handed
/// unity matrix: column vectors, column-major storage, +Y up, +Z forward, +X right, left-handed
/// multiply by a negative X scale to convert handedness
///
public static readonly GLTF.Math.Vector3 CoordinateSpaceConversionScale = new GLTF.Math.Vector3(-1, 1, 1);
///
/// Define whether the coordinate space scale conversion above means we have a change in handedness.
/// This is used when determining the conventional direction of rotation - the right-hand rule states
/// that rotations are clockwise in left-handed systems and counter-clockwise in right-handed systems.
/// Reversing the direction of one or three axes of reverses the handedness.
///
public static bool CoordinateSpaceConversionRequiresHandednessFlip
{
get
{
return CoordinateSpaceConversionScale.X * CoordinateSpaceConversionScale.Y * CoordinateSpaceConversionScale.Z < 0.0f;
}
}
public static readonly GLTF.Math.Vector4 TangentSpaceConversionScale = new GLTF.Math.Vector4(-1, 1, 1, -1);
///
/// Get the converted unity translation, rotation, and scale from a gltf node
///
/// gltf node
/// unity translation vector
/// unity rotation quaternion
/// unity scale vector
public static void GetUnityTRSProperties(this Node node, out Vector3 position, out Quaternion rotation,
out Vector3 scale)
{
if (!node.UseTRS)
{
Matrix4x4 unityMat = node.Matrix.ToUnityMatrix4x4Convert();
unityMat.GetTRSProperties(out position, out rotation, out scale);
}
else
{
position = node.Translation.ToUnityVector3Convert();
rotation = node.Rotation.ToUnityQuaternionConvert();
scale = node.Scale.ToUnityVector3Raw();
}
}
internal static readonly Quaternion InvertDirection = new Quaternion(0, -1, 0, 0);
///
/// Set a gltf node's converted translation, rotation, and scale from a unity transform
///
/// gltf node to modify
/// unity transform to convert
/// invert look direction (e.g. for lights and cameras)
public static void SetUnityTransform(this Node node, Transform transform, bool invertLookDirection)
{
node.Translation = transform.localPosition.ToGltfVector3Convert();
node.Rotation = (transform.localRotation * (invertLookDirection ? InvertDirection : Quaternion.identity)).ToGltfQuaternionConvert();
node.Scale = transform.localScale.ToGltfVector3Raw();
}
// todo: move to utility class
///
/// Get unity translation, rotation, and scale from a unity matrix
///
/// unity matrix to get properties from
/// unity translation vector
/// unity rotation quaternion
/// unity scale vector
public static void GetTRSProperties(this Matrix4x4 mat, out Vector3 position, out Quaternion rotation,
out Vector3 scale)
{
position = mat.GetColumn(3);
Vector3 x = mat.GetColumn(0);
Vector3 y = mat.GetColumn(1);
Vector3 z = mat.GetColumn(2);
Vector3 calculatedZ = Vector3.Cross(x, y);
bool mirrored = Vector3.Dot(calculatedZ, z) < 0.0f;
scale = new Vector3(x.magnitude * (mirrored ? -1.0f : 1.0f), y.magnitude, z.magnitude);
rotation = Quaternion.LookRotation(mat.GetColumn(2), mat.GetColumn(1));
}
///
/// Get converted unity translation, rotation, and scale from a gltf matrix
///
/// gltf matrix to get and convert properties from
/// unity translation vector
/// unity rotation quaternion
/// unity scale vector
public static void GetTRSProperties(this GLTF.Math.Matrix4x4 gltfMat, out Vector3 position, out Quaternion rotation,
out Vector3 scale)
{
gltfMat.ToUnityMatrix4x4Convert().GetTRSProperties(out position, out rotation, out scale);
}
///
/// Get a gltf column vector from a gltf matrix
///
/// gltf matrix
/// the specified column vector from the matrix
///
public static GLTF.Math.Vector4 GetColumn(this GLTF.Math.Matrix4x4 mat, uint columnNum)
{
switch (columnNum)
{
case 0:
{
return new GLTF.Math.Vector4(mat.M11, mat.M21, mat.M31, mat.M41);
}
case 1:
{
return new GLTF.Math.Vector4(mat.M12, mat.M22, mat.M32, mat.M42);
}
case 2:
{
return new GLTF.Math.Vector4(mat.M13, mat.M23, mat.M33, mat.M43);
}
case 3:
{
return new GLTF.Math.Vector4(mat.M14, mat.M24, mat.M34, mat.M44);
}
default:
throw new System.Exception("column num is out of bounds");
}
}
///
/// Convert gltf quaternion to a unity quaternion
///
/// gltf quaternion
/// unity quaternion
public static Quaternion ToUnityQuaternionConvert(this GLTF.Math.Quaternion gltfQuat)
{
Vector3 fromAxisOfRotation = new Vector3(gltfQuat.X, gltfQuat.Y, gltfQuat.Z);
float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
Vector3 toAxisOfRotation = axisFlipScale * Vector3.Scale(fromAxisOfRotation, CoordinateSpaceConversionScale.ToUnityVector3Raw());
return new Quaternion(toAxisOfRotation.x, toAxisOfRotation.y, toAxisOfRotation.z, gltfQuat.W);
}
public static Quaternion ToUnityQuaternionConvert(this quaternion quat)
{
Vector3 fromAxisOfRotation = new Vector3(quat.value.x, quat.value.y, quat.value.z);
float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
Vector3 toAxisOfRotation = axisFlipScale * Vector3.Scale(fromAxisOfRotation, CoordinateSpaceConversionScale.ToUnityVector3Raw());
return new Quaternion(toAxisOfRotation.x, toAxisOfRotation.y, toAxisOfRotation.z, quat.value.w);
}
public static Quaternion ToUnityQuaternionConvert(this float4 quat)
{
Vector3 fromAxisOfRotation = new Vector3(quat.x, quat.y, quat.z);
float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
Vector3 toAxisOfRotation = axisFlipScale * Vector3.Scale(fromAxisOfRotation, CoordinateSpaceConversionScale.ToUnityVector3Raw());
return new Quaternion(toAxisOfRotation.x, toAxisOfRotation.y, toAxisOfRotation.z, quat.w);
}
///
/// Convert unity quaternion to a gltf quaternion
///
/// unity quaternion
/// gltf quaternion
public static GLTF.Math.Quaternion ToGltfQuaternionConvert(this Quaternion unityQuat)
{
Vector3 fromAxisOfRotation = new Vector3(unityQuat.x, unityQuat.y, unityQuat.z);
float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
Vector3 toAxisOfRotation = axisFlipScale * Vector3.Scale(fromAxisOfRotation, CoordinateSpaceConversionScale.ToUnityVector3Raw());
return new GLTF.Math.Quaternion(toAxisOfRotation.x, toAxisOfRotation.y, toAxisOfRotation.z, unityQuat.w);
}
///
/// Convert gltf matrix to a unity matrix
///
/// gltf matrix
/// unity matrix
public static Matrix4x4 ToUnityMatrix4x4Convert(this GLTF.Math.Matrix4x4 gltfMat)
{
Matrix4x4 rawUnityMat = gltfMat.ToUnityMatrix4x4Raw();
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
Matrix4x4 convert = Matrix4x4.Scale(coordinateSpaceConversionScale);
Matrix4x4 unityMat = convert * rawUnityMat * convert;
return unityMat;
}
///
/// Convert gltf matrix to a unity matrix
///
/// gltf matrix
/// unity matrix
public static Matrix4x4 ToUnityMatrix4x4Convert(this float4x4 gltfMat)
{
Matrix4x4 rawUnityMat = gltfMat.ToUnityMatrix4x4Raw();
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
Matrix4x4 convert = Matrix4x4.Scale(coordinateSpaceConversionScale);
Matrix4x4 unityMat = convert * rawUnityMat * convert;
return unityMat;
}
///
/// Convert gltf matrix to a unity matrix
///
/// unity matrix
/// gltf matrix
public static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Convert(this Matrix4x4 unityMat)
{
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
Matrix4x4 convert = Matrix4x4.Scale(coordinateSpaceConversionScale);
GLTF.Math.Matrix4x4 gltfMat = (convert * unityMat * convert).ToGltfMatrix4x4Raw();
return gltfMat;
}
///
/// Convert gltf Vector3 to unity Vector3
///
/// gltf vector3
/// unity vector3
public static Vector3 ToUnityVector3Convert(this GLTF.Math.Vector3 gltfVec3)
{
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
Vector3 unityVec3 = Vector3.Scale(gltfVec3.ToUnityVector3Raw(), coordinateSpaceConversionScale);
return unityVec3;
}
///
/// Convert gltf Vector3 to unity Vector3
///
/// gltf vector3
/// unity vector3
public static Vector3 ToUnityVector3Convert(this float3 gltfVec3)
{
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
Vector3 unityVec3 = Vector3.Scale(gltfVec3.ToUnityVector3Raw(), coordinateSpaceConversionScale);
return unityVec3;
}
public static float3 ToUnityFloat3Convert(this float3 gltfVec3)
{
float3 coordinateSpaceConversionScale = new float3(CoordinateSpaceConversionScale.X, CoordinateSpaceConversionScale.Y, CoordinateSpaceConversionScale.Z);
float3 unityVec3 = gltfVec3 * coordinateSpaceConversionScale;
return unityVec3;
}
public static void ToUnityVector3Convert(this float3[] vec3, Vector3[] arr, int offset)
{
float3 conversion = new float3(CoordinateSpaceConversionScale.X,
CoordinateSpaceConversionScale.Y,
CoordinateSpaceConversionScale.Z);
for (int i = 0; i < vec3.Length; i++)
{
arr[i+offset] = vec3[i] * conversion;
}
}
///
/// Convert unity Vector3 to gltf Vector3
///
/// unity Vector3
/// gltf Vector3
public static GLTF.Math.Vector3 ToGltfVector3Convert(this Vector3 unityVec3)
{
Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
GLTF.Math.Vector3 gltfVec3 = Vector3.Scale(unityVec3, coordinateSpaceConversionScale).ToGltfVector3Raw();
return gltfVec3;
}
public static GLTF.Math.Vector3 ToGltfVector3Raw(this Vector3 unityVec3)
{
GLTF.Math.Vector3 gltfVec3 = new GLTF.Math.Vector3(unityVec3.x, unityVec3.y, unityVec3.z);
return gltfVec3;
}
public static GLTF.Math.Vector4 ToGltfVector4Raw(this Vector4 unityVec4)
{
GLTF.Math.Vector4 gltfVec4 = new GLTF.Math.Vector4(unityVec4.x, unityVec4.y, unityVec4.z, unityVec4.w);
return gltfVec4;
}
public static Matrix4x4 ToUnityMatrix4x4Raw(this GLTF.Math.Matrix4x4 gltfMat)
{
Vector4 rawUnityCol0 = gltfMat.GetColumn(0).ToUnityVector4Raw();
Vector4 rawUnityCol1 = gltfMat.GetColumn(1).ToUnityVector4Raw();
Vector4 rawUnityCol2 = gltfMat.GetColumn(2).ToUnityVector4Raw();
Vector4 rawUnityCol3 = gltfMat.GetColumn(3).ToUnityVector4Raw();
Matrix4x4 rawUnityMat = new UnityEngine.Matrix4x4();
rawUnityMat.SetColumn(0, rawUnityCol0);
rawUnityMat.SetColumn(1, rawUnityCol1);
rawUnityMat.SetColumn(2, rawUnityCol2);
rawUnityMat.SetColumn(3, rawUnityCol3);
return rawUnityMat;
}
public static Matrix4x4 ToUnityMatrix4x4Raw(this float4x4 gltfMat)
{
Vector4 rawUnityCol0 = gltfMat.c0.ToUnityVector4Raw();
Vector4 rawUnityCol1 = gltfMat.c1.ToUnityVector4Raw();
Vector4 rawUnityCol2 = gltfMat.c2.ToUnityVector4Raw();
Vector4 rawUnityCol3 = gltfMat.c3.ToUnityVector4Raw();
Matrix4x4 rawUnityMat = new UnityEngine.Matrix4x4();
rawUnityMat.SetColumn(0, rawUnityCol0);
rawUnityMat.SetColumn(1, rawUnityCol1);
rawUnityMat.SetColumn(2, rawUnityCol2);
rawUnityMat.SetColumn(3, rawUnityCol3);
return rawUnityMat;
}
public static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Raw(this Matrix4x4 unityMat)
{
GLTF.Math.Vector4 c0 = unityMat.GetColumn(0).ToGltfVector4Raw();
GLTF.Math.Vector4 c1 = unityMat.GetColumn(1).ToGltfVector4Raw();
GLTF.Math.Vector4 c2 = unityMat.GetColumn(2).ToGltfVector4Raw();
GLTF.Math.Vector4 c3 = unityMat.GetColumn(3).ToGltfVector4Raw();
GLTF.Math.Matrix4x4 rawGltfMat = new GLTF.Math.Matrix4x4(c0.X, c0.Y, c0.Z, c0.W, c1.X, c1.Y, c1.Z, c1.W, c2.X, c2.Y, c2.Z, c2.W, c3.X, c3.Y, c3.Z, c3.W);
return rawGltfMat;
}
public static Vector2 ToUnityVector2Raw(this GLTF.Math.Vector2 vec2)
{
return new Vector2(vec2.X, vec2.Y);
}
public static Vector2 ToUnityVector2Raw(this float2 vec2)
{
return new Vector2(vec2.x, vec2.y);
}
public static Vector2[] ToUnityVector2Raw(this GLTF.Math.Vector2[] inVecArr)
{
Vector2[] outVecArr = new Vector2[inVecArr.Length];
for (int i = 0; i < inVecArr.Length; ++i)
{
outVecArr[i] = inVecArr[i].ToUnityVector2Raw();
}
return outVecArr;
}
public static Vector2[] ToUnityVector2Raw(this float2[] vec2)
{
var r = new Vector2[vec2.Length];
for (int i = 0; i < vec2.Length; i++)
{
r[i] = vec2[i].ToUnityVector2Raw();
}
return r;
}
public static void ToUnityVector2Raw(this float2[] vec2, Vector2[] arr, int offset)
{
for (int i = 0; i < vec2.Length; i++)
{
arr[i+offset] = vec2[i].ToUnityVector2Raw();
}
}
public static Vector3 ToUnityVector3Raw(this GLTF.Math.Vector3 vec3)
{
return new Vector3(vec3.X, vec3.Y, vec3.Z);
}
public static Vector3 ToUnityVector3Raw(this float3 vec3)
{
return new Vector3(vec3.x, vec3.y, vec3.z);
}
public static Vector3[] ToUnityVector3Raw(this float3[] vec3)
{
var r = new Vector3[vec3.Length];
for (int i = 0; i < vec3.Length; i++)
{
r[i] = vec3[i].ToUnityVector3Raw();
}
return r;
}
public static void ToUnityVector3Raw(this float3[] vec3, Vector3[] arr, int offset)
{
for (int i = 0; i < vec3.Length; i++)
{
arr[i+offset] = vec3[i].ToUnityVector3Raw();
}
}
public static Vector4 ToUnityVector4Raw(this GLTF.Math.Vector4 vec4)
{
return new Vector4(vec4.X, vec4.Y, vec4.Z, vec4.W);
}
public static Vector4 ToUnityVector4Raw(this float4 vec4)
{
return new Vector4(vec4.x, vec4.y, vec4.z, vec4.w);
}
public static Vector4[] ToUnityVector4Raw(this float4[] vec4)
{
var r = new Vector4[vec4.Length];
for (int i = 0; i < vec4.Length; i++)
{
r[i] = vec4[i].ToUnityVector4Raw();
}
return r;
}
public static void ToUnityVector4Raw(this float4[] vec4, Vector4[] arr, int offset)
{
for (int i = 0; i < vec4.Length; i++)
{
arr[i+offset] = vec4[i].ToUnityVector4Raw();
}
}
public static UnityEngine.Color ToUnityColorRaw(this GLTF.Math.Color color)
{
var c = new UnityEngine.Color(color.R, color.G, color.B, color.A).gamma;
return c;
}
public static void ToUnityColorRaw(this float4[] inArr, Color[] outArr, int offset)
{
for (int i = 0; i < inArr.Length; i++)
{
outArr[i + offset] = inArr[i].ToUnityColorRaw();
}
}
public static UnityEngine.Color ToUnityColorRaw(this float4 color)
{
var c = new UnityEngine.Color(color.x, color.y, color.z, color.w).gamma;
return c;
}
public static UnityEngine.Color ToUnityColorLinear(this GLTF.Math.Color color)
{
var c = new UnityEngine.Color(color.R, color.G, color.B, color.A);
return c;
}
public static void ToUnityColorLinear(this float4[] inArr, Color[] outArr, int offset)
{
for (int i = 0; i < inArr.Length; i++)
{
outArr[i + offset] = inArr[i].ToUnityColorLinear();
}
}
public static UnityEngine.Color ToUnityColorLinear(this float4 color)
{
var c = new UnityEngine.Color(color.x, color.y, color.z, color.w);
return c;
}
public static UnityEngine.Color ToUnityColorGamma(this GLTF.Math.Color color)
{
var c = new UnityEngine.Color(color.R, color.G, color.B, color.A).linear;
return c;
}
public static GLTF.Math.Color ToNumericsColorRaw(this UnityEngine.Color color)
{
var c = color;
return new GLTF.Math.Color(c.r, c.g, c.b, c.a);
}
public static GLTF.Math.Color ToNumericsColorLinear(this UnityEngine.Color color)
{
var lc = color.linear;
return new GLTF.Math.Color(lc.r, lc.g, lc.b, lc.a);
}
public static GLTF.Math.Color ToNumericsColorGamma(this UnityEngine.Color color)
{
var lc = color.gamma;
return new GLTF.Math.Color(lc.r, lc.g, lc.b, lc.a);
}
public static GLTF.Math.Color[] ToNumericsColorLinear(this UnityEngine.Color[] inColorArr)
{
GLTF.Math.Color[] outColorArr = new GLTF.Math.Color[inColorArr.Length];
for (int i = 0; i < inColorArr.Length; ++i)
{
outColorArr[i] = inColorArr[i].ToNumericsColorLinear();
}
return outColorArr;
}
public static UnityEngine.Color[] ToLinear(this UnityEngine.Color[] inColorArr)
{
UnityEngine.Color[] outColorArr = new UnityEngine.Color[inColorArr.Length];
for (int i = 0; i < inColorArr.Length; ++i)
{
outColorArr[i] = inColorArr[i].linear;
}
return outColorArr;
}
public static void ToUnityColorRaw(this GLTF.Math.Color[] inArr, Color[] outArr, int offset = 0)
{
for (int i = 0; i < inArr.Length; i++)
{
outArr[offset + i] = inArr[i].ToUnityColorRaw();
}
}
public static void ToUnityColorLinear(this GLTF.Math.Color[] inArr, Color[] outArr, int offset = 0)
{
for (int i = 0; i < inArr.Length; i++)
{
outArr[offset + i] = inArr[i].ToUnityColorLinear();
}
}
public static int[] ToIntArrayRaw(this uint[] uintArr)
{
int[] intArr = new int[uintArr.Length];
for (int i = 0; i < uintArr.Length; ++i)
{
uint uintVal = uintArr[i];
Debug.Assert(uintVal <= int.MaxValue);
intArr[i] = (int)uintVal;
}
return intArr;
}
public static GLTF.Math.Quaternion ToGltfQuaternionRaw(this Quaternion unityQuat)
{
return new GLTF.Math.Quaternion(unityQuat.x, unityQuat.y, unityQuat.z, unityQuat.w);
}
public static Quaternion ToUnityQuaternionRaw(this quaternion quaternion)
{
return new Quaternion(quaternion.value.x, quaternion.value.y, quaternion.value.z, quaternion.value.w);
}
public static Quaternion ToUnityQuaternionRaw(this float4 quaternion)
{
return new Quaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
}
///
/// Flips the V component of the UV (1-V) to put from glTF into Unity space
///
/// The attribute accessor to modify
public static void FlipTexCoordArrayV(ref AttributeAccessor attributeAccessor)
{
for (var i = 0; i < attributeAccessor.AccessorContent.AsFloat2s.Length; i++)
{
attributeAccessor.AccessorContent.AsFloat2s[i].y = 1.0f - attributeAccessor.AccessorContent.AsFloat2s[i].y;
}
}
///
/// Flip the V component of the UV (1-V)
///
/// The array to copy from and modify
/// Copied Vector2 with coordinates in glTF space
public static UnityEngine.Vector2[] FlipTexCoordArrayVAndCopy(UnityEngine.Vector2[] array)
{
var returnArray = new UnityEngine.Vector2[array.Length];
for (var i = 0; i < array.Length; i++)
{
returnArray[i].x = array[i].x;
returnArray[i].y = 1.0f - array[i].y;
}
return returnArray;
}
///
/// Converts vector3 to specified coordinate space
///
/// The attribute accessor to modify
/// The coordinate space to move into
public static void ConvertVector3CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
{
for (int i = 0; i < attributeAccessor.AccessorContent.AsFloat3s.Length; i++)
{
attributeAccessor.AccessorContent.AsFloat3s[i].x *= coordinateSpaceCoordinateScale.X;
attributeAccessor.AccessorContent.AsFloat3s[i].y *= coordinateSpaceCoordinateScale.Y;
attributeAccessor.AccessorContent.AsFloat3s[i].z *= coordinateSpaceCoordinateScale.Z;
}
}
///
/// Converts and copies based on the specified coordinate scale
///
/// The array to convert and copy
/// The specified coordinate space
/// The copied and converted coordinate space
public static UnityEngine.Vector3[] ConvertVector3CoordinateSpaceAndCopy(Vector3[] array, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
{
var returnArray = new UnityEngine.Vector3[array.Length];
var coordinateScale = coordinateSpaceCoordinateScale.ToUnityVector3Raw();
for (int i = 0; i < array.Length; i++)
{
returnArray[i] = array[i];
returnArray[i].Scale(coordinateScale);
}
return returnArray;
}
///
/// Converts vector4 to specified coordinate space
///
/// The attribute accessor to modify
/// The coordinate space to move into
public static void ConvertVector4CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
{
for (int i = 0; i < attributeAccessor.AccessorContent.AsFloat4s.Length; i++)
{
attributeAccessor.AccessorContent.AsFloat4s[i].x *= coordinateSpaceCoordinateScale.X;
attributeAccessor.AccessorContent.AsFloat4s[i].y *= coordinateSpaceCoordinateScale.Y;
attributeAccessor.AccessorContent.AsFloat4s[i].z *= coordinateSpaceCoordinateScale.Z;
attributeAccessor.AccessorContent.AsFloat4s[i].w *= coordinateSpaceCoordinateScale.W;
}
}
///
/// Converts and copies based on the specified coordinate scale
///
/// The array to convert and copy
/// The specified coordinate space
/// The copied and converted coordinate space
public static Vector4[] ConvertVector4CoordinateSpaceAndCopy(Vector4[] array, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
{
var returnArray = new Vector4[array.Length];
var coordinateScale = coordinateSpaceCoordinateScale.ToUnityVector4Raw();
for (var i = 0; i < array.Length; i++)
{
returnArray[i] = array[i];
returnArray[i].Scale(coordinateScale);
}
return returnArray;
}
///
/// Converts and copies based on the specified coordinate scale. Also verify the tangent.w component to be -1 or 1
///
/// The array to convert and copy
/// The specified coordinate space
/// The copied and converted coordinate space
public static Vector4[] ConvertTangentCoordinateSpaceAndCopy(Vector4[] array, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
{
var returnArray = new Vector4[array.Length];
var coordinateScale = coordinateSpaceCoordinateScale.ToUnityVector4Raw();
for (var i = 0; i < array.Length; i++)
{
returnArray[i] = array[i];
returnArray[i].w = Mathf.Sign(returnArray[i].w);
returnArray[i].Scale(coordinateScale);
}
return returnArray;
}
///
/// Rewinds the indicies into Unity coordinate space from glTF space
///
/// The attribute accessor to modify
public static void FlipTriangleFaces(int[] indices)
{
for (int i = 0; i < indices.Length; i += 3)
{
int temp = indices[i];
indices[i] = indices[i + 2];
indices[i + 2] = temp;
}
}
public static Matrix4x4 ToUnityMatrix4x4(this GLTF.Math.Matrix4x4 matrix)
{
return new Matrix4x4()
{
m00 = matrix.M11,
m01 = matrix.M12,
m02 = matrix.M13,
m03 = matrix.M14,
m10 = matrix.M21,
m11 = matrix.M22,
m12 = matrix.M23,
m13 = matrix.M24,
m20 = matrix.M31,
m21 = matrix.M32,
m22 = matrix.M33,
m23 = matrix.M34,
m30 = matrix.M41,
m31 = matrix.M42,
m32 = matrix.M43,
m33 = matrix.M44
};
}
public static Matrix4x4[] ToUnityMatrix4x4(this GLTF.Math.Matrix4x4[] inMatrixArr)
{
Matrix4x4[] outMatrixArr = new Matrix4x4[inMatrixArr.Length];
for (int i = 0; i < inMatrixArr.Length; ++i)
{
outMatrixArr[i] = inMatrixArr[i].ToUnityMatrix4x4();
}
return outMatrixArr;
}
public static Quaternion SwitchHandedness(this Quaternion input)
{
return new Quaternion(-input.x, input.y, input.z, -input.w);
}
/*
public static Vector4 SwitchHandedness(this Vector4 input)
{
return new Vector4(-input.x, input.y, input.z, -input.w);
}
public static Matrix4x4 SwitchHandedness(this Matrix4x4 matrix)
{
Vector3 position = matrix.GetColumn(3).SwitchHandedness();
Quaternion rotation = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1)).SwitchHandedness();
Vector3 scale = new Vector3(matrix.GetColumn(0).magnitude, matrix.GetColumn(1).magnitude, matrix.GetColumn(2).magnitude);
float epsilon = 0.00001f;
// Some issues can occurs with non uniform scales
if (Mathf.Abs(scale.x - scale.y) > epsilon || Mathf.Abs(scale.y - scale.z) > epsilon || Mathf.Abs(scale.x - scale.z) > epsilon)
{
Debug.LogWarning("A matrix with non uniform scale is being converted from left to right handed system. This code is not working correctly in this case");
}
// Handle negative scale component in matrix decomposition
if (Matrix4x4.Determinant(matrix) < 0)
{
Quaternion rot = Quaternion.LookRotation(matrix.GetColumn(2), matrix.GetColumn(1));
Matrix4x4 corr = Matrix4x4.TRS(matrix.GetColumn(3), rot, Vector3.one).inverse;
Matrix4x4 extractedScale = corr * matrix;
scale = new Vector3(extractedScale.m00, extractedScale.m11, extractedScale.m22);
}
// convert transform values from left handed to right handed
return Matrix4x4.TRS(position, rotation, scale);
}
*/
}
}