diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs new file mode 100644 index 000000000..6b79293c6 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs @@ -0,0 +1,24 @@ +using System; +using System.Runtime.InteropServices; + +namespace UniGLTF +{ + [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] + public readonly struct Byte3 : IEquatable + { + public readonly byte x; + public readonly byte y; + public readonly byte z; + public Byte3(byte _x, byte _y, byte _z) + { + x = _x; + y = _y; + z = _z; + } + + public bool Equals(Byte3 other) + { + return x == other.x && y == other.y && z == other.z; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs.meta new file mode 100644 index 000000000..8f28a2d50 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/Byte3.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a3aeebc68fc223f47801acd181ed116a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs index 17f5fe0c5..860abb4ca 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshIO/PrimitiveExtensions.cs @@ -146,11 +146,129 @@ namespace UniGLTF return result; } + /// + /// glTF 仕様では VEC3/VEC4 x float/unsigned byte normalized/unsigned short normalized + /// がある。 + /// public static NativeArray? GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength) { if (!HasColor(primitives)) return null; - switch (data.GLTF.accessors[primitives.attributes.COLOR_0].TypeCount) + var accessor = data.GLTF.accessors[primitives.attributes.COLOR_0]; + switch (accessor.componentType) + { + case glComponentType.UNSIGNED_BYTE: + return GetColorsUInt8(primitives, data, positionsLength); + case glComponentType.UNSIGNED_SHORT: + return GetColorsUInt16(primitives, data, positionsLength); + case glComponentType.FLOAT: + return GetColorsFloat(primitives, data, positionsLength); + default: + throw new NotImplementedException( + $"unknown color type {accessor.componentType}"); + } + } + + /// unsigned byte normalized => f = c / 255.0 + public static NativeArray? GetColorsUInt8(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasColor(primitives)) return null; + + var accessor = data.GLTF.accessors[primitives.attributes.COLOR_0]; + switch (accessor.TypeCount) + { + case 3: + { + var vec3Color = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (vec3Color.Length != positionsLength) + { + throw new Exception("different length"); + } + var colors = data.NativeArrayManager.CreateNativeArray(vec3Color.Length); + + for (var index = 0; index < vec3Color.Length; index++) + { + var color = vec3Color[index]; + colors[index] = new Color(color.x / 255.0f, color.y / 255.0f, color.z / 255.0f); + } + return colors; + } + + case 4: + { + var vec4Color = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (vec4Color.Length != positionsLength) + { + throw new Exception("different length"); + } + var colors = data.NativeArrayManager.CreateNativeArray(vec4Color.Length); + + for (var index = 0; index < vec4Color.Length; index++) + { + var color = vec4Color[index]; + colors[index] = new Color(color.x / 255.0f, color.y / 255.0f, color.z / 255.0f, color.w / 255.0f); + } + return colors; + } + + default: + throw new NotImplementedException($"unknown color type {accessor.type}"); + } + } + + /// unsigned short normalized => c = round(f * 65535.0) + public static NativeArray? GetColorsUInt16(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasColor(primitives)) return null; + + var accessor = data.GLTF.accessors[primitives.attributes.COLOR_0]; + switch (accessor.TypeCount) + { + case 3: + { + var vec3Color = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (vec3Color.Length != positionsLength) + { + throw new Exception("different length"); + } + var colors = data.NativeArrayManager.CreateNativeArray(vec3Color.Length); + + for (var index = 0; index < vec3Color.Length; index++) + { + var color = vec3Color[index]; + colors[index] = new Color(color.x / 65535.0f, color.y / 65535.0f, color.z / 65535.0f); + } + return colors; + } + + case 4: + { + var vec4Color = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); + if (vec4Color.Length != positionsLength) + { + throw new Exception("different length"); + } + var colors = data.NativeArrayManager.CreateNativeArray(vec4Color.Length); + + for (var index = 0; index < vec4Color.Length; index++) + { + var color = vec4Color[index]; + colors[index] = new Color(color.x / 65535.0f, color.y / 65535.0f, color.z / 65535.0f, color.w / 65535.0f); + } + return colors; + } + + default: + throw new NotImplementedException($"unknown color type {accessor.type}"); + } + } + + public static NativeArray? GetColorsFloat(this glTFPrimitives primitives, GltfData data, int positionsLength) + { + if (!HasColor(primitives)) return null; + + var accessor = data.GLTF.accessors[primitives.attributes.COLOR_0]; + switch (accessor.TypeCount) { case 3: { @@ -166,17 +284,17 @@ namespace UniGLTF var color = vec3Color[index]; colors[index] = new Color(color.x, color.y, color.z); } - return colors; } + case 4: var result = data.GetArrayFromAccessor(primitives.attributes.COLOR_0); if (result.Length != positionsLength) { throw new Exception("different length"); } - return result; + default: throw new NotImplementedException( $"unknown color type {data.GLTF.accessors[primitives.attributes.COLOR_0].type}"); diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs new file mode 100644 index 000000000..ce80edd3c --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs @@ -0,0 +1,25 @@ +using System; +using System.Runtime.InteropServices; + +namespace UniGLTF +{ + [Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)] + public readonly struct UShort3 : IEquatable + { + public readonly ushort x; + public readonly ushort y; + public readonly ushort z; + + public UShort3(ushort _x, ushort _y, ushort _z) + { + x = _x; + y = _y; + z = _z; + } + + public bool Equals(UShort3 other) + { + return x == other.x && y == other.y && z == other.z; + } + } +} diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs.meta new file mode 100644 index 000000000..485f3db62 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/UShort3.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 33180f1228cb5fc4cb666ed60c65264c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: