diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs index fdbaff4c0..54bf0874f 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ImporterContext.cs @@ -70,8 +70,6 @@ namespace UniGLTF { // https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_draco_mesh_compression "KHR_draco_mesh_compression", - // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization - "KHR_mesh_quantization", }; #region Load. Build unity objects diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs index c6ce9a551..17f5fe0c5 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs @@ -14,31 +14,124 @@ namespace UniGLTF public static NativeArray GetPositions(this glTFPrimitives primitives, GltfData data) { - return data.GetArrayFromAccessor(primitives.attributes.POSITION); + var accessor = data.GLTF.accessors[primitives.attributes.POSITION]; + if (accessor.type != "VEC3") + { + throw new ArgumentException($"unknown POSITION type: {accessor.componentType}:{accessor.type}"); + } + + if (accessor.componentType == glComponentType.FLOAT) + { + return data.GetArrayFromAccessor(primitives.attributes.POSITION); + } + else if (accessor.componentType == glComponentType.UNSIGNED_SHORT) + { + // KHR_mesh_quantization + // not UShort3 for 4byte alignment ! + var src = data.GetArrayFromAccessor(primitives.attributes.POSITION); + var array = data.NativeArrayManager.CreateNativeArray(src.Length); + for (int i = 0; i < src.Length; ++i) + { + var v = src[i]; + array[i] = new Vector3(v.x, v.y, v.z); + } + return array; + } + else + { + throw new NotImplementedException($"unknown POSITION type: {accessor.componentType}:{accessor.type}"); + } } public static NativeArray? GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength) { if (!HasNormal(primitives)) return null; - var result = data.GetArrayFromAccessor(primitives.attributes.NORMAL); - if (result.Length != positionsLength) + + var accessor = data.GLTF.accessors[primitives.attributes.NORMAL]; + if (accessor.type != "VEC3") { - throw new Exception("different length"); + throw new ArgumentException($"unknown NORMAL type: {accessor.componentType}:{accessor.type}"); } - return result; + if (accessor.componentType == glComponentType.FLOAT) + { + var result = data.GetArrayFromAccessor(primitives.attributes.NORMAL); + if (result.Length != positionsLength) + { + throw new Exception("NORMAL is different in length from POSITION"); + } + return result; + } + else if (accessor.componentType == glComponentType.BYTE) + { + // KHR_mesh_quantization + // not Byte3 for 4byte alignment ! + var src = data.GetArrayFromAccessor(primitives.attributes.NORMAL); + var array = data.NativeArrayManager.CreateNativeArray(src.Length); + if (accessor.normalized) + { + var factor = 1.0f / 127.0f; + for (int i = 0; i < src.Length; ++i) + { + var v = src[i]; + array[i] = new Vector3( + v.x * factor, + v.y * factor, + v.z * factor); + } + } + else + { + for (int i = 0; i < src.Length; ++i) + { + var v = src[i]; + array[i] = new Vector3(v.x, v.y, v.z); + } + } + return array; + } + else + { + throw new NotImplementedException($"unknown NORMAL type: {accessor.componentType}:{accessor.type}"); + } } public static NativeArray? GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength) { if (!HasTexCoord0(primitives)) return null; - var result = data.GetArrayFromAccessor(primitives.attributes.TEXCOORD_0); - if (result.Length != positionsLength) + + var accessor = data.GLTF.accessors[primitives.attributes.TEXCOORD_0]; + if (accessor.type != "VEC2") { - throw new Exception("different length"); + throw new ArgumentException($"unknown TEXCOORD_0 type: {accessor.componentType}:{accessor.type}"); } - return result; + if (accessor.componentType == glComponentType.FLOAT) + { + var result = data.GetArrayFromAccessor(primitives.attributes.TEXCOORD_0); + if (result.Length != positionsLength) + { + throw new Exception("different length"); + } + + return result; + } + if (accessor.componentType == glComponentType.UNSIGNED_SHORT) + { + // KHR_mesh_quantization + var src = data.GetArrayFromAccessor(primitives.attributes.TEXCOORD_0); + var array = data.NativeArrayManager.CreateNativeArray(src.Length); + for (int i = 0; i < src.Length; ++i) + { + var v = src[i]; + array[i] = new Vector2(v.x, v.y); + } + return array; + } + else + { + throw new ArgumentException($"unknown TEXCOORD_0 type: {accessor.componentType}:{accessor.type}"); + } } public static NativeArray? GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs new file mode 100644 index 000000000..73b6f4841 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; + +namespace UniGLTF +{ + [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] + public readonly struct SByte4 : IEquatable + { + public readonly sbyte x; + public readonly sbyte y; + public readonly sbyte z; + public readonly sbyte w; + public SByte4(sbyte _x, sbyte _y, sbyte _z, sbyte _w) + { + x = _x; + y = _y; + z = _z; + w = _w; + } + + public bool Equals(SByte4 other) + { + return x == other.x && y == other.y && z == other.z && w == other.w; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs.meta new file mode 100644 index 000000000..64eaedcd0 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/SByte4.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4d60f1d5b95391e448bd511699ebc64e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs new file mode 100644 index 000000000..34b74644b --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.InteropServices; + +namespace UniGLTF +{ + [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] + public readonly struct UShort2 : IEquatable + { + public readonly ushort x; + public readonly ushort y; + + public UShort2(ushort _x, ushort _y) + { + x = _x; + y = _y; + } + + public bool Equals(UShort2 other) + { + return x == other.x && y == other.y; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs.meta new file mode 100644 index 000000000..dc4606cce --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort2.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 245b4464c9ff77642bd3e43db042abea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: