Initial support for KHR_mesh_quantization

This commit is contained in:
ousttrue 2022-05-10 14:56:03 +09:00
parent 3d60280188
commit bf06bcb74e
6 changed files with 173 additions and 11 deletions

View File

@ -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

View File

@ -14,31 +14,124 @@ namespace UniGLTF
public static NativeArray<Vector3> GetPositions(this glTFPrimitives primitives, GltfData data)
{
return data.GetArrayFromAccessor<Vector3>(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<Vector3>(primitives.attributes.POSITION);
}
else if (accessor.componentType == glComponentType.UNSIGNED_SHORT)
{
// KHR_mesh_quantization
// not UShort3 for 4byte alignment !
var src = data.GetArrayFromAccessor<UShort4>(primitives.attributes.POSITION);
var array = data.NativeArrayManager.CreateNativeArray<Vector3>(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<Vector3>? GetNormals(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasNormal(primitives)) return null;
var result = data.GetArrayFromAccessor<Vector3>(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<Vector3>(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<SByte4>(primitives.attributes.NORMAL);
var array = data.NativeArrayManager.CreateNativeArray<Vector3>(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<Vector2>? GetTexCoords0(this glTFPrimitives primitives, GltfData data, int positionsLength)
{
if (!HasTexCoord0(primitives)) return null;
var result = data.GetArrayFromAccessor<Vector2>(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<Vector2>(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<UShort2>(primitives.attributes.TEXCOORD_0);
var array = data.NativeArrayManager.CreateNativeArray<Vector2>(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<Vector2>? GetTexCoords1(this glTFPrimitives primitives, GltfData data, int positionsLength)

View File

@ -0,0 +1,26 @@
using System;
using System.Runtime.InteropServices;
namespace UniGLTF
{
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct SByte4 : IEquatable<SByte4>
{
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;
}
}
}

View File

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

View File

@ -0,0 +1,23 @@
using System;
using System.Runtime.InteropServices;
namespace UniGLTF
{
[Serializable, StructLayout(LayoutKind.Sequential, Pack = 1)]
public readonly struct UShort2 : IEquatable<UShort2>
{
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;
}
}
}

View File

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