213 lines
8.5 KiB
C#
213 lines
8.5 KiB
C#
using System;
|
|
using Unity.Collections;
|
|
using UnityEngine;
|
|
|
|
namespace UniGLTF
|
|
{
|
|
internal static class PrimitiveExtensions
|
|
{
|
|
public static bool HasNormal(this glTFPrimitives primitives) => primitives.attributes.NORMAL != -1;
|
|
public static bool HasTexCoord0(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_0 != -1;
|
|
public static bool HasTexCoord1(this glTFPrimitives primitives) => primitives.attributes.TEXCOORD_1 != -1;
|
|
public static bool HasSkin(this glTFPrimitives primitives) => primitives.attributes.JOINTS_0 != -1 && primitives.attributes.WEIGHTS_0 != -1;
|
|
public static bool HasColor(this glTFPrimitives primitives) => primitives.attributes.COLOR_0 != -1;
|
|
|
|
public static NativeArray<Vector3> GetPositions(this glTFPrimitives primitives, GltfData data)
|
|
{
|
|
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 accessor = data.GLTF.accessors[primitives.attributes.NORMAL];
|
|
if (accessor.type != "VEC3")
|
|
{
|
|
throw new ArgumentException($"unknown NORMAL type: {accessor.componentType}:{accessor.type}");
|
|
}
|
|
|
|
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 accessor = data.GLTF.accessors[primitives.attributes.TEXCOORD_0];
|
|
if (accessor.type != "VEC2")
|
|
{
|
|
throw new ArgumentException($"unknown TEXCOORD_0 type: {accessor.componentType}:{accessor.type}");
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (!HasTexCoord1(primitives)) return null;
|
|
var result = data.GetArrayFromAccessor<Vector2>(primitives.attributes.TEXCOORD_1);
|
|
if (result.Length != positionsLength)
|
|
{
|
|
throw new Exception("different length");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public static NativeArray<Color>? GetColors(this glTFPrimitives primitives, GltfData data, int positionsLength)
|
|
{
|
|
if (!HasColor(primitives)) return null;
|
|
|
|
switch (data.GLTF.accessors[primitives.attributes.COLOR_0].TypeCount)
|
|
{
|
|
case 3:
|
|
{
|
|
var vec3Color = data.GetArrayFromAccessor<Vector3>(primitives.attributes.COLOR_0);
|
|
if (vec3Color.Length != positionsLength)
|
|
{
|
|
throw new Exception("different length");
|
|
}
|
|
var colors = data.NativeArrayManager.CreateNativeArray<Color>(vec3Color.Length);
|
|
|
|
for (var index = 0; index < vec3Color.Length; index++)
|
|
{
|
|
var color = vec3Color[index];
|
|
colors[index] = new Color(color.x, color.y, color.z);
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
case 4:
|
|
var result = data.GetArrayFromAccessor<Color>(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}");
|
|
}
|
|
}
|
|
|
|
public static JointsAccessor.Getter GetJoints(this glTFPrimitives primitives, GltfData data, int positionsLength)
|
|
{
|
|
// skin
|
|
if (!HasSkin(primitives)) return null;
|
|
var (getter, length) = JointsAccessor.GetAccessor(data, primitives.attributes.JOINTS_0);
|
|
if (length != positionsLength)
|
|
{
|
|
throw new Exception("different length");
|
|
}
|
|
|
|
return getter;
|
|
|
|
}
|
|
|
|
public static WeightsAccessor.Getter GetWeights(this glTFPrimitives primitives, GltfData data, int positionsLength)
|
|
{
|
|
// skin
|
|
if (!HasSkin(primitives)) return null;
|
|
var (getter, length) = WeightsAccessor.GetAccessor(data, primitives.attributes.WEIGHTS_0);
|
|
if (length != positionsLength)
|
|
{
|
|
throw new Exception("different length");
|
|
}
|
|
|
|
return getter;
|
|
}
|
|
}
|
|
} |