diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs
new file mode 100644
index 000000000..b20a94a21
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace UniGLTF
+{
+ ///
+ /// JOINTS_0 の byte4 もしくは ushort4 に対するアクセスを提供する
+ ///
+ public static class JointsAccessor
+ {
+ public delegate (ushort x, ushort y, ushort z, ushort w) Getter(int index);
+
+ public static (Getter, int) GetAccessor(glTF gltf, int accessorIndex)
+ {
+ var gltfAccessor = gltf.accessors[accessorIndex];
+ switch (gltfAccessor.componentType)
+ {
+ case glComponentType.UNSIGNED_BYTE:
+ {
+ var array = gltf.GetArrayFromAccessor(accessorIndex);
+ Getter getter = (i) =>
+ {
+ var value = array[i];
+ return (value.x, value.y, value.z, value.w);
+ };
+ return (getter, array.Length);
+ }
+
+ case glComponentType.UNSIGNED_SHORT:
+ {
+ var array = gltf.GetArrayFromAccessor(accessorIndex);
+ Getter getter = (i) =>
+ {
+ var value = array[i];
+ return (value.x, value.y, value.z, value.w);
+ };
+ return (getter, array.Length);
+ }
+ }
+
+ throw new NotImplementedException($"JOINTS_0 not support {gltfAccessor.componentType}");
+ }
+ }
+}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs.meta
new file mode 100644
index 000000000..be1ea71aa
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/JointsAccessor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: c577e942203a0694dbd7dfdbd2b5b4e5
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs
index 248798737..8d6a762c5 100644
--- a/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/MeshImporter.cs
@@ -98,49 +98,21 @@ namespace UniGLTF
}
}
- delegate ushort Getter(int index, int component);
- static (Getter, int) GetAccessor(glTF gltf, int accessorIndex)
+
+ public static BoneWeight NormalizeBoneWeight(BoneWeight src)
{
- var gltfAccessor = gltf.accessors[accessorIndex];
- switch (gltfAccessor.componentType)
+ var sum = src.weight0 + src.weight1 + src.weight2 + src.weight3;
+ if (sum == 0)
{
- case glComponentType.UNSIGNED_BYTE:
- {
- var array = gltf.GetArrayFromAccessor(accessorIndex);
- Getter getter = (i, j) =>
- {
- switch (j)
- {
- case 0: return array[i].x;
- case 1: return array[i].y;
- case 2: return array[i].z;
- case 3: return array[i].w;
- default: throw new Exception();
- }
- };
- return (getter, array.Length);
- }
-
- case glComponentType.UNSIGNED_SHORT:
- {
- var array = gltf.GetArrayFromAccessor(accessorIndex);
- Getter getter = (i, j) =>
- {
- switch (j)
- {
- case 0: return array[i].x;
- case 1: return array[i].y;
- case 2: return array[i].z;
- case 3: return array[i].w;
- default: throw new Exception();
- }
- };
- return (getter, array.Length);
- }
+ return src;
}
-
- throw new Exception();
+ var f = 1.0f / sum;
+ src.weight0 *= f;
+ src.weight1 *= f;
+ src.weight2 *= f;
+ src.weight3 *= f;
+ return src;
}
///
@@ -239,32 +211,37 @@ namespace UniGLTF
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
- var (joints0, length) = GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
- var weights0 = ctx.GLTF.GetArrayFromAccessor(prim.attributes.WEIGHTS_0).Select(x => x.One()).ToArray();
- if (length != positions.Length)
+ var (joints0, jointsLength) = JointsAccessor.GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
+ var (weights0, weightsLength) = WeightsAccessor.GetAccessor(ctx.GLTF, prim.attributes.WEIGHTS_0);
+ if (jointsLength != positions.Length)
{
throw new Exception("different length");
}
- if (weights0.Length != positions.Length)
+ if (weightsLength != positions.Length)
{
throw new Exception("different length");
}
FillZero(m_boneWeights, fillLength);
- for (int j = 0; j < length; ++j)
+ for (int j = 0; j < jointsLength; ++j)
{
var bw = new BoneWeight();
+
+ var joints = joints0(j);
+ var weights = weights0(j);
- bw.boneIndex0 = joints0(j, 0);
- bw.weight0 = weights0[j].x;
+ bw.boneIndex0 = joints.x;
+ bw.weight0 = weights.x;
- bw.boneIndex1 = joints0(j, 1);
- bw.weight1 = weights0[j].y;
+ bw.boneIndex1 = joints.y;
+ bw.weight1 = weights.y;
- bw.boneIndex2 = joints0(j, 2);
- bw.weight2 = weights0[j].z;
+ bw.boneIndex2 = joints.z;
+ bw.weight2 = weights.z;
- bw.boneIndex3 = joints0(j, 3);
- bw.weight3 = weights0[j].w;
+ bw.boneIndex3 = joints.w;
+ bw.weight3 = weights.w;
+
+ bw = NormalizeBoneWeight(bw);
m_boneWeights.Add(bw);
}
@@ -406,29 +383,30 @@ namespace UniGLTF
// skin
if (prim.attributes.JOINTS_0 != -1 && prim.attributes.WEIGHTS_0 != -1)
{
- var (joints0, length) = GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
- var weights0 = ctx.GLTF.GetArrayFromAccessor(prim.attributes.WEIGHTS_0);
- for (int i = 0; i < weights0.Length; ++i)
- {
- weights0[i] = weights0[i].One();
- }
+ var (joints0, jointsLength) = JointsAccessor.GetAccessor(ctx.GLTF, prim.attributes.JOINTS_0);
+ var (weights0, weightsLength) = WeightsAccessor.GetAccessor(ctx.GLTF, prim.attributes.WEIGHTS_0);
- for (int j = 0; j < length; ++j)
+ for (int j = 0; j < jointsLength; ++j)
{
var bw = new BoneWeight();
+
+ var joints = joints0(j);
+ var weights = weights0(j);
- bw.boneIndex0 = joints0(j, 0);
- bw.weight0 = weights0[j].x;
+ bw.boneIndex0 = joints.x;
+ bw.weight0 = weights.x;
- bw.boneIndex1 = joints0(j, 1);
- bw.weight1 = weights0[j].y;
+ bw.boneIndex1 = joints.y;
+ bw.weight1 = weights.y;
- bw.boneIndex2 = joints0(j, 2);
- bw.weight2 = weights0[j].z;
+ bw.boneIndex2 = joints.z;
+ bw.weight2 = weights.z;
- bw.boneIndex3 = joints0(j, 3);
- bw.weight3 = weights0[j].w;
+ bw.boneIndex3 = joints.w;
+ bw.weight3 = weights.w;
+ bw = NormalizeBoneWeight(bw);
+
m_boneWeights.Add(bw);
}
}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs
new file mode 100644
index 000000000..7a264b070
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs
@@ -0,0 +1,56 @@
+using System;
+using UnityEngine;
+
+namespace UniGLTF
+{
+ public static class WeightsAccessor
+ {
+ ///
+ /// WEIGHTS_0 の byte4 もしくは ushort4 もしくは float4 に対するアクセスを提供する
+ ///
+ public delegate (float x, float y, float z, float w) Getter(int index);
+
+ public static (Getter, int) GetAccessor(glTF gltf, int accessorIndex)
+ {
+ var gltfAccessor = gltf.accessors[accessorIndex];
+ switch (gltfAccessor.componentType)
+ {
+ case glComponentType.UNSIGNED_BYTE:
+ {
+ var array = gltf.GetArrayFromAccessor(accessorIndex);
+ Getter getter = (i) =>
+ {
+ var value = array[i];
+ var inv = 1.0f / byte.MaxValue;
+ return (value.x*inv, value.y*inv, value.z*inv, value.w*inv);
+ };
+ return (getter, array.Length);
+ }
+
+ case glComponentType.UNSIGNED_SHORT:
+ {
+ var array = gltf.GetArrayFromAccessor(accessorIndex);
+ Getter getter = (i) =>
+ {
+ var value = array[i];
+ var inv = 1.0f / ushort.MaxValue;
+ return (value.x*inv, value.y*inv, value.z*inv, value.w*inv);
+ };
+ return (getter, array.Length);
+ }
+
+ case glComponentType.FLOAT:
+ {
+ var array = gltf.GetArrayFromAccessor(accessorIndex);
+ Getter getter = (i) =>
+ {
+ var value = array[i];
+ return (value.x, value.y, value.z, value.w);
+ };
+ return (getter, array.Length);
+ }
+ }
+
+ throw new NotImplementedException($"WEIGHTS_0 not support {gltfAccessor.componentType}"); }
+ }
+}
diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs.meta
new file mode 100644
index 000000000..0af30984a
--- /dev/null
+++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/WeightsAccessor.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 606f2dd4678c3a84e874097526fdc6c7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs b/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs
new file mode 100644
index 000000000..840fd67f7
--- /dev/null
+++ b/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using NUnit.Framework;
+
+namespace UniGLTF
+{
+ public class MeshTests
+ {
+ [Test]
+ public void AccessorTest()
+ {
+ byte[] bytes = default;
+ using(var ms = new MemoryStream())
+ using(var w = new BinaryWriter(ms))
+ {
+ w.Write(1.0f);
+ w.Write(2.0f);
+ w.Write(3.0f);
+ w.Write(4.0f);
+ w.Write(5.0f);
+ w.Write(6.0f);
+ w.Write(7.0f);
+ w.Write(8.0f);
+ bytes = ms.ToArray();
+ }
+ var storage = new SimpleStorage(new ArraySegment(bytes));
+
+ var gltf = new glTF
+ {
+ buffers=new List
+ {
+ new glTFBuffer
+ {
+ }
+ },
+ bufferViews = new List
+ {
+ new glTFBufferView{
+ buffer=0,
+ byteLength=32,
+ byteOffset=0,
+ }
+ },
+ accessors = new List
+ {
+ new glTFAccessor{
+ bufferView = 0,
+ componentType=glComponentType.FLOAT,
+ count=2,
+ byteOffset=0,
+ type="VEC4",
+ }
+ }
+ };
+ gltf.buffers[0].OpenStorage(storage);
+
+ var (getter, len) = WeightsAccessor.GetAccessor(gltf, 0);
+ Assert.AreEqual((1.0f, 2.0f, 3.0f, 4.0f), getter(0));
+ Assert.AreEqual((5.0f, 6.0f, 7.0f, 8.0f), getter(1));
+ }
+ }
+}
diff --git a/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs.meta
new file mode 100644
index 000000000..4f4af94e9
--- /dev/null
+++ b/Assets/UniGLTF/Tests/UniGLTF/MeshTests.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 319f54b4f10c93a4d80670e424f4fe34
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: