Skip to content

Commit b9f9ee8

Browse files
authored
Add 8 bone export support for Babylon->GLTF (#955)
1 parent e29f119 commit b9f9ee8

File tree

5 files changed

+88
-9
lines changed

5 files changed

+88
-9
lines changed

SharedProjects/Babylon2GLTF/GLTFExporter.Mesh.cs

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,41 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
104104
{
105105
// In babylon, the 4 bones indices are stored in a single int
106106
// Each bone index is 8-bit offset from the next
107+
ushort[] unpackBabylonBonesToArray (uint babylonBoneIndices)
108+
{
109+
uint bone3 = babylonBoneIndices >> 24;
110+
uint bone2 = (babylonBoneIndices << 8) >> 24;
111+
uint bone1 = (babylonBoneIndices << 16) >> 24;
112+
uint bone0 = (babylonBoneIndices << 24) >> 24;
113+
babylonBoneIndices -= bone0 << 0;
114+
return new ushort[] { (ushort)bone0, (ushort)bone1, (ushort)bone2, (ushort)bone3 };
115+
}
116+
107117
uint bonesIndicesMerged = (uint)meshData.matricesIndices[indexVertex];
108-
uint bone3 = bonesIndicesMerged >> 24;
109-
uint bone2 = (bonesIndicesMerged << 8 ) >> 24;
110-
uint bone1 = (bonesIndicesMerged << 16) >> 24;
111-
uint bone0 = (bonesIndicesMerged << 24) >> 24;
112-
bonesIndicesMerged -= bone0 << 0;
113-
var bonesIndicesArray = new ushort[] { (ushort)bone0, (ushort)bone1, (ushort)bone2, (ushort)bone3 };
114-
globalVertex.BonesIndices = bonesIndicesArray;
118+
globalVertex.BonesIndices = unpackBabylonBonesToArray(bonesIndicesMerged);
115119
globalVertex.BonesWeights = ArrayExtension.SubArrayFromEntity(meshData.matricesWeights, indexVertex, 4);
120+
void clearBoneUnusedIndices(ushort[] indices, float[] weights)
121+
{
122+
for (int i = 0; i < indices.Length; ++i)
123+
{
124+
// Zero out indices of unused joint weights to avoid ACCESSOR_JOINTS_USED_ZERO_WEIGHT.
125+
if (MathUtilities.IsAlmostEqualTo(weights[i], 0, float.Epsilon))
126+
{
127+
indices[i] = 0;
128+
}
129+
}
130+
}
131+
132+
clearBoneUnusedIndices(globalVertex.BonesIndices, globalVertex.BonesWeights);
133+
134+
if (hasBonesExtra)
135+
{
136+
uint bonesIndicesExtraMerged = (uint)meshData.matricesIndicesExtra[indexVertex];
137+
globalVertex.BonesIndicesExtra = unpackBabylonBonesToArray(bonesIndicesExtraMerged);
138+
globalVertex.BonesWeightsExtra = ArrayExtension.SubArrayFromEntity(meshData.matricesWeightsExtra, indexVertex, 4);
139+
140+
clearBoneUnusedIndices(globalVertex.BonesIndicesExtra, globalVertex.BonesWeightsExtra);
141+
}
116142
}
117143

118144
globalVertices.Add(globalVertex);
@@ -367,6 +393,11 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
367393

368394
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.JOINTS_0.ToString(), tmpGltfMeshPrimitive.attributes[GLTFMeshPrimitive.Attribute.JOINTS_0.ToString()]);
369395
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.WEIGHTS_0.ToString(), tmpGltfMeshPrimitive.attributes[GLTFMeshPrimitive.Attribute.WEIGHTS_0.ToString()]);
396+
if (hasBonesExtra)
397+
{
398+
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.JOINTS_1.ToString(), tmpGltfMeshPrimitive.attributes[GLTFMeshPrimitive.Attribute.JOINTS_1.ToString()]);
399+
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.WEIGHTS_1.ToString(), tmpGltfMeshPrimitive.attributes[GLTFMeshPrimitive.Attribute.WEIGHTS_1.ToString()]);
400+
}
370401
sharedSkinnedMeshesByOriginal[tmpGltfMesh].Add(gltfMesh);
371402
}
372403
else
@@ -387,6 +418,23 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
387418
joints.ForEach(n => accessorJoints.bytesList.AddRange(BitConverter.GetBytes(n)));
388419
accessorJoints.count = globalVerticesSubMesh.Count;
389420

421+
if (hasBonesExtra)
422+
{
423+
// --- Joints Extra ---
424+
var accessorJointsExtra = GLTFBufferService.Instance.CreateAccessor(
425+
gltf,
426+
GLTFBufferService.Instance.GetBufferViewUnsignedShortVec4(gltf, buffer),
427+
"accessorJointsExtra",
428+
GLTFAccessor.ComponentType.UNSIGNED_SHORT,
429+
GLTFAccessor.TypeEnum.VEC4
430+
);
431+
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.JOINTS_1.ToString(), accessorJointsExtra.index);
432+
// Populate accessor
433+
List<ushort> jointsExtra = globalVerticesSubMesh.SelectMany(v => new[] { v.BonesIndicesExtra[0], v.BonesIndicesExtra[1], v.BonesIndicesExtra[2], v.BonesIndicesExtra[3] }).ToList();
434+
jointsExtra.ForEach(n => accessorJointsExtra.bytesList.AddRange(BitConverter.GetBytes(n)));
435+
accessorJointsExtra.count = globalVerticesSubMesh.Count;
436+
}
437+
390438
// --- Weights ---
391439
var accessorWeights = GLTFBufferService.Instance.CreateAccessor(
392440
gltf,
@@ -400,6 +448,23 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
400448
List<float> weightBones = globalVerticesSubMesh.SelectMany(v => new[] { v.BonesWeights[0], v.BonesWeights[1], v.BonesWeights[2], v.BonesWeights[3] }).ToList();
401449
weightBones.ForEach(n => accessorWeights.bytesList.AddRange(BitConverter.GetBytes(n)));
402450
accessorWeights.count = globalVerticesSubMesh.Count;
451+
452+
if (hasBonesExtra)
453+
{
454+
// --- Weights Extra ---
455+
var accessorWeightsExtra = GLTFBufferService.Instance.CreateAccessor(
456+
gltf,
457+
GLTFBufferService.Instance.GetBufferViewFloatVec4(gltf, buffer),
458+
"accessorWeightsExtra",
459+
GLTFAccessor.ComponentType.FLOAT,
460+
GLTFAccessor.TypeEnum.VEC4
461+
);
462+
meshPrimitive.attributes.Add(GLTFMeshPrimitive.Attribute.WEIGHTS_1.ToString(), accessorWeightsExtra.index);
463+
// Populate accessor
464+
List<float> weightBonesExtra = globalVerticesSubMesh.SelectMany(v => new[] { v.BonesWeightsExtra[0], v.BonesWeightsExtra[1], v.BonesWeightsExtra[2], v.BonesWeightsExtra[3] }).ToList();
465+
weightBonesExtra.ForEach(n => accessorWeightsExtra.bytesList.AddRange(BitConverter.GetBytes(n)));
466+
accessorWeightsExtra.count = globalVerticesSubMesh.Count;
467+
}
403468
}
404469
}
405470

SharedProjects/Babylon2GLTF/GLTFGlobalVertex.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public class GLTFGlobalVertex
1111
public BabylonVector2 UV2 { get; set; }
1212
public float[] Color { get; set; }
1313
public ushort[] BonesIndices { get; set; }
14+
public ushort[] BonesIndicesExtra { get; set; }
1415
public float[] BonesWeights { get; set; }
16+
public float[] BonesWeightsExtra { get; set; }
1517
}
1618
}

SharedProjects/BabylonExport.Entities/BabylonMesh.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ public interface IBabylonMeshData
1818
float[] uvs6 { get; set; }
1919
float[] colors { get; set; }
2020
int[] matricesIndices { get; set; }
21+
int[] matricesIndicesExtra { get; set; }
2122
float[] matricesWeights { get; set; }
23+
float[] matricesWeightsExtra { get; set; }
2224
int[] indices { get; set; }
2325
}
2426

SharedProjects/BabylonExport.Entities/BabylonVertexData.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,15 @@ public class BabylonVertexData : IBabylonMeshData
4949
[DataMember]
5050
public int[] matricesIndices { get; set; }
5151

52+
[DataMember]
53+
public int[] matricesIndicesExtra { get; set; }
54+
5255
[DataMember]
5356
public float[] matricesWeights { get; set; }
54-
57+
58+
[DataMember]
59+
public float[] matricesWeightsExtra { get; set; }
60+
5561
[DataMember]
5662
public int[] indices { get; set; }
5763
#endregion
@@ -76,7 +82,9 @@ public BabylonVertexData(IBabylonMeshData data)
7682
uvs6 = data.uvs6;
7783
colors = data.colors;
7884
matricesIndices = data.matricesIndices;
85+
matricesIndicesExtra = data.matricesIndicesExtra;
7986
matricesWeights = data.matricesWeights;
87+
matricesWeightsExtra = data.matricesWeightsExtra;
8088
indices = data.indices;
8189
}
8290
}

SharedProjects/GltfExport.Entities/GLTFMeshPrimitive.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ public enum Attribute
2626
TEXCOORD_1,
2727
COLOR_0,
2828
JOINTS_0,
29-
WEIGHTS_0
29+
JOINTS_1,
30+
WEIGHTS_0,
31+
WEIGHTS_1
3032
}
3133

3234
[DataMember(IsRequired = true)]

0 commit comments

Comments
 (0)